Preacher
Preacher

Reputation: 2420

How do I use model attributes/activerecord methods in carrierwave version processing?

This is another question in pursuit of an answer to this question.

In my watermark processor if I set the watermark image's path to a static watermark image, everything works just fine.

I have three models: Watermark, Gallery, and Photo. Watermark has_many :galleries. Gallery belongs_to :watermark and has_many :photos. Photo belongs_to :gallery and mount_uploader :image, PhotoUploader.

Here's what I'd like to do in photo_uploader.rb:

  version :large do
    process :watermark
    process :resize_to_limit => [600, 600]
  end

  def watermark
    manipulate! do |img|
      watermark = Magick::Image.read(model.gallery.watermark.image_url).first
      img = img.composite(watermark, Magick::CenterGravity, Magick::OverCompositeOp)
    end
  end

While using model methods/attributes works fine in the store_dir method, it doesn't work in the watermark processor. How can I pass the model.gallery.watermark.image_url argument to the watermark processor?

Upvotes: 3

Views: 1924

Answers (1)

the problem is the that by the time the image is mounted on the Model, the variables inside the watemark def, inside the uploader class, are not avialiabled. Thats what did. I'm using mongoid to deal with mongoDB. I set a param inside the Model, that will hold the value that i want eg. the value the_current_model.gallery.watermark.image_url. This param will be user_image.

class Asset
  include Mongoid::Document
  mount_uploader :image, AssetUploader

  field :user_image

  attr_accessible :user_image

  after_save :mark_it

  private
  def mark_it
    image.recreate_versions! if user_image.present?
  end

end

The key to solve this problem is recreate the image (as you see on the model calling the mark_it def) after the data being saved on the database and the param user_image allowed to be used for you uploader class.

class AssetUploader < CarrierWave::Uploader::Base

  include CarrierWave::RMagick

  storage :file
  # storage :fog

  after :cache, :unlink_original_cache

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  process :resize_to_fit => [800, 800]
  process :quality => 80

  version :thumb do
    process :resize_to_fit => [200, 200]
  end

  version :large do
    process :watermark
  end

  def watermark
    if model.user_name.present?
      manipulate! do |img|
        text = Magick::Draw.new 
        text.gravity = Magick::CenterGravity
        text.fill = 'white'    
        text.pointsize = 40 
        text.stroke = 'none' 
        text.annotate(img, 0, 0, 0, 0, "#{model.user_name}") 
        img
      end
    end
  end

  def unlink_original(file)
    File.delete path if version_name.blank?
  end

  def unlink_original_cache(file)
    File.delete if version_name.blank?
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end

end

Now the key is here:

def watermark
        if model.user_name.present?
          manipulate! do |img|
            text = Magick::Draw.new 
            text.gravity = Magick::CenterGravity
            text.fill = 'white'    
            text.pointsize = 40 
            text.stroke = 'none' 
            text.annotate(img, 0, 0, 0, 0, "#{model.user_name}") 
            img
          end
        end
      end

The method watermark only creates the image with the watermark on it, if the user_name param on the model is set (created on the db). So when the data is saved on the db, this param is avaliabled for you uploader class to use as want.

Thats what I did, and it worked very well! I hope it could help!

Upvotes: 1

Related Questions