Class: Adrift::Attachment

Inherits:
Object
  • Object
show all
Defined in:
lib/adrift/attachment.rb

Overview

Handles attaching files to a model, allowing to automatically create different stlyes (versions) of them.

Actually, this class’s responsibility consist in just directing this process: it relies on a #storage object, for saving and removing the attached files, and on a #processor object, for the task of generating the different versions of a file from the given style definitions.

Also, it provides a naive pattern mechanism to express the attachment’s #path and #url.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, model, options = {}) ⇒ Attachment

Creates a new Attachment object. name is the name of the Attachment, model is the model object it’s attached to, and options is a Hash that lets customize the Attachment’s behaviour.

The model object must allow reading and writing to an attribute called after the Attachment’s name which stores the attached file’s name. For instance, for an attachment named avatar, the model needs to respond to the methods avatar_filename and avatar_filename=.

See ::default_options for a list of the supported options. The options passed here will overwrite the default ones.



121
122
123
124
125
126
127
128
129
# File 'lib/adrift/attachment.rb', line 121

def initialize(name, model, options={})
  self.class.default_options.merge(options).each do |name, value|
    writer_name = "#{name}="
    if respond_to?(writer_name)
      send writer_name, value.is_a?(Proc) ? value.call : value
    end
  end
  @name, @model = name, model
end

Instance Attribute Details

#default_styleObject

Returns the value of attribute default_style.



14
15
16
# File 'lib/adrift/attachment.rb', line 14

def default_style
  @default_style
end

#default_url=(value) ⇒ Object (writeonly)

Sets the attribute default_url

Parameters:

  • value

    the value to set the attribute default_url to.



15
16
17
# File 'lib/adrift/attachment.rb', line 15

def default_url=(value)
  @default_url = value
end

#modelObject (readonly)

Returns the value of attribute model.



16
17
18
# File 'lib/adrift/attachment.rb', line 16

def model
  @model
end

#nameObject (readonly)

Returns the value of attribute name.



16
17
18
# File 'lib/adrift/attachment.rb', line 16

def name
  @name
end

#path(style = default_style) ⇒ Object

Returns the attachment’s path for the given style. If no style is given it assumes :default_style option. When the attachment is empty it returns nil.



149
150
151
# File 'lib/adrift/attachment.rb', line 149

def path(style=default_style)
  specialize(@path, style) unless empty?
end

#pattern_classObject

Returns the value of attribute pattern_class.



14
15
16
# File 'lib/adrift/attachment.rb', line 14

def pattern_class
  @pattern_class
end

#processorObject

Returns the value of attribute processor.



14
15
16
# File 'lib/adrift/attachment.rb', line 14

def processor
  @processor
end

#storageObject

Returns the value of attribute storage.



14
15
16
# File 'lib/adrift/attachment.rb', line 14

def storage
  @storage
end

#stylesObject

Returns the value of attribute styles.



14
15
16
# File 'lib/adrift/attachment.rb', line 14

def styles
  @styles
end

#url(style = default_style) ⇒ Object

Returns the attachment’s url for the given style. If no style is given it assumes the :default_style option. Also, it uses the :url or the :default_url option, depending whether or not the attachment is empty.



142
143
144
# File 'lib/adrift/attachment.rb', line 142

def url(style=default_style)
  specialize(empty? ? @default_url : @url, style)
end

Class Method Details

.config(&block) ⇒ Object

Allows to change the options used for every new attachment. For instance, to change the :default_style and :path options:

Adrift::Attachment.config do
  default_style :default
  path '/custom/storage/path/:url'
end

See ::default_options for a list of the supported options.



27
28
29
30
31
32
33
34
# File 'lib/adrift/attachment.rb', line 27

def self.config(&block)
  config = BasicObject.new
  def config.method_missing(m, *args)
    options = Attachment.default_options
    options[m] = args.first if options.has_key?(m)
  end
  config.instance_eval(&block)
end

.default_optionsObject

Default options for every new Attachment. These are:

:default_style

Style assumed by #url and #path when no one has been provided.

:styles

Hash with the style definitions, they keys are the style names, and the values whatever makes sense to the processor to generate the alternate versions of the attached file. By default, they indicate the thumbnails dimmensions, for instance:

