paperclip 2.3.1.1 → 2.3.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of paperclip might be problematic. Click here for more details.
- data/README.rdoc +6 -1
- data/Rakefile +11 -38
- data/generators/paperclip/USAGE +2 -2
- data/generators/paperclip/paperclip_generator.rb +8 -8
- data/lib/generators/paperclip/USAGE +8 -0
- data/lib/generators/paperclip/paperclip_generator.rb +31 -0
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
- data/lib/paperclip.rb +113 -69
- data/lib/paperclip/attachment.rb +58 -146
- data/lib/paperclip/callback_compatability.rb +50 -22
- data/lib/paperclip/geometry.rb +7 -7
- data/lib/paperclip/interpolations.rb +21 -21
- data/lib/paperclip/iostream.rb +3 -2
- data/lib/paperclip/matchers.rb +29 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +8 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +13 -5
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +13 -7
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +16 -4
- data/lib/paperclip/processor.rb +2 -2
- data/lib/paperclip/railtie.rb +22 -0
- data/lib/paperclip/storage.rb +29 -25
- data/lib/paperclip/style.rb +90 -0
- data/lib/paperclip/thumbnail.rb +20 -15
- data/lib/paperclip/upfile.rb +5 -2
- data/lib/paperclip/version.rb +3 -0
- data/{tasks/paperclip_tasks.rake → lib/tasks/paperclip.rake} +0 -0
- data/rails/init.rb +2 -0
- data/shoulda_macros/paperclip.rb +5 -3
- data/test/attachment_test.rb +52 -74
- data/test/geometry_test.rb +1 -1
- data/test/helper.rb +62 -22
- data/test/integration_test.rb +8 -8
- data/test/interpolations_test.rb +4 -4
- data/test/iostream_test.rb +9 -2
- data/test/matchers/have_attached_file_matcher_test.rb +9 -6
- data/test/matchers/validate_attachment_content_type_matcher_test.rb +15 -8
- data/test/matchers/validate_attachment_presence_matcher_test.rb +11 -6
- data/test/matchers/validate_attachment_size_matcher_test.rb +18 -17
- data/test/paperclip_test.rb +58 -68
- data/test/storage_test.rb +53 -13
- data/test/style_test.rb +141 -0
- data/test/thumbnail_test.rb +17 -17
- data/test/upfile_test.rb +8 -0
- metadata +69 -42
data/lib/paperclip/iostream.rb
CHANGED
@@ -4,7 +4,8 @@ module IOStream
|
|
4
4
|
|
5
5
|
# Returns a Tempfile containing the contents of the readable object.
|
6
6
|
def to_tempfile
|
7
|
-
|
7
|
+
name = respond_to?(:original_filename) ? original_filename : (respond_to?(:path) ? path : "stream")
|
8
|
+
tempfile = Paperclip::Tempfile.new("stream" + File.extname(name))
|
8
9
|
tempfile.binmode
|
9
10
|
self.stream_to(tempfile)
|
10
11
|
end
|
@@ -25,7 +26,7 @@ module IOStream
|
|
25
26
|
while self.read(in_blocks_of, buffer) do
|
26
27
|
dstio.write(buffer)
|
27
28
|
end
|
28
|
-
dstio.rewind
|
29
|
+
dstio.rewind
|
29
30
|
dstio
|
30
31
|
end
|
31
32
|
end
|
data/lib/paperclip/matchers.rb
CHANGED
@@ -2,3 +2,32 @@ require 'paperclip/matchers/have_attached_file_matcher'
|
|
2
2
|
require 'paperclip/matchers/validate_attachment_presence_matcher'
|
3
3
|
require 'paperclip/matchers/validate_attachment_content_type_matcher'
|
4
4
|
require 'paperclip/matchers/validate_attachment_size_matcher'
|
5
|
+
|
6
|
+
module Paperclip
|
7
|
+
module Shoulda
|
8
|
+
# Provides rspec-compatible matchers for testing Paperclip attachments.
|
9
|
+
#
|
10
|
+
# In spec_helper.rb, you'll need to require the matchers:
|
11
|
+
#
|
12
|
+
# require "paperclip/matchers"
|
13
|
+
#
|
14
|
+
# And include the module:
|
15
|
+
#
|
16
|
+
# Spec::Runner.configure do |config|
|
17
|
+
# config.include Paperclip::Shoulda::Matchers
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Example:
|
21
|
+
# describe User do
|
22
|
+
# it { should have_attached_file(:avatar) }
|
23
|
+
# it { should validate_attachment_presence(:avatar) }
|
24
|
+
# it { should validate_attachment_content_type(:avatar).
|
25
|
+
# allowing('image/png', 'image/gif').
|
26
|
+
# rejecting('text/plain', 'text/xml') }
|
27
|
+
# it { should validate_attachment_size(:avatar).
|
28
|
+
# less_than(2.megabytes) }
|
29
|
+
# end
|
30
|
+
module Matchers
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module Paperclip
|
2
2
|
module Shoulda
|
3
3
|
module Matchers
|
4
|
+
# Ensures that the given instance or class has an attachment with the
|
5
|
+
# given name.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# describe User do
|
9
|
+
# it { should have_attached_file(:avatar) }
|
10
|
+
# end
|
4
11
|
def have_attached_file name
|
5
12
|
HaveAttachedFileMatcher.new(name)
|
6
13
|
end
|
@@ -12,6 +19,7 @@ module Paperclip
|
|
12
19
|
|
13
20
|
def matches? subject
|
14
21
|
@subject = subject
|
22
|
+
@subject = @subject.class unless Class === @subject
|
15
23
|
responds? && has_column? && included?
|
16
24
|
end
|
17
25
|
|
@@ -1,6 +1,15 @@
|
|
1
1
|
module Paperclip
|
2
2
|
module Shoulda
|
3
3
|
module Matchers
|
4
|
+
# Ensures that the given instance or class validates the content type of
|
5
|
+
# the given attachment as specified.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# describe User do
|
9
|
+
# it { should validate_attachment_content_type(:icon).
|
10
|
+
# allowing('image/png', 'image/gif').
|
11
|
+
# rejecting('text/plain', 'text/xml') }
|
12
|
+
# end
|
4
13
|
def validate_attachment_content_type name
|
5
14
|
ValidateAttachmentContentTypeMatcher.new(name)
|
6
15
|
end
|
@@ -22,6 +31,7 @@ module Paperclip
|
|
22
31
|
|
23
32
|
def matches? subject
|
24
33
|
@subject = subject
|
34
|
+
@subject = @subject.class unless Class === @subject
|
25
35
|
@allowed_types && @rejected_types &&
|
26
36
|
allowed_types_allowed? && rejected_types_rejected?
|
27
37
|
end
|
@@ -32,7 +42,7 @@ module Paperclip
|
|
32
42
|
end
|
33
43
|
|
34
44
|
def negative_failure_message
|
35
|
-
"Content types #{@allowed_types.join(", ")} should be rejected" +
|
45
|
+
"Content types #{@allowed_types.join(", ")} should be rejected" +
|
36
46
|
" and #{@rejected_types.join(", ")} accepted by #{@attachment_name}"
|
37
47
|
end
|
38
48
|
|
@@ -46,9 +56,8 @@ module Paperclip
|
|
46
56
|
types.all? do |type|
|
47
57
|
file = StringIO.new(".")
|
48
58
|
file.content_type = type
|
49
|
-
|
50
|
-
|
51
|
-
attachment.errors[:content_type].nil?
|
59
|
+
(subject = @subject.new).attachment_for(@attachment_name).assign(file)
|
60
|
+
subject.valid? && subject.errors[:"#{@attachment_name}_content_type"].blank?
|
52
61
|
end
|
53
62
|
end
|
54
63
|
|
@@ -63,4 +72,3 @@ module Paperclip
|
|
63
72
|
end
|
64
73
|
end
|
65
74
|
end
|
66
|
-
|
@@ -1,6 +1,12 @@
|
|
1
1
|
module Paperclip
|
2
2
|
module Shoulda
|
3
3
|
module Matchers
|
4
|
+
# Ensures that the given instance or class validates the presence of the
|
5
|
+
# given attachment.
|
6
|
+
#
|
7
|
+
# describe User do
|
8
|
+
# it { should validate_attachment_presence(:avatar) }
|
9
|
+
# end
|
4
10
|
def validate_attachment_presence name
|
5
11
|
ValidateAttachmentPresenceMatcher.new(name)
|
6
12
|
end
|
@@ -12,6 +18,7 @@ module Paperclip
|
|
12
18
|
|
13
19
|
def matches? subject
|
14
20
|
@subject = subject
|
21
|
+
@subject = @subject.class unless Class === @subject
|
15
22
|
error_when_not_valid? && no_error_when_valid?
|
16
23
|
end
|
17
24
|
|
@@ -30,19 +37,18 @@ module Paperclip
|
|
30
37
|
protected
|
31
38
|
|
32
39
|
def error_when_not_valid?
|
33
|
-
|
34
|
-
|
35
|
-
not
|
40
|
+
(subject = @subject.new).send(@attachment_name).assign(nil)
|
41
|
+
subject.valid?
|
42
|
+
not subject.errors[:"#{@attachment_name}_file_name"].blank?
|
36
43
|
end
|
37
44
|
|
38
45
|
def no_error_when_valid?
|
39
46
|
@file = StringIO.new(".")
|
40
|
-
|
41
|
-
|
42
|
-
|
47
|
+
(subject = @subject.new).send(@attachment_name).assign(@file)
|
48
|
+
subject.valid?
|
49
|
+
subject.errors[:"#{@attachment_name}_file_name"].blank?
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
46
53
|
end
|
47
54
|
end
|
48
|
-
|
@@ -1,6 +1,16 @@
|
|
1
1
|
module Paperclip
|
2
2
|
module Shoulda
|
3
3
|
module Matchers
|
4
|
+
# Ensures that the given instance or class validates the size of the
|
5
|
+
# given attachment as specified.
|
6
|
+
#
|
7
|
+
# Examples:
|
8
|
+
# it { should validate_attachment_size(:avatar).
|
9
|
+
# less_than(2.megabytes) }
|
10
|
+
# it { should validate_attachment_size(:icon).
|
11
|
+
# greater_than(1024) }
|
12
|
+
# it { should validate_attachment_size(:icon).
|
13
|
+
# in(0..100) }
|
4
14
|
def validate_attachment_size name
|
5
15
|
ValidateAttachmentSizeMatcher.new(name)
|
6
16
|
end
|
@@ -28,6 +38,7 @@ module Paperclip
|
|
28
38
|
|
29
39
|
def matches? subject
|
30
40
|
@subject = subject
|
41
|
+
@subject = @subject.class unless Class === @subject
|
31
42
|
lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
|
32
43
|
end
|
33
44
|
|
@@ -54,9 +65,11 @@ module Paperclip
|
|
54
65
|
def passes_validation_with_size(new_size)
|
55
66
|
file = StringIO.new(".")
|
56
67
|
override_method(file, :size){ new_size }
|
57
|
-
|
58
|
-
|
59
|
-
|
68
|
+
override_method(file, :to_tempfile){ file }
|
69
|
+
|
70
|
+
(subject = @subject.new).send(@attachment_name).assign(file)
|
71
|
+
subject.valid?
|
72
|
+
subject.errors[:"#{@attachment_name}_file_size"].blank?
|
60
73
|
end
|
61
74
|
|
62
75
|
def lower_than_low?
|
@@ -80,4 +93,3 @@ module Paperclip
|
|
80
93
|
end
|
81
94
|
end
|
82
95
|
end
|
83
|
-
|
data/lib/paperclip/processor.rb
CHANGED
@@ -6,7 +6,7 @@ module Paperclip
|
|
6
6
|
#
|
7
7
|
# Processors are required to be defined inside the Paperclip module and
|
8
8
|
# are also required to be a subclass of Paperclip::Processor. There is
|
9
|
-
# only one method you *must* implement to properly be a subclass:
|
9
|
+
# only one method you *must* implement to properly be a subclass:
|
10
10
|
# #make, but #initialize may also be of use. Both methods accept 3
|
11
11
|
# arguments: the file that will be operated on (which is an instance of
|
12
12
|
# File), a hash of options that were defined in has_attached_file's
|
@@ -33,7 +33,7 @@ module Paperclip
|
|
33
33
|
new(file, options, attachment).make
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
# Due to how ImageMagick handles its image format conversion and how Tempfile
|
38
38
|
# handles its naming scheme, it is necessary to override how Tempfile makes
|
39
39
|
# its names so as to allow for file extensions. Idea taken from the comments
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'paperclip'
|
2
|
+
|
3
|
+
module Paperclip
|
4
|
+
if defined? Rails::Railtie
|
5
|
+
require 'rails'
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
ActiveSupport.on_load :active_record do
|
8
|
+
Paperclip::Railtie.insert
|
9
|
+
end
|
10
|
+
rake_tasks do
|
11
|
+
load "tasks/paperclip.rake"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Railtie
|
17
|
+
def self.insert
|
18
|
+
ActiveRecord::Base.send(:include, Paperclip)
|
19
|
+
File.send(:include, Paperclip::Upfile)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/paperclip/storage.rb
CHANGED
@@ -8,21 +8,21 @@ module Paperclip
|
|
8
8
|
# * +path+: The location of the repository of attachments on disk. This can (and, in
|
9
9
|
# almost all cases, should) be coordinated with the value of the +url+ option to
|
10
10
|
# allow files to be saved into a place where Apache can serve them without
|
11
|
-
# hitting your app. Defaults to
|
11
|
+
# hitting your app. Defaults to
|
12
12
|
# ":rails_root/public/:attachment/:id/:style/:basename.:extension"
|
13
|
-
# By default this places the files in the app's public directory which can be served
|
14
|
-
# directly. If you are using capistrano for deployment, a good idea would be to
|
15
|
-
# make a symlink to the capistrano-created system directory from inside your app's
|
13
|
+
# By default this places the files in the app's public directory which can be served
|
14
|
+
# directly. If you are using capistrano for deployment, a good idea would be to
|
15
|
+
# make a symlink to the capistrano-created system directory from inside your app's
|
16
16
|
# public directory.
|
17
17
|
# See Paperclip::Attachment#interpolate for more information on variable interpolaton.
|
18
18
|
# :path => "/var/app/attachments/:class/:id/:style/:basename.:extension"
|
19
19
|
module Filesystem
|
20
20
|
def self.extended base
|
21
21
|
end
|
22
|
-
|
23
|
-
def exists?(
|
22
|
+
|
23
|
+
def exists?(style_name = default_style)
|
24
24
|
if original_filename
|
25
|
-
File.exist?(path(
|
25
|
+
File.exist?(path(style_name))
|
26
26
|
else
|
27
27
|
false
|
28
28
|
end
|
@@ -30,17 +30,17 @@ module Paperclip
|
|
30
30
|
|
31
31
|
# Returns representation of the data of the file assigned to the given
|
32
32
|
# style, in the format most representative of the current storage.
|
33
|
-
def to_file
|
34
|
-
@queued_for_write[
|
33
|
+
def to_file style_name = default_style
|
34
|
+
@queued_for_write[style_name] || (File.new(path(style_name), 'rb') if exists?(style_name))
|
35
35
|
end
|
36
36
|
|
37
37
|
def flush_writes #:nodoc:
|
38
|
-
@queued_for_write.each do |
|
38
|
+
@queued_for_write.each do |style_name, file|
|
39
39
|
file.close
|
40
|
-
FileUtils.mkdir_p(File.dirname(path(
|
41
|
-
log("saving #{path(
|
42
|
-
FileUtils.mv(file.path, path(
|
43
|
-
FileUtils.chmod(0644, path(
|
40
|
+
FileUtils.mkdir_p(File.dirname(path(style_name)))
|
41
|
+
log("saving #{path(style_name)}")
|
42
|
+
FileUtils.mv(file.path, path(style_name))
|
43
|
+
FileUtils.chmod(0644, path(style_name))
|
44
44
|
end
|
45
45
|
@queued_for_write = {}
|
46
46
|
end
|
@@ -78,25 +78,25 @@ module Paperclip
|
|
78
78
|
# database.yml file, so different environments can use different accounts:
|
79
79
|
# development:
|
80
80
|
# access_key_id: 123...
|
81
|
-
# secret_access_key: 123...
|
81
|
+
# secret_access_key: 123...
|
82
82
|
# test:
|
83
83
|
# access_key_id: abc...
|
84
|
-
# secret_access_key: abc...
|
84
|
+
# secret_access_key: abc...
|
85
85
|
# production:
|
86
86
|
# access_key_id: 456...
|
87
|
-
# secret_access_key: 456...
|
87
|
+
# secret_access_key: 456...
|
88
88
|
# This is not required, however, and the file may simply look like this:
|
89
89
|
# access_key_id: 456...
|
90
|
-
# secret_access_key: 456...
|
90
|
+
# secret_access_key: 456...
|
91
91
|
# In which case, those access keys will be used in all environments. You can also
|
92
92
|
# put your bucket name in this file, instead of adding it to the code directly.
|
93
|
-
# This is useful when you want the same account but a different bucket for
|
93
|
+
# This is useful when you want the same account but a different bucket for
|
94
94
|
# development versus production.
|
95
95
|
# * +s3_permissions+: This is a String that should be one of the "canned" access
|
96
96
|
# policies that S3 provides (more information can be found here:
|
97
97
|
# http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html#RESTCannedAccessPolicies)
|
98
98
|
# The default for Paperclip is :public_read.
|
99
|
-
# * +s3_protocol+: The protocol for the URLs generated to your S3 assets. Can be either
|
99
|
+
# * +s3_protocol+: The protocol for the URLs generated to your S3 assets. Can be either
|
100
100
|
# 'http' or 'https'. Defaults to 'http' when your :s3_permissions are :public_read (the
|
101
101
|
# default), and 'https' when your :s3_permissions are anything else.
|
102
102
|
# * +s3_headers+: A hash of headers such as {'Expires' => 1.year.from_now.httpdate}
|
@@ -111,7 +111,7 @@ module Paperclip
|
|
111
111
|
# * +url+: There are three options for the S3 url. You can choose to have the bucket's name
|
112
112
|
# placed domain-style (bucket.s3.amazonaws.com) or path-style (s3.amazonaws.com/bucket).
|
113
113
|
# Lastly, you can specify a CNAME (which requires the CNAME to be specified as
|
114
|
-
# :s3_alias_url. You can read more about CNAMEs and S3 at
|
114
|
+
# :s3_alias_url. You can read more about CNAMEs and S3 at
|
115
115
|
# http://docs.amazonwebservices.com/AmazonS3/latest/index.html?VirtualHosting.html
|
116
116
|
# Normally, this won't matter in the slightest and you can leave the default (which is
|
117
117
|
# path-style, or :s3_path_url). But in some cases paths don't work and you need to use
|
@@ -160,6 +160,10 @@ module Paperclip
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
+
def expiring_url(time = 3600)
|
164
|
+
AWS::S3::S3Object.url_for(path, bucket_name, :expires_in => time )
|
165
|
+
end
|
166
|
+
|
163
167
|
def bucket_name
|
164
168
|
@bucket
|
165
169
|
end
|
@@ -170,9 +174,9 @@ module Paperclip
|
|
170
174
|
|
171
175
|
def parse_credentials creds
|
172
176
|
creds = find_credentials(creds).stringify_keys
|
173
|
-
(creds[
|
177
|
+
(creds[Rails.env] || creds).symbolize_keys
|
174
178
|
end
|
175
|
-
|
179
|
+
|
176
180
|
def exists?(style = default_style)
|
177
181
|
if original_filename
|
178
182
|
AWS::S3::S3Object.exists?(path(style), bucket_name)
|
@@ -223,12 +227,12 @@ module Paperclip
|
|
223
227
|
end
|
224
228
|
@queued_for_delete = []
|
225
229
|
end
|
226
|
-
|
230
|
+
|
227
231
|
def find_credentials creds
|
228
232
|
case creds
|
229
233
|
when File
|
230
234
|
YAML::load(ERB.new(File.read(creds.path)).result)
|
231
|
-
when String
|
235
|
+
when String, Pathname
|
232
236
|
YAML::load(ERB.new(File.read(creds)).result)
|
233
237
|
when Hash
|
234
238
|
creds
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Paperclip
|
3
|
+
# The Style class holds the definition of a thumbnail style, applying
|
4
|
+
# whatever processing is required to normalize the definition and delaying
|
5
|
+
# the evaluation of block parameters until useful context is available.
|
6
|
+
|
7
|
+
class Style
|
8
|
+
|
9
|
+
attr_reader :name, :attachment, :format
|
10
|
+
|
11
|
+
# Creates a Style object. +name+ is the name of the attachment,
|
12
|
+
# +definition+ is the style definition from has_attached_file, which
|
13
|
+
# can be string, array or hash
|
14
|
+
def initialize name, definition, attachment
|
15
|
+
@name = name
|
16
|
+
@attachment = attachment
|
17
|
+
if definition.is_a? Hash
|
18
|
+
@geometry = definition.delete(:geometry)
|
19
|
+
@format = definition.delete(:format)
|
20
|
+
@processors = definition.delete(:processors)
|
21
|
+
@other_args = definition
|
22
|
+
else
|
23
|
+
@geometry, @format = [definition, nil].flatten[0..1]
|
24
|
+
@other_args = {}
|
25
|
+
end
|
26
|
+
@format = nil if @format.blank?
|
27
|
+
end
|
28
|
+
|
29
|
+
# retrieves from the attachment the processors defined in the has_attached_file call
|
30
|
+
# (which method (in the attachment) will call any supplied procs)
|
31
|
+
# There is an important change of interface here: a style rule can set its own processors
|
32
|
+
# by default we behave as before, though.
|
33
|
+
def processors
|
34
|
+
@processors || attachment.processors
|
35
|
+
end
|
36
|
+
|
37
|
+
# retrieves from the attachment the whiny setting
|
38
|
+
def whiny
|
39
|
+
attachment.whiny
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns true if we're inclined to grumble
|
43
|
+
def whiny?
|
44
|
+
!!whiny
|
45
|
+
end
|
46
|
+
|
47
|
+
def convert_options
|
48
|
+
attachment.send(:extra_options_for, name)
|
49
|
+
end
|
50
|
+
|
51
|
+
# returns the geometry string for this style
|
52
|
+
# if a proc has been supplied, we call it here
|
53
|
+
def geometry
|
54
|
+
@geometry.respond_to?(:call) ? @geometry.call(attachment.instance) : @geometry
|
55
|
+
end
|
56
|
+
|
57
|
+
# Supplies the hash of options that processors expect to receive as their second argument
|
58
|
+
# Arguments other than the standard geometry, format etc are just passed through from
|
59
|
+
# initialization and any procs are called here, just before post-processing.
|
60
|
+
def processor_options
|
61
|
+
args = {}
|
62
|
+
@other_args.each do |k,v|
|
63
|
+
args[k] = v.respond_to?(:call) ? v.call(attachment) : v
|
64
|
+
end
|
65
|
+
[:processors, :geometry, :format, :whiny, :convert_options].each do |k|
|
66
|
+
(arg = send(k)) && args[k] = arg
|
67
|
+
end
|
68
|
+
args
|
69
|
+
end
|
70
|
+
|
71
|
+
# Supports getting and setting style properties with hash notation to ensure backwards-compatibility
|
72
|
+
# eg. @attachment.styles[:large][:geometry]@ will still work
|
73
|
+
def [](key)
|
74
|
+
if [:name, :convert_options, :whiny, :processors, :geometry, :format].include?(key)
|
75
|
+
send(key)
|
76
|
+
elsif defined? @other_args[key]
|
77
|
+
@other_args[key]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def []=(key, value)
|
82
|
+
if [:name, :convert_options, :whiny, :processors, :geometry, :format].include?(key)
|
83
|
+
send("#{key}=".intern, value)
|
84
|
+
else
|
85
|
+
@other_args[key] = value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|