has_image 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|