has_image 0.3.0 → 0.4.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.
- data/Changelog.md +100 -0
- data/MIT-LICENSE +15 -17
- data/README.md +159 -0
- data/Rakefile +6 -38
- data/lib/has_image.rb +31 -12
- data/lib/has_image/processor.rb +17 -18
- data/lib/has_image/railtie.rb +7 -0
- data/lib/has_image/storage.rb +31 -31
- data/lib/has_image/version.rb +3 -0
- data/lib/has_image/view_helpers.rb +3 -6
- data/{test_rails → test}/complex_pic_test.rb +10 -5
- data/{test_rails → test}/fixtures/bad_image.jpg +0 -0
- data/{test_rails → test}/fixtures/image.jpg +0 -0
- data/{test_rails → test}/fixtures/image.png +0 -0
- data/{test_rails → test}/pic_test.rb +4 -3
- data/test/processor_test.rb +9 -10
- data/test/storage_test.rb +28 -29
- data/test/test_helper.rb +47 -0
- metadata +92 -35
- data/CHANGELOG +0 -72
- data/FAQ +0 -25
- data/README.textile +0 -193
- data/init.rb +0 -1
- data/test_rails/database.yml +0 -3
- data/test_rails/schema.rb +0 -15
- data/test_rails/test_helper.rb +0 -52
data/Changelog.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
## 0.4.0 (2010-09-29)
|
2
|
+
|
3
|
+
We have picked up maintainence of has\_image after a few years of neglect. This
|
4
|
+
is a transitional release which adds Rails 3 compatibility and a few small bug
|
5
|
+
fixes, as well as the following:
|
6
|
+
|
7
|
+
* Allow passing `nil` to avoid resizing.
|
8
|
+
|
9
|
+
## Older changes
|
10
|
+
|
11
|
+
### 2009-03-11
|
12
|
+
|
13
|
+
* Fix a critical problem with image updates breaking when used together with
|
14
|
+
Rails' partial updates feature (now "on" by default). Thanks to Juan
|
15
|
+
Schwindt <juan@schwindt.org> for the report.
|
16
|
+
* Replaced a raw SQL call with update_all.
|
17
|
+
|
18
|
+
### 2008-10-22
|
19
|
+
|
20
|
+
* Added option to not delete images on destroy
|
21
|
+
* Made thumbnail name separator configurable
|
22
|
+
* Added height/width methods to storage
|
23
|
+
* Allowed regenerating only one thumbnail size
|
24
|
+
* Made has_image column configurable
|
25
|
+
* Added some compatibility with attachment_fu
|
26
|
+
* General refactorings and overall code improvement
|
27
|
+
|
28
|
+
### 2008-10-22
|
29
|
+
|
30
|
+
* Documentation improvements and minor code cleanups.
|
31
|
+
|
32
|
+
### 2008-10-09
|
33
|
+
|
34
|
+
* Fixed display of images with special symbols in the name,
|
35
|
+
like '2777-nipple-+-apple-napple.jpg'. + is reserved by HTTP.
|
36
|
+
Now escaping filenames before giving them back in #public_path()
|
37
|
+
|
38
|
+
### 2008-09-10
|
39
|
+
|
40
|
+
* Fixed images not being converted to target format.
|
41
|
+
|
42
|
+
### 2008-08-29
|
43
|
+
|
44
|
+
* Fixed bad call to has_image_file
|
45
|
+
|
46
|
+
### 2008-08-28
|
47
|
+
|
48
|
+
* Added ability to regenerate a model's thumbnails.
|
49
|
+
* Changed a few methods in storage to accept the model rather than the id.
|
50
|
+
This makes storage more hackable as regards generating paths and file names.
|
51
|
+
* Added "has_image_id" method to model instance methods to facilitate
|
52
|
+
grouping the images under a directory structure based on a related model's
|
53
|
+
ids.
|
54
|
+
* Made the generated file name simply by the image object's id - this
|
55
|
+
is better adherance to the principle of least surprise.
|
56
|
+
|
57
|
+
### 2008-08-25
|
58
|
+
|
59
|
+
* Fixed bad call to resize_to in view helper.
|
60
|
+
|
61
|
+
### 2008-08-19
|
62
|
+
|
63
|
+
* Made storage work more correctly with tempfiles.
|
64
|
+
|
65
|
+
### 2008-08-18
|
66
|
+
|
67
|
+
* Fixed ability to set the path for storing image files.
|
68
|
+
|
69
|
+
### 2008-08-01
|
70
|
+
|
71
|
+
* Improved partitioned path handling to avoid collisions when the id is
|
72
|
+
very high, which can happen if you use db:fixtures:load.
|
73
|
+
|
74
|
+
### 2008-08-01
|
75
|
+
|
76
|
+
* Fixed a bug where overwriting a previous image triggered callbacks more
|
77
|
+
than once, causing errors.
|
78
|
+
|
79
|
+
### 2008-07-29
|
80
|
+
|
81
|
+
* Downcased generated file names to avoid potential issues on
|
82
|
+
case-insensitive filesystems.
|
83
|
+
* Added "absolute path" method to model instances.
|
84
|
+
* Made image deletion nullify the "has_image_file" field.
|
85
|
+
* Added "has_image?" method to model instances.
|
86
|
+
* Fixed ENONENT error with record update when there are no images yet.
|
87
|
+
* Reverted thumbnail sorting feature - it's fast but makes terrible quality
|
88
|
+
thumbnails. It's just not worth it.
|
89
|
+
|
90
|
+
### 2008-07-28
|
91
|
+
|
92
|
+
* Added sorted thumbnail processing. This improves thumbnail generation
|
93
|
+
speed by about 25% for 4.5 meg jpegs with 5 thumbnails.
|
94
|
+
* Fixed broken resize for non-fixed-width thumbnails.
|
95
|
+
* Added check for bad geometry strings.
|
96
|
+
* Added dependencies and Rubyforge project to gemspec, updated docs.
|
97
|
+
|
98
|
+
### 2008-07-25
|
99
|
+
|
100
|
+
* First public release.
|
data/MIT-LICENSE
CHANGED
@@ -1,20 +1,18 @@
|
|
1
|
-
Copyright (c) 2008
|
1
|
+
Copyright (c) 2008-2010 Norman Clarke and Adrián Mugnolo
|
2
2
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
the following conditions:
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
8
|
+
subject to the following conditions:
|
10
9
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
12
|
-
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
13
12
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
# has\_image - An Image attachment library for Active Record
|
2
|
+
|
3
|
+
The has\_image library extends Active Record to allow Rails applications to have
|
4
|
+
attached images. It is very small and lightweight: it only requires one column
|
5
|
+
in your model to store the uploaded image's file name.
|
6
|
+
|
7
|
+
It was originally created as a smaller, simpler, lighter alternative to
|
8
|
+
[attachment_fu](http://github.com/technoweenie/attachment_fu) for applications
|
9
|
+
that need to handle uploaded images.
|
10
|
+
|
11
|
+
It only supports using a filesystem for storage, and only supports
|
12
|
+
[MiniMagick](http://github.com/probablycorey/mini_magick) as an image processor.
|
13
|
+
However, its code is very small, clean and hackable, so adding support for other
|
14
|
+
backends or processors should be fairly easy.
|
15
|
+
|
16
|
+
Some typical use cases are: websites that want to create photo galleries with
|
17
|
+
fixed-dimension thumbnails, or that want to store user profile pictures without
|
18
|
+
creating a separate model for the images.
|
19
|
+
|
20
|
+
It creates only one database record per image, and uses ImageMagick's
|
21
|
+
[crop](http://www.imagemagick.org/script/command-line-options.php#crop) and
|
22
|
+
[center
|
23
|
+
gravity](http://www.imagemagick.org/script/command-line-options.php#gravity)
|
24
|
+
functions to produce thumbnails that generally look acceptable, unless the image
|
25
|
+
is a panorama, or the subject matter is close to one of the margins, etc. For
|
26
|
+
most sites where people upload pictures of themselves the generated thumbnails
|
27
|
+
will look good almost all the time.
|
28
|
+
|
29
|
+
## Examples
|
30
|
+
|
31
|
+
Point-and-drool use case. It's probably not what you want, but it may be useful
|
32
|
+
for bootstrapping.
|
33
|
+
|
34
|
+
class Member < ActiveRecord::Base
|
35
|
+
has_image
|
36
|
+
end
|
37
|
+
|
38
|
+
Single image, no thumbnails, with some size limits:
|
39
|
+
|
40
|
+
class Picture < ActiveRecord::Base
|
41
|
+
has_image :resize_to => "200x200",
|
42
|
+
:max_size => 3.megabytes,
|
43
|
+
:min_size => 4.kilobytes
|
44
|
+
end
|
45
|
+
|
46
|
+
Image with some thumbnails:
|
47
|
+
|
48
|
+
class Photo < ActiveRecord::Base
|
49
|
+
has_image :resize_to => "640x480",
|
50
|
+
:thumbnails => {
|
51
|
+
:square => "200x200",
|
52
|
+
:medium => "320x240"
|
53
|
+
},
|
54
|
+
:max_size => 3.megabytes,
|
55
|
+
:min_size => 4.kilobytes
|
56
|
+
end
|
57
|
+
|
58
|
+
It also provides a view helper to make displaying the images extremely simple:
|
59
|
+
|
60
|
+
<%= image_tag_for(@photo) # show the full-sized image %>
|
61
|
+
<%= image_tag_for(@photo, :thumb => :square) # show the square thumbnail %>
|
62
|
+
|
63
|
+
The image_tag_for helper calls Rails' image_tag, so you can pass in all the
|
64
|
+
regular options to set the alt property, CSS class, etc:
|
65
|
+
|
66
|
+
<%= image_tag_for(@photo, :alt => "my cool picture", :class => "photo") %>
|
67
|
+
|
68
|
+
Setting up forms for has\_image is simple, too:
|
69
|
+
|
70
|
+
<% form_for(@photo, :html => {:multipart => true}) do |f| %>
|
71
|
+
<p>
|
72
|
+
<%= f.label :image_data %>
|
73
|
+
<%= f.file_field :image_data %>
|
74
|
+
</p>
|
75
|
+
<p>
|
76
|
+
<%= f.submit %>
|
77
|
+
</p>
|
78
|
+
<% end %>
|
79
|
+
|
80
|
+
## Compatibility
|
81
|
+
|
82
|
+
Has\_image is compatible with Rails 2.1.x - 3.0.x.
|
83
|
+
|
84
|
+
## Getting it
|
85
|
+
|
86
|
+
Install has_image via RubyGems:
|
87
|
+
|
88
|
+
gem install has_image
|
89
|
+
|
90
|
+
and add it to your Gemfile (Rails 3.0.x) or environment.rb (Rails 2.x).
|
91
|
+
|
92
|
+
Then, add a column named `has_image_file` to your model.
|
93
|
+
|
94
|
+
## Source code
|
95
|
+
|
96
|
+
[http://github.com/norman/has_image](http://github.com/norman/has_image)
|
97
|
+
|
98
|
+
## FAQ
|
99
|
+
|
100
|
+
### How do I validate the mime type of my uploaded images?
|
101
|
+
|
102
|
+
You don't. Rather than examine the mime type, has\_image runs the "identify"
|
103
|
+
command on the file to determine if it is processable by ImageMagick, and if it
|
104
|
+
is, converts it to the format you specify, which defaults to JPEG.
|
105
|
+
|
106
|
+
This is better than checking for mime types, because your users may upload
|
107
|
+
exotic image types that you didn't even realize would work, such as Truevision
|
108
|
+
Targa images, or Seattle Film Works files.
|
109
|
+
|
110
|
+
If you wish to give users a list of file types they can upload, a good start
|
111
|
+
would be jpeg, png, bmp, and maybe gif and ttf if your installation of
|
112
|
+
ImageMagick understands them. You can find out what image types your ImageMagick
|
113
|
+
understands by running:
|
114
|
+
|
115
|
+
identify -list format
|
116
|
+
|
117
|
+
Ideally, if your users just upload files that "look like" images on their
|
118
|
+
computers, it has\_image should "just work."
|
119
|
+
|
120
|
+
## Hacking it
|
121
|
+
|
122
|
+
Don't like the way it makes images? Want to pipe the images through some [crazy
|
123
|
+
fast seam carving library written in
|
124
|
+
OCaml](http://eigenclass.org/hiki/seam-carving-in-ocaml), or watermark them with
|
125
|
+
your corporate logo? Happiness is just a
|
126
|
+
[monkey-patch](http://en.wikipedia.org/wiki/Monkey_patch) away:
|
127
|
+
|
128
|
+
module HasImage
|
129
|
+
class Processor
|
130
|
+
def resize_image(size)
|
131
|
+
# your new-and-improved thumbnailer code goes here.
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
Has\_image follows a philosophy of [skinny model, fat
|
137
|
+
plugin](http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model.)
|
138
|
+
This means that it tries to pollute your ActiveRecord model with as little
|
139
|
+
functionality as possible, so that in a sense, the model is acts like a
|
140
|
+
"controller" and the plugin like a "model" as regards the image handling
|
141
|
+
functionality. This makes it easier to test, hack, and reuse, because the
|
142
|
+
storage and processing functionality is largely independent of your model, and
|
143
|
+
of Rails.
|
144
|
+
|
145
|
+
## Bugs
|
146
|
+
|
147
|
+
Please report them on the Github issue tracker.
|
148
|
+
|
149
|
+
Copyright (c) 2008-2010 Norman Clarke and Adrian Mugnolo. Released under the MIT
|
150
|
+
License.
|
151
|
+
|
152
|
+
## Acknowledgements
|
153
|
+
|
154
|
+
We'd like to thank the following contributors for their help with has\_image:
|
155
|
+
|
156
|
+
* [Juan Schwindt](http://github.com/jschwindt)
|
157
|
+
* [Gerrit Keiser](http://github.com/gerrit)
|
158
|
+
* the folks from [Tricycle Developments](http://github.com/tricycle)
|
159
|
+
* [Dima Sabanin](http://github.com/railsmonk)
|
data/Rakefile
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rake/testtask'
|
3
|
-
require
|
3
|
+
require "rake/gempackagetask"
|
4
|
+
require "rake/clean"
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
CLEAN << "pkg" << "doc" << "coverage"
|
7
|
+
Rake::GemPackageTask.new(eval(File.read("has_image.gemspec"))) { |pkg| }
|
7
8
|
|
8
|
-
task :
|
9
|
+
task :default => :test
|
9
10
|
|
10
11
|
desc 'Test the non-Rails part of has_image.'
|
11
12
|
Rake::TestTask.new(:test) do |t|
|
@@ -13,37 +14,4 @@ Rake::TestTask.new(:test) do |t|
|
|
13
14
|
t.libs << 'test'
|
14
15
|
t.pattern = 'test/**/*_test.rb'
|
15
16
|
t.verbose = true
|
16
|
-
end
|
17
|
-
|
18
|
-
desc 'Test the Rails part of has_image.'
|
19
|
-
Rake::TestTask.new(:test_rails) do |t|
|
20
|
-
t.libs << 'lib'
|
21
|
-
t.libs << 'test_rails'
|
22
|
-
t.pattern = 'test_rails/**/*_test.rb'
|
23
|
-
t.verbose = true
|
24
|
-
end
|
25
|
-
|
26
|
-
desc "Run rcov"
|
27
|
-
task :rcov do
|
28
|
-
rm_f "coverage"
|
29
|
-
rm_f "coverage.data"
|
30
|
-
if PLATFORM =~ /darwin/
|
31
|
-
exclude = '--exclude "gems"'
|
32
|
-
else
|
33
|
-
exclude = '--exclude "rubygems"'
|
34
|
-
end
|
35
|
-
rcov = "rcov --rails -Ilib:test --sort coverage --text-report #{exclude} --no-validator-links"
|
36
|
-
cmd = "#{rcov} #{Dir["test/**/*.rb"].join(" ")}"
|
37
|
-
sh cmd
|
38
|
-
end
|
39
|
-
|
40
|
-
desc 'Generate documentation for has_image.'
|
41
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
42
|
-
rdoc.rdoc_dir = 'rdoc'
|
43
|
-
rdoc.title = 'HasImage'
|
44
|
-
rdoc.options << '--line-numbers' << '--inline-source' << '-c UTF-8'
|
45
|
-
rdoc.rdoc_files.include('README.textile')
|
46
|
-
rdoc.rdoc_files.include('FAQ')
|
47
|
-
rdoc.rdoc_files.include('CHANGELOG')
|
48
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
-
end
|
17
|
+
end
|
data/lib/has_image.rb
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
require "cgi"
|
2
|
+
require "active_support"
|
3
|
+
|
4
|
+
# AR < 3 would autoload everything
|
5
|
+
unless "".respond_to? :to_param
|
6
|
+
require "active_support/core_ext/object/blank"
|
7
|
+
require "active_support/core_ext/object/to_param"
|
8
|
+
require "active_support/core_ext/numeric/bytes"
|
9
|
+
require "active_support/core_ext/class/inheritable_attributes"
|
10
|
+
end
|
11
|
+
|
1
12
|
require 'has_image/processor'
|
2
13
|
require 'has_image/storage'
|
3
14
|
require 'has_image/view_helpers'
|
@@ -58,7 +69,7 @@ require 'has_image/view_helpers'
|
|
58
69
|
# directory. Add something like this to your config/environments/test.rb:
|
59
70
|
#
|
60
71
|
# config.after_initialize do
|
61
|
-
# MyClass.has_image_options[:base_path] = File.join(RAILS_ROOT, "tmp")
|
72
|
+
# MyClass.has_image_options[:base_path] = File.join(RAILS_ROOT, "tmp")
|
62
73
|
# end
|
63
74
|
#
|
64
75
|
# If you want to stub out calls to has_image so that your tests don't do
|
@@ -90,7 +101,6 @@ module HasImage
|
|
90
101
|
def enable # :nodoc:
|
91
102
|
return if ActiveRecord::Base.respond_to? :has_image
|
92
103
|
ActiveRecord::Base.send(:include, HasImage)
|
93
|
-
return if ActionView::Base.respond_to? :image_tag_for
|
94
104
|
ActionView::Base.send(:include, ViewHelpers)
|
95
105
|
end
|
96
106
|
|
@@ -243,7 +253,7 @@ module HasImage
|
|
243
253
|
end
|
244
254
|
|
245
255
|
def image_size
|
246
|
-
[width, height]
|
256
|
+
self[:image_size] || [width, height].join('x')
|
247
257
|
end
|
248
258
|
|
249
259
|
# Deletes the image from the storage.
|
@@ -254,9 +264,11 @@ module HasImage
|
|
254
264
|
storage.remove_images(self, send(has_image_options[:column]))
|
255
265
|
# The record will be frozen if we're being called after destroy.
|
256
266
|
unless frozen?
|
257
|
-
#
|
258
|
-
#
|
259
|
-
|
267
|
+
# FIXME: although this is cleaner now, it introduces a new issue
|
268
|
+
# with partial updates.
|
269
|
+
updates = "#{connection.quote_column_name(has_image_options[:column])} = NULL"
|
270
|
+
conditions = "#{connection.quote_column_name(self.class.primary_key)} = #{connection.quote(id)}"
|
271
|
+
self.class.update_all(updates, conditions)
|
260
272
|
self.send("#{has_image_options[:column]}=", nil)
|
261
273
|
end
|
262
274
|
rescue Errno::ENOENT
|
@@ -297,17 +309,22 @@ module HasImage
|
|
297
309
|
private
|
298
310
|
|
299
311
|
def populate_attributes
|
312
|
+
# FIXME: this is a quick and dirty work around for image updates
|
313
|
+
# breaking when running with Rails' partial updates. This is originated
|
314
|
+
# by the update_all call in the remove_images method which bypasses
|
315
|
+
# ActiveRecord::Dirty attribute change tracking.
|
316
|
+
attribute_will_change!(has_image_options[:column].to_s) if respond_to?(:attribute_will_change!, true)
|
317
|
+
|
300
318
|
send("#{has_image_options[:column]}=", storage.install_images(self))
|
301
319
|
self[:width] = storage.measure(absolute_path, :width) if self.class.column_names.include?('width')
|
302
320
|
self[:height] = storage.measure(absolute_path, :height) if self.class.column_names.include?('height')
|
321
|
+
self[:image_size] = [storage.measure(absolute_path, :width), storage.measure(absolute_path, :height)].join('x') if self.class.column_names.include?('image_size')
|
303
322
|
save!
|
304
323
|
end
|
305
324
|
|
306
|
-
|
307
325
|
end
|
308
326
|
|
309
327
|
module ModelClassMethods
|
310
|
-
|
311
328
|
# Get the hash of thumbnails set by the options specified when invoking
|
312
329
|
# HasImage::ClassMethods#has_image.
|
313
330
|
def thumbnails
|
@@ -317,11 +334,13 @@ module HasImage
|
|
317
334
|
def from_partitioned_path(path)
|
318
335
|
find HasImage::Storage.id_from_path(path)
|
319
336
|
end
|
320
|
-
|
321
337
|
end
|
322
|
-
|
323
338
|
end
|
324
339
|
|
325
|
-
if defined?(Rails)
|
326
|
-
|
340
|
+
if defined?(Rails)
|
341
|
+
if Rails.version >= "3"
|
342
|
+
require "has_image/railtie"
|
343
|
+
else
|
344
|
+
HasImage.enable
|
345
|
+
end
|
327
346
|
end
|