module Refile::Attachment

Public Instance Methods

accepts_attachments_for(collection_name, collection_class:, accessor_prefix:, attachment: :file, append: false) click to toggle source

Macro which generates accessors in pure Ruby classes for assigning multiple attachments at once. This is primarily useful together with multiple file uploads. There is also an Active Record version of this macro.

The name of the generated accessors will be the name of the association (represented by an attribute accessor) and the name of the attachment in the associated class. So if a `Post` accepts attachments for `images`, and the attachment in the `Image` class is named `file`, then the accessors will be named `images_files`.

@example in associated class

class Document
  extend Refile::Attachment
  attr_accessor :file_id

  attachment :file

  def initialize(attributes = {})
    self.file = attributes[:file]
  end
end

@example in class

class Post
  extend Refile::Attachment
  include ActiveModel::Model

  attr_accessor :documents

  accepts_attachments_for :documents, accessor_prefix: 'documents_files', collection_class: Document

  def initialize(attributes = {})
    @documents = attributes[:documents] || []
  end
end

@example in form

<%= form_for @post do |form| %>
  <%= form.attachment_field :documents_files, multiple: true %>
<% end %>

@param [Symbol] collection_name Name of the association @param [Class] collection_class Associated class @param [String] accessor_prefix Name of the generated accessors @param [Symbol] attachment Name of the attachment in the associated class @param [Boolean] append If true, new files are appended instead of replacing the entire list of associated classes. @return [void]

# File lib/refile/attachment.rb, line 156
def accepts_attachments_for(collection_name, collection_class:, accessor_prefix:, attachment: :file, append: false)
  include MultipleAttachments.new(
    collection_name,
    collection_class: collection_class,
    name: accessor_prefix,
    attachment: attachment,
    append: append
  )
end
attachment(name, cache: :cache, store: :store, raise_errors: true, type: nil, extension: nil, content_type: nil) click to toggle source

Macro which generates accessors for the given column which make it possible to upload and retrieve previously uploaded files through the generated accessors.

The `raise_errors` option controls whether assigning an invalid file should immediately raise an error, or save the error and defer handling it until later.

Given a record with an attachment named `image`, the following methods will be added:

  • `image`

  • `image=`

  • `remove_image`

  • `remove_image=`

  • `remote_image_url`

  • `remote_image_url=`

  • `image_url`

  • `image_presigned_url`

@example

class User
  extend Refile::Attachment

  attachment :image
  attr_accessor :image_id
end

@param [String] name Name of the column which accessor are generated for @param [#to_s] cache Name of a backend in {Refile.backends} to use as transient cache @param [#to_s] store Name of a backend in {Refile.backends} to use as permanent store @param [true, false] raise_errors Whether to raise errors in case an invalid file is assigned @param [Symbol, nil] type The type of file that can be uploaded, see {Refile.types} @param [String, Array<String>, nil] extension Limit the uploaded file to the given extension or list of extensions @param [String, Array<String>, nil] content_type Limit the uploaded file to the given content type or list of content types @return [void]

# File lib/refile/attachment.rb, line 39
def attachment(name, cache: :cache, store: :store, raise_errors: true, type: nil, extension: nil, content_type: nil)
  definition = AttachmentDefinition.new(name,
    cache: cache,
    store: store,
    raise_errors: raise_errors,
    type: type,
    extension: extension,
    content_type: content_type
  )

  define_singleton_method :"#{name}_attachment_definition" do
    definition
  end

  mod = Module.new do
    attacher = :"#{name}_attacher"

    define_method :"#{name}_attachment_definition" do
      definition
    end

    define_method attacher do
      ivar = :"@#{attacher}"
      instance_variable_get(ivar) or instance_variable_set(ivar, Attacher.new(definition, self))
    end

    define_method "#{name}=" do |value|
      send(attacher).set(value)
    end

    define_method name do
      send(attacher).get
    end

    define_method "remove_#{name}=" do |remove|
      send(attacher).remove = remove
    end

    define_method "remove_#{name}" do
      send(attacher).remove
    end

    define_method "remote_#{name}_url=" do |url|
      send(attacher).download(url)
    end

    define_method "remote_#{name}_url" do
    end

    define_method "#{name}_url" do |*args|
      Refile.attachment_url(self, name, *args)
    end

    define_method "presigned_#{name}_url" do |expires_in = 900|
      attachment = send(attacher)
      attachment.store.object(attachment.id).presigned_url(:get, expires_in: expires_in) unless attachment.id.nil?
    end

    define_method "#{name}_data" do
      send(attacher).data
    end

    define_singleton_method("to_s")    { "Refile::Attachment(#{name})" }
    define_singleton_method("inspect") { "Refile::Attachment(#{name})" }
  end

  include mod
end