paperclip 2.4.3 → 2.4.4

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.md CHANGED
@@ -96,7 +96,7 @@ In your migrations:
96
96
 
97
97
  In your edit and new views:
98
98
 
99
- <% form_for :user, @user, :url => user_path, :html => { :multipart => true } do |form| %>
99
+ <%= form_for :user, @user, :url => user_path, :html => { :multipart => true } do |form| %>
100
100
  <%= form.file_field :avatar %>
101
101
  <% end %>
102
102
 
@@ -234,10 +234,22 @@ URI Obfuscation
234
234
  ---------------
235
235
 
236
236
  Paperclip has an interpolation called `:hash` for obfuscating filenames of
237
- publicly-available files. For more on this feature read the author's own
238
- explanation.
237
+ publicly-available files.
239
238
 
240
- [https://github.com/thoughtbot/paperclip/pull/416](https://github.com/thoughtbot/paperclip/pull/416)
239
+ Example Usage:
240
+
241
+ has_attached_file :avatar, {
242
+ :url => "/system/:hash.:extension",
243
+ :hash_secret => "longSecretString"
244
+ }
245
+
246
+
247
+ The `:hash` interpolation will be replaced with a unique hash made up of whatever
248
+ is specified in `:hash_data`. The default value for `:hash_data` is `":class/:attachment/:id/:style/:updated_at"`.
249
+
250
+ `:hash_secret` is required, an exception will be raised if `:hash` is used without `:hash_secret` present.
251
+
252
+ For more on this feature read the author's own explanation. [https://github.com/thoughtbot/paperclip/pull/416](https://github.com/thoughtbot/paperclip/pull/416)
241
253
 
242
254
  MD5 Checksum / Fingerprint
243
255
  -------
@@ -78,29 +78,28 @@ module Paperclip
78
78
  Paperclip::Interpolations[key] = block
79
79
  end
80
80
 
81
- # The run method takes a command to execute and an array of parameters
82
- # that get passed to it. The command is prefixed with the :command_path
83
- # option from Paperclip.options. If you have many commands to run and
84
- # they are in different paths, the suggested course of action is to
85
- # symlink them so they are all in the same directory.
81
+ # The run method takes the name of a binary to run, the arguments to that binary
82
+ # and some options:
86
83
  #
87
- # If the command returns with a result code that is not one of the
88
- # expected_outcodes, a Cocaine::CommandLineError will be raised. Generally
89
- # a code of 0 is expected, but a list of codes may be passed if necessary.
90
- # These codes should be passed as a hash as the last argument, like so:
84
+ # :command_path -> A $PATH-like variable that defines where to look for the binary
85
+ # on the filesystem. Colon-separated, just like $PATH.
91
86
  #
92
- # Paperclip.run("echo", "something", :expected_outcodes => [0,1,2,3])
87
+ # :expected_outcodes -> An array of integers that defines the expected exit codes
88
+ # of the binary. Defaults to [0].
93
89
  #
94
- # This method can log the command being run when
95
- # Paperclip.options[:log_command] is set to true (defaults to false). This
96
- # will only log if logging in general is set to true as well.
97
- def run(cmd, *params)
90
+ # :log_command -> Log the command being run when set to true (defaults to false).
91
+ # This will only log if logging in general is set to true as well.
92
+ #
93
+ # :swallow_stderr -> Set to true if you don't care what happens on STDERR.
94
+ #
95
+ def run(cmd, arguments = "", local_options = {})
98
96
  if options[:image_magick_path]
99
97
  Paperclip.log("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead")
100
98
  end
101
99
  command_path = options[:command_path] || options[:image_magick_path]
102
100
  Cocaine::CommandLine.path = ( Cocaine::CommandLine.path ? [Cocaine::CommandLine.path, command_path ].flatten : command_path )
103
- Cocaine::CommandLine.new(cmd, *params).run
101
+ local_options = local_options.merge(:logger => logger) if logging? && (options[:log_command] || local_options[:log_command])
102
+ Cocaine::CommandLine.new(cmd, arguments, local_options).run
104
103
  end
105
104
 
106
105
  def processor(name) #:nodoc:
@@ -131,7 +131,9 @@ module Paperclip
131
131
  def url(style_name = default_style, use_timestamp = @options.use_timestamp)
132
132
  default_url = @options.default_url.is_a?(Proc) ? @options.default_url.call(self) : @options.default_url
133
133
  url = original_filename.nil? ? interpolate(default_url, style_name) : interpolate(@options.url, style_name)
134
- URI.escape(use_timestamp && updated_at ? [url, updated_at].compact.join(url.include?("?") ? "&" : "?") : url)
134
+
135
+ url << (url.include?("?") ? "&" : "?") + updated_at.to_s if use_timestamp && updated_at
136
+ url.respond_to?(:escape) ? url.escape : URI.escape(url)
135
137
  end
136
138
 
137
139
  # Returns the path of the attachment as defined by the :path option. If the
@@ -139,7 +141,8 @@ module Paperclip
139
141
  # on disk. If the file is stored in S3, the path is the "key" part of the
140
142
  # URL, and the :bucket option refers to the S3 bucket.
141
143
  def path(style_name = default_style)
142
- original_filename.nil? ? nil : interpolate(@options.path, style_name)
144
+ path = original_filename.nil? ? nil : interpolate(@options.path, style_name)
145
+ path.respond_to?(:unescape) ? path.unescape : path
143
146
  end
144
147
 
145
148
  # Alias to +url+
@@ -0,0 +1,33 @@
1
+ require 'uri'
2
+
3
+ module Paperclip
4
+ class InterpolatedString < String
5
+ def escaped?
6
+ !!@escaped
7
+ end
8
+
9
+ def escape
10
+ if !escaped?
11
+ escaped_string = self.class.new(URI.escape(self))
12
+ escaped_string.instance_variable_set(:@escaped, true)
13
+ escaped_string
14
+ else
15
+ self
16
+ end
17
+ end
18
+
19
+ def unescape
20
+ if escaped?
21
+ escaped_string = self.class.new(URI.unescape(self))
22
+ escaped_string.instance_variable_set(:@escaped, false)
23
+ escaped_string
24
+ else
25
+ self
26
+ end
27
+ end
28
+
29
+ def force_escape
30
+ @escaped = true
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,5 @@
1
+ require 'paperclip/interpolated_string'
2
+
1
3
  module Paperclip
2
4
  # This module contains all the methods that are available for interpolation
3
5
  # in paths and urls. To add your own (or override an existing one), you
@@ -29,11 +31,13 @@ module Paperclip
29
31
  # an interpolation pattern for Paperclip to use.
30
32
  def self.interpolate pattern, *args
31
33
  pattern = args.first.instance.send(pattern) if pattern.kind_of? Symbol
32
- all.reverse.inject( pattern.dup ) do |result, tag|
34
+ interpolated_string = all.reverse.inject(InterpolatedString.new(pattern)) do |result, tag|
33
35
  result.gsub(/:#{tag}/) do |match|
34
36
  send( tag, *args )
35
37
  end
36
38
  end
39
+ interpolated_string.force_escape if pattern =~ /:url/
40
+ interpolated_string
37
41
  end
38
42
 
39
43
  # Returns the filename, the same way as ":basename.:extension" would.
@@ -86,7 +90,7 @@ module Paperclip
86
90
 
87
91
  # Returns the basename of the file. e.g. "file" for "file.jpg"
88
92
  def basename attachment, style_name
89
- attachment.original_filename.gsub(/#{File.extname(attachment.original_filename)}$/, "")
93
+ attachment.original_filename.gsub(/#{Regexp.escape(File.extname(attachment.original_filename))}$/, "")
90
94
  end
91
95
 
92
96
  # Returns the extension of the file. e.g. "jpg" for "file.jpg"
@@ -54,7 +54,7 @@ module Paperclip
54
54
  end
55
55
 
56
56
  def method_missing(method, *args, &blk)
57
- if method.to_s[-1] == "="
57
+ if method.to_s[-1,1] == "="
58
58
  instance_variable_set("@#{method[0..-2]}", args[0])
59
59
  else
60
60
  instance_variable_get("@#{method}")
@@ -86,7 +86,7 @@ module Paperclip
86
86
  @s3_headers = @options.s3_headers || {}
87
87
 
88
88
  unless @options.url.to_s.match(/^:s3.*url$/) || @options.url == ":asset_host"
89
- @options.path = @options.path.gsub(/:url/, @options.url)
89
+ @options.path = @options.path.gsub(/:url/, @options.url).gsub(/^:rails_root\/public\/system/, '')
90
90
  @options.url = ":s3_path_url"
91
91
  end
92
92
  @options.url = @options.url.inspect if @options.url.is_a?(Symbol)
@@ -1,3 +1,3 @@
1
1
  module Paperclip
2
- VERSION = "2.4.3" unless defined? Paperclip::VERSION
2
+ VERSION = "2.4.4" unless defined? Paperclip::VERSION
3
3
  end
@@ -73,7 +73,7 @@ namespace :paperclip do
73
73
  ENV['STYLES'] = missing_styles.join(',')
74
74
  Rake::Task['paperclip:refresh:thumbnails'].execute
75
75
  end
76
- end
76
+ end
77
77
  Paperclip.save_current_attachments_styles!
78
78
  end
79
79
  end
@@ -84,12 +84,16 @@ namespace :paperclip do
84
84
  names = Paperclip::Task.obtain_attachments(klass)
85
85
  names.each do |name|
86
86
  Paperclip.each_instance_with_attachment(klass, name) do |instance|
87
- instance.send(name).send(:validate)
88
- if instance.send(name).valid?
89
- true
90
- else
91
- instance.send("#{name}=", nil)
92
- instance.save
87
+ unless instance.valid?
88
+ attributes = %w(file_size file_name content_type).map{ |suffix| "#{name}_#{suffix}".to_sym }
89
+ if attributes.any?{ |attribute| instance.errors[attribute].present? }
90
+ instance.send("#{name}=", nil)
91
+ if Rails.version >= "3.0.0"
92
+ instance.save(:validate => false)
93
+ else
94
+ instance.save(false)
95
+ end
96
+ end
93
97
  end
94
98
  end
95
99
  end
@@ -0,0 +1,62 @@
1
+ require './test/helper'
2
+
3
+ class InterpolatedStringTest < Test::Unit::TestCase
4
+ context "inheritance" do
5
+ should "inherited from String" do
6
+ assert Paperclip::InterpolatedString.new("paperclip").is_a? String
7
+ end
8
+ end
9
+
10
+ context "#escape" do
11
+ subject { Paperclip::InterpolatedString.new("paperclip foo").escape }
12
+
13
+ should "returns an InterpolatedString object" do
14
+ assert subject.is_a? Paperclip::InterpolatedString
15
+ end
16
+
17
+ should "escape the output string" do
18
+ assert_equal "paperclip%20foo", subject
19
+ end
20
+
21
+ should "not double escape output string" do
22
+ assert_equal "paperclip%20foo", subject.escape
23
+ end
24
+ end
25
+
26
+ context "#unescape" do
27
+ subject { Paperclip::InterpolatedString.new("paperclip%20foo").escape.unescape }
28
+
29
+ should "returns an InterpolatedString object" do
30
+ assert subject.is_a? Paperclip::InterpolatedString
31
+ end
32
+
33
+ should "unescape the output string" do
34
+ assert_equal "paperclip%20foo", subject
35
+ end
36
+
37
+ should "not double unescape output string" do
38
+ assert_equal "paperclip%20foo", subject.unescape
39
+ end
40
+ end
41
+
42
+ context "#escaped?" do
43
+ subject { Paperclip::InterpolatedString.new("paperclip") }
44
+
45
+ should "returns true if string was escaped" do
46
+ assert subject.escape.escaped?
47
+ end
48
+
49
+ should "returns false if string wasn't escaped" do
50
+ assert !subject.escaped?
51
+ end
52
+ end
53
+
54
+ context "#force_escape" do
55
+ subject { Paperclip::InterpolatedString.new("paperclip") }
56
+ setup { subject.force_escape }
57
+
58
+ should "sets escaped flag to true" do
59
+ assert subject.escaped?
60
+ end
61
+ end
62
+ end
@@ -154,6 +154,13 @@ class InterpolationsTest < Test::Unit::TestCase
154
154
  attachment.stubs(:original_filename).returns("one")
155
155
  assert_equal "one", Paperclip::Interpolations.filename(attachment, :style)
156
156
  end
157
+
158
+ should "return the basename when the extension contains regexp special characters" do
159
+ attachment = mock
160
+ attachment.stubs(:styles).returns({})
161
+ attachment.stubs(:original_filename).returns("one.ab)")
162
+ assert_equal "one", Paperclip::Interpolations.basename(attachment, :style)
163
+ end
157
164
 
158
165
  should "return the timestamp" do
159
166
  now = Time.now
@@ -8,6 +8,13 @@ class MockAttachment < Struct.new(:one, :two)
8
8
  end
9
9
 
10
10
  class OptionsTest < Test::Unit::TestCase
11
+ should "be able to set a value" do
12
+ @options = Paperclip::Options.new(nil, {})
13
+ assert_nil @options.path
14
+ @options.path = "this/is/a/path"
15
+ assert_equal "this/is/a/path", @options.path
16
+ end
17
+
11
18
  context "#styles with a plain hash" do
12
19
  setup do
13
20
  @attachment = MockAttachment.new(nil, nil)
@@ -3,11 +3,13 @@ require './test/helper'
3
3
  class PaperclipTest < Test::Unit::TestCase
4
4
  context "Calling Paperclip.run" do
5
5
  setup do
6
- Cocaine::CommandLine.expects(:new).with("convert", "stuff").returns(stub(:run))
6
+ Paperclip.options[:log_command] = false
7
+ Cocaine::CommandLine.expects(:new).with("convert", "stuff", {}).returns(stub(:run))
7
8
  @original_command_line_path = Cocaine::CommandLine.path
8
9
  end
9
10
 
10
11
  teardown do
12
+ Paperclip.options[:log_command] = true
11
13
  Cocaine::CommandLine.path = @original_command_line_path
12
14
  end
13
15
 
@@ -22,6 +24,14 @@ class PaperclipTest < Test::Unit::TestCase
22
24
  end
23
25
  end
24
26
 
27
+ context "Calling Paperclip.run with a logger" do
28
+ should "pass the defined logger if :log_command is set" do
29
+ Paperclip.options[:log_command] = true
30
+ Cocaine::CommandLine.expects(:new).with("convert", "stuff", :logger => Paperclip.logger).returns(stub(:run))
31
+ Paperclip.run("convert", "stuff")
32
+ end
33
+ end
34
+
25
35
  context "Paperclip.each_instance_with_attachment" do
26
36
  setup do
27
37
  @file = File.new(File.join(FIXTURES_DIR, "5k.png"), 'rb')
@@ -44,6 +44,10 @@ class FileSystemTest < Test::Unit::TestCase
44
44
  assert File.exists?(@dummy.avatar.path)
45
45
  end
46
46
 
47
+ should "store the path unescaped" do
48
+ assert_match /\/spaced file\.png/, @dummy.avatar.path
49
+ end
50
+
47
51
  should "return an escaped version of URL" do
48
52
  assert_match /\/spaced%20file\.png/, @dummy.avatar.url
49
53
  end
@@ -25,7 +25,10 @@ unless ENV["S3_TEST_BUCKET"].blank?
25
25
  @dummy.avatar = @file
26
26
  end
27
27
 
28
- teardown { @file.close }
28
+ teardown do
29
+ @file.close
30
+ @dummy.destroy
31
+ end
29
32
 
30
33
  should "still return a Tempfile when sent #to_file" do
31
34
  assert_equal Paperclip::Tempfile, @dummy.avatar.to_file.class
@@ -47,5 +50,39 @@ unless ENV["S3_TEST_BUCKET"].blank?
47
50
  end
48
51
  end
49
52
  end
53
+
54
+ context "An attachment that uses S3 for storage and has spaces in file name" do
55
+ setup do
56
+ rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
57
+ :storage => :s3,
58
+ :bucket => ENV["S3_TEST_BUCKET"],
59
+ :s3_credentials => File.new(File.join(File.dirname(__FILE__), "..", "s3.yml"))
60
+
61
+ Dummy.delete_all
62
+ @dummy = Dummy.new
63
+ @dummy.avatar = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', 'spaced file.png'), 'rb')
64
+ @dummy.save
65
+ end
66
+
67
+ teardown { @dummy.destroy }
68
+
69
+ should "return an unescaped version for path" do
70
+ assert_match /.+\/spaced file\.png/, @dummy.avatar.path
71
+ end
72
+
73
+ should "return an escaped version for url" do
74
+ assert_match /.+\/spaced%20file\.png/, @dummy.avatar.url
75
+ end
76
+
77
+ should "be accessible" do
78
+ assert_match /200 OK/, `curl -I #{@dummy.avatar.url}`
79
+ end
80
+
81
+ should "be destoryable" do
82
+ url = @dummy.avatar.url
83
+ @dummy.destroy
84
+ assert_match /404 Not Found/, `curl -I #{url}`
85
+ end
86
+ end
50
87
  end
51
88
  end
@@ -116,7 +116,6 @@ class S3Test < Test::Unit::TestCase
116
116
  rebuild_model :styles => { :large => ['500x500#', :jpg] },
117
117
  :storage => :s3,
118
118
  :bucket => "bucket",
119
- :path => ":attachment/:basename.:extension",
120
119
  :s3_credentials => {
121
120
  'access_key_id' => "12345",
122
121
  'secret_access_key' => "54321"
@@ -126,7 +125,11 @@ class S3Test < Test::Unit::TestCase
126
125
  @dummy.avatar = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', 'spaced file.png'), 'rb')
127
126
  end
128
127
 
129
- should "return an escaped version of url" do
128
+ should "return an unescaped version for path" do
129
+ assert_match /.+\/spaced file\.png/, @dummy.avatar.path
130
+ end
131
+
132
+ should "return an escaped version for url" do
130
133
  assert_match /.+\/spaced%20file\.png/, @dummy.avatar.url
131
134
  end
132
135
  end
metadata CHANGED
@@ -1,144 +1,191 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: paperclip
3
- version: !ruby/object:Gem::Version
4
- version: 2.4.3
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
5
  prerelease:
6
+ segments:
7
+ - 2
8
+ - 4
9
+ - 4
10
+ version: 2.4.4
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Jon Yurek
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2011-10-05 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2011-10-14 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: activerecord
16
- requirement: &70187246781180 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 2
31
+ - 3
32
+ - 0
21
33
  version: 2.3.0
22
34
  type: :runtime
23
- prerelease: false
24
- version_requirements: *70187246781180
25
- - !ruby/object:Gem::Dependency
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
26
37
  name: activesupport
27
- requirement: &70187246780680 !ruby/object:Gem::Requirement
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
28
40
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 7
45
+ segments:
46
+ - 2
47
+ - 3
48
+ - 2
32
49
  version: 2.3.2
33
50
  type: :runtime
34
- prerelease: false
35
- version_requirements: *70187246780680
36
- - !ruby/object:Gem::Dependency
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
37
53
  name: cocaine
38
- requirement: &70187246780220 !ruby/object:Gem::Requirement
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
39
56
  none: false
40
- requirements:
41
- - - ! '>='
42
- - !ruby/object:Gem::Version
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 27
61
+ segments:
62
+ - 0
63
+ - 0
64
+ - 2
43
65
  version: 0.0.2
44
66
  type: :runtime
45
- prerelease: false
46
- version_requirements: *70187246780220
47
- - !ruby/object:Gem::Dependency
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
48
69
  name: mime-types
49
- requirement: &70187246779840 !ruby/object:Gem::Requirement
70
+ prerelease: false
71
+ requirement: &id004 !ruby/object:Gem::Requirement
50
72
  none: false
51
- requirements:
52
- - - ! '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
55
80
  type: :runtime
56
- prerelease: false
57
- version_requirements: *70187246779840
58
- - !ruby/object:Gem::Dependency
81
+ version_requirements: *id004
82
+ - !ruby/object:Gem::Dependency
59
83
  name: shoulda
60
- requirement: &70187246779380 !ruby/object:Gem::Requirement
84
+ prerelease: false
85
+ requirement: &id005 !ruby/object:Gem::Requirement
61
86
  none: false
62
- requirements:
63
- - - ! '>='
64
- - !ruby/object:Gem::Version
65
- version: '0'
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
66
94
  type: :development
67
- prerelease: false
68
- version_requirements: *70187246779380
69
- - !ruby/object:Gem::Dependency
95
+ version_requirements: *id005
96
+ - !ruby/object:Gem::Dependency
70
97
  name: appraisal
71
- requirement: &70187246778960 !ruby/object:Gem::Requirement
98
+ prerelease: false
99
+ requirement: &id006 !ruby/object:Gem::Requirement
72
100
  none: false
73
- requirements:
74
- - - ! '>='
75
- - !ruby/object:Gem::Version
76
- version: '0'
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
77
108
  type: :development
78
- prerelease: false
79
- version_requirements: *70187246778960
80
- - !ruby/object:Gem::Dependency
109
+ version_requirements: *id006
110
+ - !ruby/object:Gem::Dependency
81
111
  name: mocha
82
- requirement: &70187246778540 !ruby/object:Gem::Requirement
112
+ prerelease: false
113
+ requirement: &id007 !ruby/object:Gem::Requirement
83
114
  none: false
84
- requirements:
85
- - - ! '>='
86
- - !ruby/object:Gem::Version
87
- version: '0'
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ hash: 3
119
+ segments:
120
+ - 0
121
+ version: "0"
88
122
  type: :development
89
- prerelease: false
90
- version_requirements: *70187246778540
91
- - !ruby/object:Gem::Dependency
123
+ version_requirements: *id007
124
+ - !ruby/object:Gem::Dependency
92
125
  name: aws-s3
93
- requirement: &70187246778120 !ruby/object:Gem::Requirement
126
+ prerelease: false
127
+ requirement: &id008 !ruby/object:Gem::Requirement
94
128
  none: false
95
- requirements:
96
- - - ! '>='
97
- - !ruby/object:Gem::Version
98
- version: '0'
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
135
+ version: "0"
99
136
  type: :development
100
- prerelease: false
101
- version_requirements: *70187246778120
102
- - !ruby/object:Gem::Dependency
137
+ version_requirements: *id008
138
+ - !ruby/object:Gem::Dependency
103
139
  name: sqlite3
104
- requirement: &70187246777700 !ruby/object:Gem::Requirement
140
+ prerelease: false
141
+ requirement: &id009 !ruby/object:Gem::Requirement
105
142
  none: false
106
- requirements:
107
- - - ! '>='
108
- - !ruby/object:Gem::Version
109
- version: '0'
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ hash: 3
147
+ segments:
148
+ - 0
149
+ version: "0"
110
150
  type: :development
111
- prerelease: false
112
- version_requirements: *70187246777700
113
- - !ruby/object:Gem::Dependency
151
+ version_requirements: *id009
152
+ - !ruby/object:Gem::Dependency
114
153
  name: cucumber
115
- requirement: &70187246797740 !ruby/object:Gem::Requirement
154
+ prerelease: false
155
+ requirement: &id010 !ruby/object:Gem::Requirement
116
156
  none: false
117
- requirements:
118
- - - ! '>='
119
- - !ruby/object:Gem::Version
120
- version: '0'
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ hash: 3
161
+ segments:
162
+ - 0
163
+ version: "0"
121
164
  type: :development
122
- prerelease: false
123
- version_requirements: *70187246797740
124
- - !ruby/object:Gem::Dependency
165
+ version_requirements: *id010
166
+ - !ruby/object:Gem::Dependency
125
167
  name: capybara
126
- requirement: &70187246797320 !ruby/object:Gem::Requirement
168
+ prerelease: false
169
+ requirement: &id011 !ruby/object:Gem::Requirement
127
170
  none: false
128
- requirements:
129
- - - ! '>='
130
- - !ruby/object:Gem::Version
131
- version: '0'
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ hash: 3
175
+ segments:
176
+ - 0
177
+ version: "0"
132
178
  type: :development
133
- prerelease: false
134
- version_requirements: *70187246797320
179
+ version_requirements: *id011
135
180
  description: Easy upload management for ActiveRecord
136
181
  email: jyurek@thoughtbot.com
137
182
  executables: []
183
+
138
184
  extensions: []
139
- extra_rdoc_files:
185
+
186
+ extra_rdoc_files:
140
187
  - README.md
141
- files:
188
+ files:
142
189
  - README.md
143
190
  - LICENSE
144
191
  - Rakefile
@@ -149,6 +196,7 @@ files:
149
196
  - lib/paperclip/attachment.rb
150
197
  - lib/paperclip/callback_compatibility.rb
151
198
  - lib/paperclip/geometry.rb
199
+ - lib/paperclip/interpolated_string.rb
152
200
  - lib/paperclip/interpolations.rb
153
201
  - lib/paperclip/iostream.rb
154
202
  - lib/paperclip/matchers/have_attached_file_matcher.rb
@@ -187,6 +235,7 @@ files:
187
235
  - test/geometry_test.rb
188
236
  - test/helper.rb
189
237
  - test/integration_test.rb
238
+ - test/interpolated_string_test.rb
190
239
  - test/interpolations_test.rb
191
240
  - test/iostream_test.rb
192
241
  - test/matchers/have_attached_file_matcher_test.rb
@@ -210,25 +259,32 @@ files:
210
259
  - shoulda_macros/paperclip.rb
211
260
  homepage: https://github.com/thoughtbot/paperclip
212
261
  licenses: []
262
+
213
263
  post_install_message:
214
- rdoc_options:
264
+ rdoc_options:
215
265
  - --line-numbers
216
266
  - --inline-source
217
- require_paths:
267
+ require_paths:
218
268
  - lib
219
- required_ruby_version: !ruby/object:Gem::Requirement
269
+ required_ruby_version: !ruby/object:Gem::Requirement
220
270
  none: false
221
- requirements:
222
- - - ! '>='
223
- - !ruby/object:Gem::Version
224
- version: '0'
225
- required_rubygems_version: !ruby/object:Gem::Requirement
271
+ requirements:
272
+ - - ">="
273
+ - !ruby/object:Gem::Version
274
+ hash: 3
275
+ segments:
276
+ - 0
277
+ version: "0"
278
+ required_rubygems_version: !ruby/object:Gem::Requirement
226
279
  none: false
227
- requirements:
228
- - - ! '>='
229
- - !ruby/object:Gem::Version
230
- version: '0'
231
- requirements:
280
+ requirements:
281
+ - - ">="
282
+ - !ruby/object:Gem::Version
283
+ hash: 3
284
+ segments:
285
+ - 0
286
+ version: "0"
287
+ requirements:
232
288
  - ImageMagick
233
289
  rubyforge_project: paperclip
234
290
  rubygems_version: 1.8.10
@@ -236,3 +292,4 @@ signing_key:
236
292
  specification_version: 3
237
293
  summary: File attachments as attributes for ActiveRecord
238
294
  test_files: []
295
+