Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic uploader with Carrierwave

I am using a single Image model to store information about images used by different other models (via a polymorphic association).

I'd like to change the uploader on this model depending on the model associated to have different versions for different models.

For example, if the imageable is a Place, the mounted uploader would be a PlaceUploader. And if there is no PlaceUploader, it would be the default ImageUploader.

At the moment I have:

class Image < ActiveRecord::Base
  belongs_to :imageable, polymorphic: true
  mount_uploader :image, ImageUploader
end

Ideally I'd like to have:

# This is not supported by CarrierWave, just a proof of concept
mount_uploader :image, -> { |model| "#{model.imageable.class.to_s}Uploader".constantize || ImageUploader }

Is there a way to achieve that? Or a better way to have different versions depending on the associated model?


Edit

I found another solution using one single ImageUploader:

class ImageUploader < BaseUploader

  version :thumb_place, if: :attached_to_place? do
    process resize_to_fill: [200, 200]
  end

  version :thumb_user, if: :attached_to_user? do
    process :bnw
    process resize_to_fill: [100, 100]
  end

  def method_missing(method, *args)
    # Define attached_to_#{model}?
    if m = method.to_s.match(/attached_to_(.*)\?/)
      model.imageable_type.underscore.downcase.to_sym == m[1].to_sym
    else
      super
    end
  end

end

As you can see my 2 versions are named thumb_place and thumb_user because if I name them both thumb only the first one will be considered (even if it doesn't fill the condition).

like image 706
TimPetricola Avatar asked Sep 19 '13 00:09

TimPetricola


1 Answers

I need to implement same logic that i have a single Image model and base on polymorphic association to mount different uploaders.

finally i come up below solution in Rails 5:

class Image < ApplicationRecord
  belongs_to :imageable, polymorphic: true

  before_save :mount_uploader_base_on_imageable

  def mount_uploader_base_on_imageable
    if imageable.class == ImageableA
      self.class.mount_uploader :file, ImageableAUploader
    else
      self.class.mount_uploader :file, ImageableBUploader
    end
  end
end
like image 171
tony.hokan Avatar answered Nov 06 '22 08:11

tony.hokan