Module: CroppedPaperclip::ClassMethods
- Defined in:
- lib/cropped_paperclip.rb
Overview
CroppedPaperclip::ClassMethods is included into ActiveRecord::Base in the same way as the Paperclip module. It adds a ‘has_upload` class method that defines an attachment and adds several instance methods that will return the values that determine its cropping. Those values are usually but not
necessarily given by the user.
Instance Method Summary collapse
-
#delay_post_processing(attachment_name = :image) ⇒ Object
Delay post-processing.
-
#has_upload(attachment_name = :image, options = {}) ⇒ Object
Defining upload columns.
Instance Method Details
#delay_post_processing(attachment_name = :image) ⇒ Object
Delay post-processing
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/cropped_paperclip.rb', line 132 def delay_post_processing(=:image) send(:"before_#{}_post_process", :"defer_#{}_post_processing") after_save(:"resume_#{}_post_processing") # There are too many thumbnail styles in this class. We can't make the user wait while they are processed, # so the whole job of thumbnailing is spun off into a delayed_job. Since the main publication page displays # the :original style, we can show the user her public page while the rest of the thumbnails are still being # processed. # # The usual post_processing routine is abandoned when we return false from this call. # define_method :"defer_#{}_post_processing" do if send(:"reprocess_#{}?") && !send(:"awaiting_#{}_processing?") send(:"awaiting_#{}_processing", true) false end end # The delayed job is created just by interposing the `delay` method in a call to `process_image_styles!`. The effect # is to serialize this object and that call to the database and resume it later when the job runner picks it up. # We can't do that until the publication object has an id, so the call is made from an after_save handler. # define_method :"resume_#{}_post_processing" do if send(:"reprocess_#{}?") && send(:"awaiting_#{}_processing?") self.delay.send(:"process_#{}_styles!") end end # This is the eventual processing step, to which the delayed job object is just a sort of pointer. # It retrieves the original image from S3 and applies the processing styles. # define_method :"process_#{}_styles!" do send().reprocess! update_column(:"awaiting_#{}_processing", false) end end |
#has_upload(attachment_name = :image, options = {}) ⇒ Object
Defining upload columns
has_upload brings in the whole machinery of receiving and cropping an uploaded file. eg.
class User < ActiveRecord::Base
has_upload :avatar, :size => '120x120#'
The geometry string will always be treated as though it ended in ‘#’.
Set the :cropped option to false if you want the file-upload-sharing mechanism but no cropping step. In that case any geometry string can be used and it will be passed through intact.
class Group < ActiveRecord::Base
has_upload :icon, :size => '40x40#', :crop => false
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/cropped_paperclip.rb', line 37 def has_upload(=:image, ={}) unless !table_exists? || column_names.include?("#{}_upload_id") raise RuntimeError, "has_upload(#{}) called on class #{self.to_s} but we have no #{}_upload_id column" end .reverse_merge!(:geometry => "640x960#", :cropped => true, :whiny => true) [:geometry].sub!(/\D*$/, '') if [:cropped] # raise here if geometry is not useable class_variable_set(:"@@#{}_cropped", [:cropped]) # The essential step is present in this style definition. It specifies the OffsetThumbnail processor, # which is similar to the usual thumbnailer but has a more flexible scaling and cropping procedure, # and passes through a couple of callback procs that will return the scaling and cropping arguments # it requires. # crop_style = [:cropped] == false ? geometry : { :geometry => "#{[:geometry]}#", :processors => [:offset_thumbnail], # The processor will first scale the image to the width that is specified by the scale_width property of the instance :scale => lambda { |att| width = att.instance.send :"#{}_scale_width" "#{width || 0}x" }, # ...then perform the crop described by the width, height, offset_top and offset_left properties of the instance. :crop_and_offset => lambda { |att| width, height = [:geometry].split('x') left = att.instance.send :"#{}_offset_left" || 0 top = att.instance.send :"#{}_offset_top" "%dx%d%+d%+d" % [width, height, -(left || 0), -(top || 0)] } } [:styles] ||= { :icon => "48x48#" } [:styles].merge!({:cropped => crop_style}) ### Upload association # # [uploads](/app/models/upload.html) are the raw image files uploaded by this person. # They are held separately as the basis for repeatable (and shareable) image assignment. # belongs_to :"#{}_upload", :class_name => "Upload" before_save :"read_#{}_upload" ### Attachment # # Image attachments work in the usual Paperclip way except that the :cropped style is applied differently to each instance. # The editing interface allows the user to upload a picture (which creates an upload object) and choose how it is scaled # and cropped (which stores values here). # # The cropped image is created by a [custom processor](/lib/paperclip_processors/offset_thumbnail.html) very similar to # Paperclip::Thumbnail, but which looks up the scale and crop parameters to calculate the imagemagick transformation. # has_attached_file , ## Maintenance # # *read_[name]_upload* is called before_save. If there is a new upload, or any of our scale and crop values are changed, it will assign # the uploaded file. Even if it's the same file as before, the effect is to trigger post-processing again and apply the current crop and scale values. # define_method :"read_#{}_upload" do if self.send(:"reprocess_#{}?") && upload = self.send(:"#{}_upload") self.send :"#{}=", upload.file end end # *reprocess_[name]?* returns true if there have been any changes to the upload association that would necessitate a new crop. # cols = [:upload_id] cols += [:upload_id, :scale_width, :offset_top, :offset_left] if [:cropped] define_method :"reprocess_#{}?" do cols.any? {|col| send(:"#{}_#{col}_changed?") } end # * [name]_cropped? returns true if the named attachment is cropped on assignment. It can be useful in a form partial. # define_method :"#{}_cropped?" do STDERR.puts ">> #{}_cropped?" !!class_variable_get(:"@@#{}_cropped") end define_method :"#{}_for_cropping" do if upload = send(:"#{}_upload") # here we introduce a convention that might not stand up STDERR.puts ">> #{}_for_cropping" upload.url(:"#{}") end end end |