Paperclip :style depending on model (has_many polymorphic images)

后端 未结 10 948
醉梦人生
醉梦人生 2021-02-03 11:33

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

相关标签:
10条回答
  • 2021-02-03 12:20
    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

    0 讨论(0)
  • 2021-02-03 12:22

    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)

    0 讨论(0)
  • 2021-02-03 12:31

    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 :)

    0 讨论(0)
  • 2021-02-03 12:34

    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
    
    0 讨论(0)
提交回复
热议问题