styles: { small: '50x50', medium: '100x100' }

See Processor::Thumbnail for the details.

:default_url

String pattern used to build the returned value of #url when the attachment is empty.

:url

String pattern used to build the returned value of #url when the attachment is not empty.

:path

String pattern used to build the path where the attachment will be stored (and will be returned by #path).

Note: when having an attachment with more than one style, the path must be unique for each one, otherwise the stored files will be overwritten. In the most common case, what this means is just that the path option must have a :style tag.

:storage

Object delegated with the task of saving and removing files. See Storage for details and Storage::Filesystem for an implementation.

:processor

Object delegated with the task of generating the alternate versions of the attached file from the :styles. See Processor for details and Processor::Thumbnail for an implementation.

:pattern_class

The class used to build the #url and #path of the Attachment from the string patterns provided.

See the source of this method to know the values of this options. Note that these values can be changed for every new attachment with ::config, or in a per-attachment basis, when they are constructed with ::new, or after, just calling the attachment’s writer method named after the option.



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/adrift/attachment.rb', line 88

def self.default_options
  @default_options ||= {
    :default_style => :original,
    :styles        => {},
    :default_url   => '/:attachment/:style/missing.png',
    :url           => '/system/:attachment/:id/:style/:filename',
    :path          => ':root/public:url',
    :storage       => Proc.new { Storage::Filesystem.new },
    :processor     => Proc.new { Processor::Thumbnail.new },
    :pattern_class => Pattern
  }
end

.reset_default_optionsObject

Restores the attachment’s options to their default values. See the source of ::default_options to know what these default values are.



104
105
106
# File 'lib/adrift/attachment.rb', line 104

def self.reset_default_options
  @default_options = nil
end

Instance Method Details

#assign(file_to_attach) ⇒ Object

Makes file_to_attach the new attached file, but it won’t be stored nor processed until the attachment receives #save. It also updates the model’s attachment file name attribute.

See FileToAttach::Adapters for the expected interface of file_to_attach.



159
160
161
162
163
164
165
166
# File 'lib/adrift/attachment.rb', line 159

def assign(file_to_attach)
  enqueue_files_for_removal
  model_send(
    :filename=,
    file_to_attach.original_filename.to_s.tr('^a-zA-Z0-9.', '_')
  )
  @file_to_attach = file_to_attach
end

#clearObject

Throws away the current attached file, but it won’t actually be removed until the attachment receives #save. It also sets the model’s attachment file name attribute to nil.



171
172
173
174
175
# File 'lib/adrift/attachment.rb', line 171

def clear
  enqueue_files_for_removal
  @file_to_attach = nil
  model_send(:filename=, nil)
end

#destroyObject

Removes the current attached file, setting the model’s attachment file name attribute to nil.



195
196
197
198
# File 'lib/adrift/attachment.rb', line 195

def destroy
  clear
  save
end

#dirty?Boolean

Indicates whether or not there are changes that need to be saved, that is, files that need to be processed and stored and/or removed.

Returns:

  • (Boolean)


134
135
136
# File 'lib/adrift/attachment.rb', line 134

def dirty?
  !@file_to_attach.nil? || storage.dirty?
end

#empty?Boolean

Indicates whether or not there is a file attached. Note that a file could be attached without being stored or processed.

Returns:

  • (Boolean)


202
203
204
# File 'lib/adrift/attachment.rb', line 202

def empty?
  filename.nil?
end

#filenameObject

Returns the attachment’s file name.



207
208
209
# File 'lib/adrift/attachment.rb', line 207

def filename
  model_send(:filename)
end

#saveObject

When there is a new attached file will store and process it, and if there was a previous attached file it will also remove it. On the other hand it will remove the current attached file if it was thrown away (in other words, the attachment has received #clear).

Generally, this will get called when the model is saved.



184
185
186
187
188
189
190
191
# File 'lib/adrift/attachment.rb', line 184

def save
  unless @file_to_attach.nil?
    processor.process(@file_to_attach.path, styles)
    enqueue_files_for_storage
  end
  storage.flush
  @file_to_attach = nil
end