开发者

How can I reference images in the asset pipeline from a model?

I have a model with a method to return a url to a person's avatar that looks like this:

 def avatar_url
   if self.avatar?
     self.avatar.url # This uses paperclip
   else
     "/images/avatars/none.png"
   end
 end

I'm in the midst of upgrading to 3.1, so now the hard-code开发者_开发百科d none image needs be referenced through the asset pipeline. In a controller or view, I would just wrap it in image_path(), but I don't have that option in the model. How can I generate the correct url to the image?


I struggled with getting this right for a while so I thought I'd post the answer here. Whilst the above works for a standard default image (i.e. same one for each paperclip style), if you need multiple default styles you need a different approach.

If you want to have the default url play nice with the asset pipeline and asset sync and want different default images per style then you need to generate the asset path without fingerprints otherwise you'll get lots of AssetNotPrecompiled errors.

Like so:

   :default_url => ActionController::Base.helpers.asset_path("/missing/:style.png", :digest => false)

or in your paperclip options:

   :default_url => lambda { |a| "#{a.instance.create_default_url}" }

and then an instance method in the model that has the paperclip attachment:

def create_default_url
   ActionController::Base.helpers.asset_path("/missing/:style.png", :digest => false)
end

In this case you can still use the interpolation (:style) but will have to turn off the asset fingerprinting/digest.

This all seems to work fine as long as you are syncing assets without the digest as well as those with the digest.


Personally, I don't think you should really be putting this default in a model, since it's a view detail. In your (haml) view:

= image_tag(@image.avatar_url || 'none.png')

Or, create your own helper and use it like so:

= avatar_or_default(@image)

When things like this are hard in rails, it's often a sign that it's not exactly right.


We solved this problem using draper: https://github.com/jcasimir/draper. Draper let us add a wrapper around our models (for use in views) that have access to helpers.


Paperclip has an option to specify default url

has_attached_file :avatar, :default_url => '/images/.../missing_:style.png'

You can use this to serve default image' in case user has not uploaded avatar.


Using rails active storage I solved this problem by doing this:

# Post.rb
def Post < ApplicationRecord
    has_one_attached :image

    def thumbnail
        self.image.attached? ? self.image.variant(resize: "150x150").processed.service_url : 'placeholder.png';
    end

    def medium
        self.image.attached? ? self.image.variant(resize: "300x300").processed.service_url : 'placeholder.png';
    end

    def large
        self.image.attached? ? self.image.variant(resize: "600x600").processed.service_url : 'placeholder.png';
    end
end

Then in your views simply call: <%= image_tag @post.thumbnail %>,

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