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
class Banner < ActiveRecord::Base
belongs_to :banner_categoria
validates :banner_categoria_id ,{:presence =>{:message => "não informada"}}
has_attached_file :arquivo
after_initialize :init_attachment
def init_attachment
self.class.has_attached_file :arquivo,
:url => "/system/:class/:attachment/:id/:style/:basename.:extension",
:path => ":rails_root/public/system/:class/:attachment/:id/:style/:basename.:extension",
:styles => hash = {
:banner => {
:geometry => "#{self.banner_categoria.largura}x#{self.banner_categoria.altura}>",
:quality => 80
},
:thumb => "100x100#"
}
end
end
have the same problem in a production/staging server...BUT not in my local environment. I use same rails/paperclip versions in all servers (2.3.2 and 2.2.6)
After couple of hours of digging into source code of both, ActiveRecord
and Paperclip
, I think there's a solution involving a bit of monkey-patching hackery.
I haven't thoroughly tested it but seems to work for my humble needs.
Below is my config/initializers/activerecord_associations_patch.rb
:
module ActiveRecord
module Associations
class HasManyAssociation
def build_record(attributes)
if options[:as] && owner
# Unicorns
reflection.build_association({}) do |record|
set_owner_attributes(record)
unless foreign_key_for?(record)
record.public_send "#{options[:as]}=", owner
end
initialize_attributes(record)
record.assign_attributes(attributes)
end
else
# Classic Rails way
reflection.build_association(attributes) do |record|
initialize_attributes(record)
end
end
end
end
end
end
Since reflection
doesn't know our @owner
, it first assigns the attributes
which triggers call to record.#{instance}=
(i.e. Image#file=
), which in turn forwards it to #assign
and performs post_processing
hook, which in the end leads to calling styles
Proc
provided in has_attached_file
without polymorphic imageable
being set. huh…
I rewrote the method to build the record first and assign provided attributes later.
Also, it accounts for record#new_record?
in foreign_key_for?
check.
In this way attributes
are assigned once the record has been properly setup. At least i think so ;)
Cleaner solutions and constructive comments are most welcome :)
I've also met with the same problem and after searching for an elegant solution I didn't found anything "really" useful. So, here's my simple solution which seems alright for now; (tho I'm not sure if it has any downsides for the moment)
In model;
class Asset < ActiveRecord::Base
belongs_to :assetable, polymorphic: true
has_attached_file :attachment, path: ":rails_root/#{path}/assets/images/:style/:filename",
url: '/assets/images/:style/:filename',
styles: -> (a) { a.instance.send(:styles) }
private
def styles
raise 'Undefined assetable.' unless assetable
if assetable.class == Photo
{ small: 'x40', medium: '120x', large: '300x' }
elsif assetable.class == Avatar
{ small: 'x40', medium: '120x', large: '300x' }
else
raise "Styles for #{assetable.class} is not defined."
end
end
end
In controller;
@photo = Photo.new
@photo.build_image(assetable: @photo, attachment: params[:photo][:image_attributes][:attachment])
@photo.save