module Paperdragon # Fuzzy API: gives you #image that can do both upload and rendering. module Model def self.included(base) base.extend ClassMethods end module ClassMethods def processable(name, attachment_class=Attachment) include attachment_accessor_for(name, attachment_class) end private # Creates Avatar#image that returns a Paperdragon::File instance. def attachment_accessor_for(name, attachment_class) mod = Module.new do # TODO: abstract that into Uber, we use it everywhere. define_method name do |file=nil, options={}, &block| attachment = attachment_class.new(public_send("#{name}_meta_data"), options.merge(model: self)) return attachment unless file or block # run the task block and save the returned new metadata in the model. self.public_send("#{name}_meta_data=", attachment.task(*[file], &block)) end end end end # class Album # extend Paperdragon::Model::Writer # processable_writer :image # # Provides Album#image!(file) { |v| v.thumb!("64x64") } module Writer def processable_writer(name, attachment_class=Attachment) mod = Module.new do # TODO: abstract that into Uber, we use it everywhere. define_method "#{name}!" do |file=nil, options={}, &block| attachment = attachment_class.new(public_send("#{name}_meta_data"), options.merge(model: self)) # run the task block and save the returned new metadata in the model. self.public_send("#{name}_meta_data=", attachment.task(*[file], &block)) end end include mod end end # Writer. # class Album # extend Paperdragon::Model::Reader # processable_reader :image # # Provides Album#image #=> Attachment. module Reader def processable_reader(name, attachment_class=Attachment) define_method name do attachment_class.new(public_send("#{name}_meta_data"), model: self) end end end end end