Model
The model
plugin provides integration for handling attachment on
mutable structs. It is built on top of the entity
plugin.
plugin :model
Attachment
Including a Shrine::Attachment
module into a model class will:
- add entity attachment methods
- add
#<name>=
and#<name>_changed?
methods
class Photo
attr_accessor :image_data
include ImageUploader::Attachment(:image)
end
photo = Photo.new
photo.image = file
photo.image #=> #<Shrine::UploadedFile id="bc2e13.jpg" storage=:cache ...>
photo.image_data #=> '{"id":"bc2e13.jpg","storage":"cache","metadata":{...}}'
photo.image_attacher.finalize
photo.image #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
photo.image_data #=> '{"id":"397eca.jpg","storage":"store","metadata":{...}}'
#<name>=
Calls Attacher#assign
by default, which uploads the file to temporary storage
and attaches it, updating the model attribute.
photo = Photo.new
photo.image = file
photo.image.storage_key #=> :cache
photo.image_data #=> '{"id":"...","storage":"cache","metadata":{...}}'
#<name>_changed?
Calls Attacher#changed?
which returns whether the attachment has changed.
photo = Photo.new
photo.image_changed? #=> false
photo.image = file
photo.image_changed? #=> true
Disabling caching
If you don't want to use temporary storage, you can have #<name>=
upload
directly to permanent storage.
plugin :model, cache: false
photo = Photo.new
photo.image = file
photo.image.storage_key #=> :store
photo.image_data #=> '{"id":"...","storage":"store","metadata":{...}}'
This can be configured on the attacher level as well:
photo = Photo.new
photo.image_attacher(model_cache: false)
photo.image = file
photo.image.storage_key #=> :store
#<name>_attacher
Returns an Attacher
instance backed by the model instance, memoized in an
instance variable.
photo = Photo.new
photo.image_attacher #=> #<ImageUploader::Attacher> (memoizes the instance)
photo.image_attacher #=> #<ImageUploader::Attacher> (returns memoized instance)
When attacher options are passed, the attacher instance is refreshed:
photo = Photo.new
photo.image_attacher(cache: :other_cache)
photo.image_attacher.cache_key #=> :other_cache
Entity
If you still want to include Shrine::Attachment
modules to immutable
entities, you can disable "model" behaviour by passing model: false
:
class Photo
attr_reader :image_data
include ImageUploader::Attachment(:image, model: false)
end
Attacher
You can also use Shrine::Attacher
directly (with or without the
Shrine::Attachment
module):
class Photo
attr_accessor :image_data
end
photo = Photo.new
attacher = ImageUploader::Attacher.from_model(photo, :image)
attacher.assign(file) # cache
attacher.file #=> #<Shrine::UploadedFile id="bc2e13.jpg" storage=:cache ...>
photo.image_data #=> '{"id":"bc2e13.jpg","storage":"cache","metadata":{...}}'
attacher.finalize # promote
attacher.file #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
photo.image_data #=> '{"id":"397eca.jpg","storage":"store","metadata":{...}}'
Loading model
The Attacher.from_model
method can be used for creating an Attacher
instance backed by a model object.
photo = Photo.new
attacher = ImageUploader::Attacher.from_model(photo, :image)
attacher.record #=> #<Photo>
attacher.name #=> :image
attacher.attribute #=> :image_data
attacher.attach(io)
photo.image_data #=> '{"id":"...","storage":"...","metadata":{...}}'
You can also load an entity into an existing attacher with
Attacher#load_model
.
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
attacher.file #=> nil
attacher.load_model(photo, :image)
attacher.file #=> #<ImageUploader::UploadedFile>
Or just Attacher#set_model
if you don't want to load attachment data:
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
attacher.file #=> nil
attacher.set_model(photo, :image) # doesn't load attachment data
attacher.file #=> nil
Writing attachment data
The Attacher#write
method writes attachment data to the #<name>_data
attribute on the model instance.
photo = Photo.new
attacher = ImageUploader::Attacher.from_model(photo, :image)
attacher.file = uploaded_file
photo.image_data #=> nil
attacher.write
photo.image_data #=> '{"id":"...","storage":"...","metadata":{...}}'
The Attacher#write
method is automatically called on Attacher#set
, as well
as Attacher#assign
, Attacher#attach_cached
, Attacher#attach
,
Attacher#promote
and any other attacher method that calls Attacher#set
.
Serialization
By default, attachment data is serialized into JSON using the JSON
standard
library. If you want to change how data is serialized, see the
column
plugin docs.