Skip to main content

Entity

The entity plugin provides integration for handling attachments on immutable structs. It is built on top of the column plugin.

plugin :entity

Attachment

Including a Shrine::Attachment module into an entity class will add the following instance methods:

  • #<name> – returns the attached file
  • #<name>_url – returns the attached file URL
  • #<name>_attacher – returns a Shrine::Attacher instance

These methods read attachment data from the #<name>_data attribute on the entity instance.

class Photo
  attr_reader :image_data

  include ImageUploader::Attachment(:image)
end
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
photo.image          #=> #<ImageUploader::UploadedFile>
photo.image_url      #=> "https://example.com/image.jpg"
photo.image_attacher #=> #<ImageUploader::Attacher>

#<name>

Calls Attacher#get, which returns an UploadedFile object instantiated from attachment data.

photo = Photo.new(image_data: '{"id":"foo.jpg","storage":"store","metadata":{...}}')
photo.image             #=> #<ImageUploader::UploadedFile>
photo.image.id          #=> "foo.jpg"
photo.image.storage_key #=> :store
photo.image.metadata    #=> { ... }

If no file is attached, nil is returned.

photo = Photo.new(image_data: nil)
photo.image #=> nil

#<name>_url

Calls Attacher#url, which returns the URL to the attached file.

photo = Photo.new(image_data: {"id":"foo.jpg","storage":"...","metadata":{...}})
photo.image_url #=> "https://example.com/foo.jpg"

If no file is attached, nil is returned.

photo = Photo.new(image_data: nil)
photo.image_url #=> nil

#<name>_attacher

Calls Attacher.from_entity, which returns an Attacher instance backed by the entity object.

photo = Photo.new
photo.image_attacher           #=> #<ImageUploader::Attacher>
photo.image_attacher.record    #=> #<Photo>
photo.image_attacher.name      #=> :image
photo.image_attacher.attribute #=> :image_data

Any additional options will be forwarded to Attacher#initialize.

photo    = Photo.new
attacher = photo.image_attacher(cache: :other_cache)
attacher.cache_key #=> :other_cache

You can also specify default attacher options when including Shrine::Attachment:

class Photo
  attr_reader :image_data

  include ImageUploader::Attachment(:image, store: :other_store)
end
photo    = Photo.new
attacher = photo.image_attacher
attacher.store_key #=> :other_store

You can retrieve an Attacher instance from the entity class as well. In this case it will not be initialized with any entity instance.

attacher = Photo.image_attacher
attacher #=> #<ImageUploader::Attacher>
attacher.record #=> nil
attacher.name   #=> nil

attacher = Photo.image_attacher(store: :other_store)
attacher.store_key #=> :other_store

Attacher

You can also use Shrine::Attacher directly (with or without the Shrine::Attachment module):

class Photo
  attr_reader :image_data
end
photo    = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
attacher = ImageUploader::Attacher.from_entity(photo, :image)

attacher.file #=> #<Shrine::UploadedFile id="bc2e13.jpg" storage=:store ...>

attacher.attach(file)
attacher.file          #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
attacher.column_values #=> { image_data: '{"id":"397eca.jpg","storage":"store","metadata":{...}}' }

photo    = Photo.new(attacher.column_values)
attacher = ImageUploader::Attacher.from_entity(photo, :image)

attacher.file #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>

Loading entity

The Attacher.from_entity method can be used for creating an Attacher instance backed by an entity object.

photo    = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
attacher = ImageUploader::Attacher.from_entity(photo, :image)

attacher.record    #=> #<Photo>
attacher.name      #=> :image
attacher.attribute #=> :image_data

attacher.file #=> #<ImageUploader::UploadedFile>

Any additional options are forwarded to Attacher#initialize.

attacher = ImageUploader::Attacher.from_entity(photo, :image, cache: :other_cache)
attacher.cache_key #=> :other_cache

You can also load an entity into an existing attacher with Attacher#load_entity.

photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')

attacher.load_entity(photo, :image)
attacher.record #=> #<Photo>
attacher.name   #=> :image
attacher.file   #=> #<ImageUploader::UploadedFile>

Or just Attacher#set_entity if you don't want to load attachment data:

photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')

attacher.set_entity(photo, :image) # doesn't load attachment data
attacher.record #=> #<Photo>
attacher.name   #=> :image
attacher.file   #=> nil

Reloading

The Attacher#reload method reloads attached file from the attachment data on the entity attribute and resets dirty tracking.

photo = Photo.new

attacher = ImageUploader::Attacher.from_entity(photo, :image)
attacher.file #=> nil

photo.image_data = '{"id":"...","storage":"...","metadata":{...}}'

attacher.file #=> nil
attacher.reload
attacher.file #=> #<ImageUploader::UploadedFile>

If you want to reload attachment data while retaining dirty tracking state, use Attacher#read instead.

Column values

The Attacher#column_values method returns a hash with the entity attribute as key and current attachment data as value.

attacher = ImageUploader::Attacher.from_entity(Photo.new, :image)
attacher.attach(io)

attacher.column_values #=> { :image_data => '{"id":"...","storage":"...","metadata":{...}}' }

The Attacher#attribute method returns just the entity attribute from which attached file data is read.

attacher = ImageUploader::Attacher.from_entity(Photo.new, :image)
attacher.attribute #=> :image_data

Entity data

The Attacher#record method returns the entity instance from which the attacher was loaded.

attacher = ImageUploader::Attacher.from_entity(Photo.new, :image)
attacher.record #=> #<Photo>

The Attacher#name method returns the name of the attachment from which the attacher was loaded.

attacher = ImageUploader::Attacher.from_entity(Photo.new, :image)
attacher.name #=> :image

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.