file_column_with_s3 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|