Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Calling <code>manipulate!</code> multiple times within the same version applies the changes in its block to the <em>same image</em>; what you want is to create many versions, one corresponding to each <code>Email</code>. This is tricky because CarrierWave really wants you to have a small set of statically defined versions in your code; it actually builds a new, anonymous <code>Uploader</code> class to handle each version.</p> <p>We can trick it to build versions dynamically, but it's pretty ugly. Also, we have to be careful to not keep references to stale uploader classes around, or we'll accumulate classes endlessly and eventually run out of memory!</p> <pre class="lang-ruby prettyprint-override"><code># in ProductUploader: # CarrierWave stores its version classes in two places: # # 1. In a @versions hash, stored within the class; and # 2. As a constant in your uploader, with a name based on its #object_id. # # We have to clean out both of them to be sure old versions get garbage # collected! def self.reset_versions! versions.keys.select { |k| k =~ /^email_/ }.each do |k| u = versions.delete(k)[:uploader] remove_const("Uploader#{u.object_id}".gsub('-', '_')) end end def self.version_name_for email "email_#{email.name}".to_sym end # Dynamically generate the +version+ that corresponds to the image composed # with the image from +email+. def self.version_for_email email version(version_name_for(email)) do process :compose # Use +define_method+ here so that +email+ in the block refers to the # argument "email" from the outer scope. define_method(:email_image_url) { email.secondary.url } # Use the same trick to override the filename for this version. define_method(:filename) { "#{email_name}_#{model.product_number}.png" } # Compose +email_image+ on top of the product image. def compose manipulate! do |img| email_image = ::MiniMagick::Image.open(email_image_url) # Do the actual composition. img = email_image.composite(img, "jpg") do |c| c.gravity "Center" end img end end end end # Clear out any preexisting versions and generate new ones based on the # contents of +emails+. def self.versions_for emails reset_versions! email.find_each { |e| version_for_email(e) } end # After you call Product.versions_for(emails), you can use this to fetch # the version for a specific email: def version_for_email email versions[self.class.version_name_for(email)] end </code></pre> <p>To use this, be sure to call <code>Product.versions_for(Email.all)</code> (possibly in a <code>before_filter</code>), Then, you can access the version for a specific email with <code>@p.product.version_for(email)</code>:</p> <pre class="lang-ruby prettyprint-override"><code># in your controller: def action # Recreate a +version+ for each email. # If you don't want to overlay *every* email's image, you can also pass a # subset here. ProductUploader.versions_for(Email.all) # Upload a file and its versions to Cloud Files... @p = Product.find(params[:id]) @p.product = File.open(Rails.root.join('clouds.jpg'), 'r') @p.save! end </code></pre> <p>In your views, you can use <code>url</code> or any other helpers as usual:</p> <pre class="lang-ruby prettyprint-override"><code># in a view: &lt;% Email.all.find_each do |email| %&gt; &lt;%= image_tag @p.product.version_for_email(email).url %&gt; &lt;% end %&gt; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload