Module: EchoUploads::Model::ClassMethods
- Defined in:
- lib/echo_uploads/model.rb
Instance Method Summary collapse
Instance Method Details
#echo_upload(attr, options = {}) ⇒ Object
Options:
-
key
: A Proc that takes an ActionDispatch::UploadedFile and returns a key uniquely identifying the file. If this option is not specified, the key is computed as the SHA-512 hash of the file contents. A digest of the file’s contents should always be at least a part of the key. -
expires
: Length of time temporary files will be persisted. Defaults to1.day
. -
storage
: A class that persists uploaded files to disk, to the cloud, or to wherever else you want. Defaults toRails.configuration.echo_uploads.storage
, which in turn isEchoUploads::FilesystemStore
by default. -
map
: A Proc that accepts an ActionDispatch::Htttp::UploadedFile and an instance ofEchoUploads::Mapper
. It should transform the file data (e.g. scaling an image). It should then write the transformed data to one of more temporary files. To get the temporary file path(s), call#write
on theMapper
. See readme.md for an example. The:map
option can also accept a symbol naming an an instance method that works the same way as the previously described Proc. -
multiple
: You use the:map
option to write multiple versions of the file. E.g. multiple thumbnail sizes. If you do so, you must pass multiple: true. This will make the association withEchoUploads::File
ahas_many
instead of ahas_one
. The first file you write in the map function becomes the default. E.g.: Your model is calledWidget
, and the upload file attribute is calledphoto
. You pass:map
with a method that writes three files. If you call Widget#photo_path, it will return the path to the first of the three files. -
write_tmp_file
: Normally, on a failed attempt to save the record, Echo Uploads writes a temp file. That way, the user can fix the validation errors without re-uploading the file. This option determines when the temp file is written. The default is:after_rollback
, meaning the temp file is written on a failed attempt to save the record. Set tofalse
to turn off temp file saving. You can then save temp files manually by calling Set to:after_validation
and the temp file will be written on validation failure. (Warning: Although ActiveRecord implicitly validates before saving, it does so during a transaction. So setting this option to:after_validation
will prevent temp files being written during calls to#save
and similar methods.)
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/echo_uploads/model.rb', line 107 def echo_upload(attr, = {}) = { expires: 1.day, storage: Rails.configuration.echo_uploads.storage, key: ::EchoUploads::File.default_key_proc, write_tmp_file: :after_rollback }.merge() # Init the config object. We can't use [] syntax to set the hash key because # class_attribute expects you to call the setter method every time the # attribute value changes. (Merely calling [] would just mutate the referenced # object, and wouldn't invoke the setter.) self.echo_uploads_config ||= {} self.echo_uploads_config = echo_uploads_config.merge attr => {} # Define reader method for the file attribute. if Rails::VERSION::MAJOR >= 5 and Rails::VERSION::MINOR >= 1 attribute attr else attr_reader attr define_method("#{attr}=") do |file| instance_variable_set "@#{attr}", file if send(attr).present? # Mark as dirty. attribute_will_change! attr end end end # Define the accessor methods for the mapped version(s) of the file. Returns # an array. define_method("mapped_#{attr}") do unless instance_variable_get("@mapped_#{attr}") file = send attr mapper = ::EchoUploads::Mapper.new file if [:map].is_a? Proc [:map].call file, mapper else send([:map], file, mapper) end # Write an array of ActionDispatch::Http::UploadedFile objects to the instance # variable. instance_variable_set("@mapped_#{attr}", mapper.outputs) end instance_variable_get("@mapped_#{attr}") end # Define the original filename method. define_method("#{attr}_original_filename") do (attr, , &:original_filename) end # Define the path method. This method will raise if the given storage # class doesn't support the #path method. define_method("#{attr}_path") do (attr, ) do || .path end end # Define the MIME type method. define_method("#{attr}_mime") do (attr, , &:mime_type) end alias_method "#{attr}_mime_type", "#{attr}_mime" # Define the key method define_method("#{attr}_key") do (attr, , &:key) end # Define the storage method. define_method("#{attr}_storage") do (attr, , &:storage) end # Define the url method. define_method("#{attr}_url") do | = {}| (attr, ) do || if .storage.respond_to?(:url) .storage.url .key, else raise( NoMethodError, "The Echo Uploads file store you've selected, " + "#{.storage.class.to_s}, does not support the #url method." ) end end end # Define the has_x? method. Returns true if a permanent or temporary file has been # persisted, or if a file (which may not be valid) has been uploaded this request # cycle. define_method("has_#{attr}?") do # Does this record have a permanent file? send("has_prm_#{attr}?") or # Did the submitted form "remember" a previously saved metadata record? send("has_tmp_#{attr}?") or # Has a new file been uploaded in this request cycle? send(attr).present? end # Define the has_prm_x? method. Returns true if the permanent metadata record # exists and has its owner set to this object. define_method("has_prm_#{attr}?") do send("#{attr}_metadata").present? and send("#{attr}_metadata").persisted? end # Define the has_tmp_x? method. Returns true if the record "remembers" # a temporary metadata record. (Typically because validation errors caused # the form to be redisplayed.) define_method("has_tmp_#{attr}?") do send("#{attr}_tmp_metadata").present? end # Define the read_x method. Delegates to the #read method of the store (e.g. # FilesystemStore). define_method("read_#{attr}") do (attr, , &:read) end define_method("write_#{attr}") do |&block| echo_uploads_write_prm_file(attr, , &block) end define_method("#{attr}_size") do (attr, , &:size) end define_method("maybe_write_tmp_#{attr}") do echo_uploads_maybe_write_tmp_file(attr, ) end define_method("destroy_#{attr}") do (attr, , &:destroy) end # Define the association with the metadata model. if [:multiple] has_many("#{attr}_metadatas".to_sym, ->() { where(owner_attr: attr) }, as: :owner, dependent: :destroy, class_name: '::EchoUploads::File' ) alias_method attr.to_s.pluralize, "#{attr}_metadatas" define_method("#{attr}_metadata") do send("#{attr}_metadatas").first end define_method("#{attr}_metadata=") do |val| send("#{attr}_metadatas") << val end else has_one("#{attr}_metadata".to_sym, ->() { where(owner_attr: attr) }, as: :owner, dependent: :destroy, class_name: '::EchoUploads::File' ) end # Define the temp attribute for the metadata model. attr_accessor "#{attr}_tmp_metadata" echo_uploads_configure_tmp_file_writing attr, echo_uploads_configure_prm_file_writing attr, end |