file_column_with_s3 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README +4 -2
- data/Rakefile +0 -2
- data/lib/file_column.rb +2 -10
- data/lib/file_column/validations.rb +9 -47
- data/lib/file_column_helper.rb +0 -66
- data/lib/rails_file_column.rb +1 -1
- data/test/abstract_unit.rb +14 -8
- data/test/connection.rb +1 -1
- data/test/file_column_helper_test.rb +9 -5
- data/test/file_column_test.rb +30 -33
- data/test/fixtures/entry.rb +5 -8
- metadata +36 -52
- data/lib/magick_file_column.rb +0 -265
- data/test/magick_test.rb +0 -383
- data/test/magick_view_only_test.rb +0 -21
data/test/fixtures/entry.rb
CHANGED
@@ -1,19 +1,16 @@
|
|
1
1
|
class Entry < ActiveRecord::Base
|
2
|
-
attr_accessor :validation_should_fail
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
end
|
7
|
-
|
3
|
+
after_save :after_save_method
|
4
|
+
|
8
5
|
def after_assign
|
9
6
|
@after_assign_called = true
|
10
7
|
end
|
11
|
-
|
8
|
+
|
12
9
|
def after_assign_called?
|
13
10
|
@after_assign_called
|
14
11
|
end
|
15
|
-
|
16
|
-
def
|
12
|
+
|
13
|
+
def after_save_method
|
17
14
|
@after_save_called = true
|
18
15
|
end
|
19
16
|
|
metadata
CHANGED
@@ -1,100 +1,86 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: file_column_with_s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mingle SaaS team
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: mingle-storage
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
16
15
|
requirements:
|
17
16
|
- - "~>"
|
18
17
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
20
|
-
|
18
|
+
version: '0.1'
|
19
|
+
name: mingle-storage
|
21
20
|
prerelease: false
|
21
|
+
type: :runtime
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: '0.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: rails
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
30
29
|
requirements:
|
31
|
-
- - "
|
30
|
+
- - "~>"
|
32
31
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
|
32
|
+
version: '5.0'
|
33
|
+
name: activesupport
|
35
34
|
prerelease: false
|
35
|
+
type: :runtime
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '5.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: sqlite3
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
44
43
|
requirements:
|
45
|
-
- - "
|
44
|
+
- - "~>"
|
46
45
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
|
46
|
+
version: '5.0'
|
47
|
+
name: actionview
|
49
48
|
prerelease: false
|
49
|
+
type: :runtime
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '5.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: rmagick
|
57
56
|
requirement: !ruby/object:Gem::Requirement
|
58
57
|
requirements:
|
59
|
-
- - "
|
58
|
+
- - "~>"
|
60
59
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
|
60
|
+
version: '5.0'
|
61
|
+
name: actionpack
|
63
62
|
prerelease: false
|
63
|
+
type: :runtime
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '5.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name: aws-sdk
|
71
70
|
requirement: !ruby/object:Gem::Requirement
|
72
71
|
requirements:
|
73
|
-
- - "
|
72
|
+
- - "~>"
|
74
73
|
- !ruby/object:Gem::Version
|
75
74
|
version: '0'
|
76
|
-
|
75
|
+
name: jdbc-sqlite3
|
77
76
|
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: nokogiri
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - '='
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: 1.5.11
|
90
77
|
type: :development
|
91
|
-
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
|
-
- -
|
80
|
+
- - "~>"
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
97
|
-
description:
|
82
|
+
version: '0'
|
83
|
+
description:
|
98
84
|
email: mingle.saas@thoughtworks.com
|
99
85
|
executables: []
|
100
86
|
extensions: []
|
@@ -107,7 +93,6 @@ files:
|
|
107
93
|
- lib/file_column/validations.rb
|
108
94
|
- lib/file_column_helper.rb
|
109
95
|
- lib/file_compat.rb
|
110
|
-
- lib/magick_file_column.rb
|
111
96
|
- lib/rails_file_column.rb
|
112
97
|
- lib/test_case.rb
|
113
98
|
- s3_env.example
|
@@ -121,12 +106,11 @@ files:
|
|
121
106
|
- test/fixtures/mysql.sql
|
122
107
|
- test/fixtures/schema.rb
|
123
108
|
- test/fixtures/skanthak.png
|
124
|
-
- test/magick_test.rb
|
125
|
-
- test/magick_view_only_test.rb
|
126
109
|
homepage: https://github.com/ThoughtWorksStudios/file_column
|
127
|
-
licenses:
|
110
|
+
licenses:
|
111
|
+
- MIT
|
128
112
|
metadata: {}
|
129
|
-
post_install_message:
|
113
|
+
post_install_message:
|
130
114
|
rdoc_options: []
|
131
115
|
require_paths:
|
132
116
|
- lib
|
@@ -141,9 +125,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
125
|
- !ruby/object:Gem::Version
|
142
126
|
version: '0'
|
143
127
|
requirements: []
|
144
|
-
rubyforge_project:
|
145
|
-
rubygems_version: 2.
|
146
|
-
signing_key:
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 2.6.13
|
130
|
+
signing_key:
|
147
131
|
specification_version: 4
|
148
132
|
summary: File attachment library for ruby
|
149
133
|
test_files: []
|
data/lib/magick_file_column.rb
DELETED
@@ -1,265 +0,0 @@
|
|
1
|
-
module FileColumn # :nodoc:
|
2
|
-
|
3
|
-
class BaseUploadedFile # :nodoc:
|
4
|
-
def transform_with_magick
|
5
|
-
if needs_transform?
|
6
|
-
begin
|
7
|
-
img = ::Magick::Image::read(absolute_path).first
|
8
|
-
rescue ::Magick::ImageMagickError
|
9
|
-
if options[:magick][:image_required]
|
10
|
-
@magick_errors ||= []
|
11
|
-
@magick_errors << "invalid image"
|
12
|
-
end
|
13
|
-
return
|
14
|
-
end
|
15
|
-
|
16
|
-
if options[:magick][:versions]
|
17
|
-
options[:magick][:versions].each_pair do |version, version_options|
|
18
|
-
next if version_options[:lazy]
|
19
|
-
dirname = version_options[:name]
|
20
|
-
FileUtils.mkdir_p File.join(@dir, dirname)
|
21
|
-
transform_image(img, version_options, absolute_path(dirname))
|
22
|
-
end
|
23
|
-
end
|
24
|
-
if options[:magick][:size] or options[:magick][:crop] or options[:magick][:transformation] or options[:magick][:attributes]
|
25
|
-
transform_image(img, options[:magick], absolute_path)
|
26
|
-
end
|
27
|
-
|
28
|
-
GC.start
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def create_magick_version_if_needed(version)
|
33
|
-
# RMagick might not have been loaded so far.
|
34
|
-
# We do not want to require it on every call of this method
|
35
|
-
# as this might be fairly expensive, so we just try if ::Magick
|
36
|
-
# exists and require it if not.
|
37
|
-
begin
|
38
|
-
::Magick
|
39
|
-
rescue NameError
|
40
|
-
require 'RMagick'
|
41
|
-
end
|
42
|
-
|
43
|
-
if version.is_a?(Symbol)
|
44
|
-
version_options = options[:magick][:versions][version]
|
45
|
-
else
|
46
|
-
version_options = MagickExtension::process_options(version)
|
47
|
-
end
|
48
|
-
|
49
|
-
unless File.exists?(absolute_path(version_options[:name]))
|
50
|
-
begin
|
51
|
-
img = ::Magick::Image::read(absolute_path).first
|
52
|
-
rescue ::Magick::ImageMagickError
|
53
|
-
# we might be called directly from the view here
|
54
|
-
# so we just return nil if we cannot load the image
|
55
|
-
return nil
|
56
|
-
end
|
57
|
-
dirname = version_options[:name]
|
58
|
-
FileUtils.mkdir_p File.join(@dir, dirname)
|
59
|
-
transform_image(img, version_options, absolute_path(dirname))
|
60
|
-
end
|
61
|
-
|
62
|
-
version_options[:name]
|
63
|
-
end
|
64
|
-
|
65
|
-
attr_reader :magick_errors
|
66
|
-
|
67
|
-
def has_magick_errors?
|
68
|
-
@magick_errors and !@magick_errors.empty?
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def needs_transform?
|
74
|
-
options[:magick] and just_uploaded? and
|
75
|
-
(options[:magick][:size] or options[:magick][:versions] or options[:magick][:transformation] or options[:magick][:attributes])
|
76
|
-
end
|
77
|
-
|
78
|
-
def transform_image(img, img_options, dest_path)
|
79
|
-
begin
|
80
|
-
if img_options[:transformation]
|
81
|
-
if img_options[:transformation].is_a?(Symbol)
|
82
|
-
img = @instance.send(img_options[:transformation], img)
|
83
|
-
else
|
84
|
-
img = img_options[:transformation].call(img)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
if img_options[:crop]
|
88
|
-
dx, dy = img_options[:crop].split(':').map { |x| x.to_f }
|
89
|
-
w, h = (img.rows * dx / dy), (img.columns * dy / dx)
|
90
|
-
img = img.crop(::Magick::CenterGravity, [img.columns, w].min,
|
91
|
-
[img.rows, h].min, true)
|
92
|
-
end
|
93
|
-
|
94
|
-
if img_options[:size]
|
95
|
-
img = img.change_geometry(img_options[:size]) do |c, r, i|
|
96
|
-
i.resize(c, r)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
if img_options[:letterbox]
|
101
|
-
w, h = img_options[:letterbox].split('x').map { |x| x.to_f }
|
102
|
-
img = img.crop((img.columns/2 - w/2), (img.rows/2 - h/2), w, h)
|
103
|
-
end
|
104
|
-
ensure
|
105
|
-
img.write(dest_path) do
|
106
|
-
if img_options[:attributes]
|
107
|
-
img_options[:attributes].each_pair do |property, value|
|
108
|
-
self.send "#{property}=", value
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
File.chmod options[:permissions], dest_path
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# If you are using file_column to upload images, you can
|
118
|
-
# directly process the images with RMagick,
|
119
|
-
# a ruby extension
|
120
|
-
# for accessing the popular imagemagick libraries. You can find
|
121
|
-
# more information about RMagick at http://rmagick.rubyforge.org.
|
122
|
-
#
|
123
|
-
# You can control what to do by adding a <tt>:magick</tt> option
|
124
|
-
# to your options hash. All operations are performed immediately
|
125
|
-
# after a new file is assigned to the file_column attribute (i.e.,
|
126
|
-
# when a new file has been uploaded).
|
127
|
-
#
|
128
|
-
# == Resizing images
|
129
|
-
#
|
130
|
-
# To resize the uploaded image according to an imagemagick geometry
|
131
|
-
# string, just use the <tt>:size</tt> option:
|
132
|
-
#
|
133
|
-
# file_column :image, :magick => {:size => "800x600>"}
|
134
|
-
#
|
135
|
-
# If the uploaded file cannot be loaded by RMagick, file_column will
|
136
|
-
# signal a validation error for the corresponding attribute. If you
|
137
|
-
# want to allow non-image files to be uploaded in a column that uses
|
138
|
-
# the <tt>:magick</tt> option, you can set the <tt>:image_required</tt>
|
139
|
-
# attribute to +false+:
|
140
|
-
#
|
141
|
-
# file_column :image, :magick => {:size => "800x600>",
|
142
|
-
# :image_required => false }
|
143
|
-
#
|
144
|
-
# == Multiple versions
|
145
|
-
#
|
146
|
-
# You can also create additional versions of your image, for example
|
147
|
-
# thumb-nails, like this:
|
148
|
-
# file_column :image, :magick => {:versions => {
|
149
|
-
# :thumb => {:size => "50x50"},
|
150
|
-
# :medium => {:size => "640x480>"}
|
151
|
-
# }
|
152
|
-
#
|
153
|
-
# These versions will be stored in separate sub-directories, named like the
|
154
|
-
# symbol you used to identify the version. So in the previous example, the
|
155
|
-
# image versions will be stored in "thumb", "screen" and "widescreen"
|
156
|
-
# directories, resp.
|
157
|
-
# A name different from the symbol can be set via the <tt>:name</tt> option.
|
158
|
-
#
|
159
|
-
# These versions can be accessed via FileColumnHelper's +url_for_image_column+
|
160
|
-
# method like this:
|
161
|
-
#
|
162
|
-
# <%= url_for_image_column "entry", "image", :thumb %>
|
163
|
-
#
|
164
|
-
# == Cropping images
|
165
|
-
#
|
166
|
-
# If you wish to crop your images with a size ratio before scaling
|
167
|
-
# them according to your version geometry, you can use the :crop directive.
|
168
|
-
# file_column :image, :magick => {:versions => {
|
169
|
-
# :square => {:crop => "1:1", :size => "50x50", :name => "thumb"},
|
170
|
-
# :screen => {:crop => "4:3", :size => "640x480>"},
|
171
|
-
# :widescreen => {:crop => "16:9", :size => "640x360!"},
|
172
|
-
# }
|
173
|
-
# }
|
174
|
-
#
|
175
|
-
# == Custom attributes
|
176
|
-
#
|
177
|
-
# To change some of the image properties like compression level before they
|
178
|
-
# are saved you can set the <tt>:attributes</tt> option.
|
179
|
-
# For a list of available attributes go to http://www.simplesystems.org/RMagick/doc/info.html
|
180
|
-
#
|
181
|
-
# file_column :image, :magick => { :attributes => { :quality => 30 } }
|
182
|
-
#
|
183
|
-
# == Custom transformations
|
184
|
-
#
|
185
|
-
# To perform custom transformations on uploaded images, you can pass a
|
186
|
-
# callback to file_column:
|
187
|
-
# file_column :image, :magick =>
|
188
|
-
# Proc.new { |image| image.quantize(256, Magick::GRAYColorspace) }
|
189
|
-
#
|
190
|
-
# The callback you give, receives one argument, which is an instance
|
191
|
-
# of Magick::Image, the RMagick image class. It should return a transformed
|
192
|
-
# image. Instead of passing a <tt>Proc</tt> object, you can also give a
|
193
|
-
# <tt>Symbol</tt>, the name of an instance method of your model.
|
194
|
-
#
|
195
|
-
# Custom transformations can be combined via the standard :size and :crop
|
196
|
-
# features, by using the :transformation option:
|
197
|
-
# file_column :image, :magick => {
|
198
|
-
# :transformation => Proc.new { |image| ... },
|
199
|
-
# :size => "640x480"
|
200
|
-
# }
|
201
|
-
#
|
202
|
-
# In this case, the standard resizing operations will be performed after the
|
203
|
-
# custom transformation.
|
204
|
-
#
|
205
|
-
# Of course, custom transformations can be used in versions, as well.
|
206
|
-
#
|
207
|
-
# <b>Note:</b> You'll need the
|
208
|
-
# RMagick extension being installed in order to use file_column's
|
209
|
-
# imagemagick integration.
|
210
|
-
module MagickExtension
|
211
|
-
|
212
|
-
def self.file_column(klass, attr, options) # :nodoc:
|
213
|
-
require 'RMagick'
|
214
|
-
options[:magick] = process_options(options[:magick],false) if options[:magick]
|
215
|
-
if options[:magick][:versions]
|
216
|
-
options[:magick][:versions].each_pair do |name, value|
|
217
|
-
options[:magick][:versions][name] = process_options(value, name.to_s)
|
218
|
-
end
|
219
|
-
end
|
220
|
-
state_method = "#{attr}_state".to_sym
|
221
|
-
after_assign_method = "#{attr}_magick_after_assign".to_sym
|
222
|
-
|
223
|
-
klass.send(:define_method, after_assign_method) do
|
224
|
-
self.send(state_method).transform_with_magick
|
225
|
-
end
|
226
|
-
|
227
|
-
options[:after_upload] ||= []
|
228
|
-
options[:after_upload] << after_assign_method
|
229
|
-
|
230
|
-
klass.validate do |record|
|
231
|
-
state = record.send(state_method)
|
232
|
-
if state.has_magick_errors?
|
233
|
-
state.magick_errors.each do |error|
|
234
|
-
record.errors.add attr, error
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
|
241
|
-
def self.process_options(options,create_name=true)
|
242
|
-
case options
|
243
|
-
when String then options = {:size => options}
|
244
|
-
when Proc, Symbol then options = {:transformation => options }
|
245
|
-
end
|
246
|
-
if options[:geometry]
|
247
|
-
options[:size] = options.delete(:geometry)
|
248
|
-
end
|
249
|
-
options[:image_required] = true unless options.key?(:image_required)
|
250
|
-
if options[:name].nil? and create_name
|
251
|
-
if create_name == true
|
252
|
-
hash = 0
|
253
|
-
for key in [:size, :crop]
|
254
|
-
hash = hash ^ options[key].hash if options[key]
|
255
|
-
end
|
256
|
-
options[:name] = hash.abs.to_s(36)
|
257
|
-
else
|
258
|
-
options[:name] = create_name
|
259
|
-
end
|
260
|
-
end
|
261
|
-
options
|
262
|
-
end
|
263
|
-
|
264
|
-
end
|
265
|
-
end
|