sjbuysse
sjbuysse

Reputation: 4134

Where to define liquid method for :url from attached file

Posts on my blog have several pictures

class Post < ActiveRecord::Base
     has_many :pictures, dependent: :destroy
end

The pictures have an attached imagefile, I use the gem paperclip to manage this.

class Picture < ActiveRecord::Base
    belongs_to :post

    has_attached_file :image,
        :path => ":rails_root/public/images/:id/:filename",
        :url  => "/images/:id/:filename",
        styles: { medium: "300x300>", thumb: "100x100>"  } 

    do_not_validate_attachment_file_type :image
end

I can create image tags easily with <%= image_tag picture.image.url %> so picture.image.url returns the url where the image is stored. I'm trying to get this url as well with the liquid templating gem. I want to do something like

{% for picture in pictures %} 
<li style="background-image:'{{picture.image.url(:medium)}}';"></li>  
{% endfor %} 

I'm guessing I need a liquid method :url, but I have no model to write it (since image is an attached file, not a model). Does someone know how I could get the image url trough liquid?

Upvotes: 2

Views: 623

Answers (1)

EugZol
EugZol

Reputation: 6545

It seems that the easiest way to do that is to manually serialize your pictures:

# ruby code
Liquid::Template.parse(text).render("pictures" => @post.pictures.map{|p| {'id' => p.id, 'medium_image_url' => p.image.url(:medium)})

# liquid code
{% for picture in pictures %} 
  <li style="background-image:'{{picture.medium_image_url}}';"></li>  
{% endfor %}

If you want to separate serialization into separate module, you can move it to ActiveModel::Serializer or Liquid::Drop. ActiveModel::Serializer is a good decision if you also use JSON (or XML) serialization, otherwise Liquid::Drop is preferable choice (it was specifically made for serialization to liquid). Here is modified example from Liquid::Drop docs:

# Ruby code

class PictureDrop < Liquid::Drop
  def initialize(picture)
    @picture = picture
  end

  def id
    @picture["id"]
  end

  def image_urls
    {
      'medium' => @picture.image.url(:medium),
      'thumb' => @picture.image.url(:thumb)
    }
  end
end

markdown = Liquid::Template.parse(text).render("pictures" => @post.pictures.map{|p| PictureDrop.new(p)})

# liquid code

{% for picture in pictures %} 
    <li style="background-image:'{{picture.image_urls['medium']}}';"></li>  
{% endfor %} 

Upvotes: 1

Related Questions