How to share Paperclip code between models

I have several models that include Paperclip::Glue and have similar has_attached_file :image code.

What is a good way of sharing the code?

I created a module, and got Exception encountered: #<NoMethodError: undefined method 'class_attribute' for AttachedImage:Module> exception.

What does this mean?

I tried creating a common base model that the other models could inherit from:

class PaperclipImage
  include Paperclip::Glue
  include MongoMapper::Document

  STYLES = {}

  image_path = ''

  has_attached_file :image, 
      :styles  => self::STYLES,
      :path    => %w( development test ).include?( ENV[ 'RACK_ENV' ]) ? "public/#{ image_path }/:style/:id/:basename.:extension" : "#{ image_path }/:style/:id/:basename.:extension",

The subclasses have their own image_path, such as `image_path = 'images'`.

But this always uses the base class image_path, instead of the image_path of the subclass.

I tried the same approach with constants: `IMAGE_PATH` and `#{ self::IMAGE_PATH }` which has the same results, even though Ruby does apparently use the subclass constant:

So, none of that worked. Is there a good way to share common code across models that include Paperclip::Glue?

The problem is that the has_attached_file method is being called when the class is being parsed. At that time it is not yet attached to the model.

If you are using rails, try using ActiveSupport::Concern with a module

module HasAttachedImage
  extend ActiveSupport::Concern
  included do
    has_attached_file :image, 
    :styles  => self::STYLES,
    :path    => %w( development test ).include?( ENV[ 'RACK_ENV' ]) ? "public/#{ image_path }/:style ...

  #other methods here

When your models include the module, the code in the included block is called.

If you are not using rails, you could figure out a similar thing with Module#included

1 Like

Thanks, that is very helpful. I’ll give it a try.