I have set up my models to use a polymorphic Image model. This is working fine, however I am wondering if it is possible to change the :styles setting for each model. Found some examples using STI (Model < Image) However this is not an option for me, because I am using a has_many relation.
Art
has_many :images, :as => :imageable
Image
belongs_to :imageable, :polymorphic => true
has_attached_file :file, :styles => { :thumb => "150x150>", :normal => "492x600>"}
#Change this setting depending on model
I tried starting up a debugger inside the Proc method. Only fields related to the attached file is populated:
run'irb(Image):006:0> a.instance => #<Image id: nil, created_at: nil, updated_at: nil, imageable_id: nil, imageable_type: nil, file_file_name: "IMG_9834.JPG", file_content_type: "image/jpeg", file_file_size: 151326, file_updated_at: "2010-10-30 08:40:23">
This is the object from ImageController#create
ImageController#create
@image => #<Image id: nil, created_at: nil, updated_at: nil, imageable_id: 83, imageable_type: "Art", file_file_name: "IMG_9834.JPG", file_content_type: "image/jpeg", file_file_size: 151326, file_updated_at: "2010-10-30 08:32:49">
I am using paperclip (2.3.5) and Rails 3.0.1. No matter what I do the a.instance object is the image with only the fields related to the attachment populated. Any ideas?
After reading a lot on the Paperclip forum I don't believe it's possible to access the instance before it has been saved. You can onlye see the Paperclip stuff and that's it.
I got around this problem by presaving the image from the Image controller with a before filter - without the attachment
before_filter :presave_image, :only => :create
...
private
def presave_image
if @image.id.nil? # Save if new record / Arts controller sets @image
@image = Image.new(:imageable_type => params[:image][:imageable_type], :imageable_id => params[:image][:imageable_id])
@image.save(:validate => false)
@image.file = params[:file] # Set to params[:image][:file] if you edit an image.
end
end
I am really late to the party here, but I wanted to clarify something about accessing model data for anyone else that happens on to this thread. I just faced this issue while using Paperclip to apply watermarks based on data from the model, and got it working after a lot of investigation.
You said:
After reading a lot on the Paperclip forum I don't believe it's possible to access the instance before it has been saved. You can only see the Paperclip stuff and that's it.
In fact, you can see the model data if it's been set in the object before your attachment is assigned!
Your paperclip processors and whatnot are invoked when the attachment in your model is assigned. If you rely on mass assignment (or not, actually), as soon as the attachment is assigned a value, paperclip does its thing.
Here's how I solved the problem:
In my model with the attachment (Photo), I made all the attributes EXCEPT the attachment attr_accessible
, thereby keeping the attachment from being assigned during mass assignment.
class Photo < ActiveRecord::Base
attr_accessible :attribution, :latitude, :longitude, :activity_id, :seq_no, :approved, :caption
has_attached_file :picture, ...
...
end
In my controller's create method (for example) I pulled out the picture
from the params
, and then created the object. (It's probably not necessary to remove the picture from params
, since the attr_accessible
statement should prevent picture
from being assgined, but it doesn't hurt). Then I assign the picture
attribute, after all the other attributes of the photo object have been setup.
def create
picture = params[:photo].delete(:picture)
@photo = Photo.new(params[:photo])
@photo.picture = picture
@photo.save
...
end
In my case, one of the styles for picture calls for applying a watermark, which is the text string held in the attribution
attribute. Before I made these code changes, the attribution string was never applied, and in the watermark code, attachment.instance.attribution
was always nil
. The changes summarized here made the entire model available inside the paperclip processors. The key is to assign your attachment attribute last.
Hope this helps someone.
I found the workaround to pickup styles on create.
The key is to implement before_post_process
and after_save
hooks.
class Image < ActiveRecord::Base
DEFAULT_STYLES = {
medium: "300x300>", thumb: "100x100>"
}
has_attached_file :file, styles: ->(file){ file.instance.styles }
validates_attachment_content_type :file, :content_type => /\Aimage\/.*\Z/
# Workaround to pickup styles from imageable model
# paperclip starts processing before all attributes are in the model
# so we start processing after saving
before_post_process ->{
!@file_reprocessed.nil?
}
after_save ->{
if !@file_reprocessed && (file_updated_at_changed? || imageable_type_changed?)
@file_reprocessed = true
file.reprocess!
end
}
belongs_to :imageable, polymorphic: true
def styles
if imageable_class.respond_to?(:image_styles)
imageable_class.image_styles
end || DEFAULT_STYLES
end
def imageable_class
imageable_type.constantize if imageable_type.present?
end
end
So you have to define image_styles class method in imageable_class In my case it was
class Property < ActiveRecord::Base
def self.image_styles
{
large: "570x380#",
thumb: "50x70#",
medium: "300x200#"
}
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With