has_image 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/README.textile +193 -0
- data/Rakefile +3 -1
- data/init.rb +1 -1
- data/lib/has_image.rb +152 -104
- data/lib/has_image/processor.rb +58 -31
- data/lib/has_image/storage.rb +72 -45
- data/test/storage_test.rb +44 -2
- data/test_rails/complex_pic_test.rb +42 -0
- data/test_rails/pic_test.rb +72 -9
- data/test_rails/schema.rb +7 -1
- data/test_rails/test_helper.rb +1 -3
- metadata +6 -9
- data/README +0 -161
- data/test_rails/pic.rb +0 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
2008-10-22 Gerrit Keiser and Tricycle Developments
|
2
|
+
* Added option to not delete images on destroy
|
3
|
+
* Made thumbnail name separator configurable
|
4
|
+
* Added height/width methods to storage
|
5
|
+
* Allowed regenerating only one thumbnail size
|
6
|
+
* Made has_image column configurable
|
7
|
+
* Added some compatibility with attachment_fu
|
8
|
+
* General refactorings and overall code improvement
|
9
|
+
|
10
|
+
2008-10-22 Norman Clarke <norman@randomba.org>
|
11
|
+
* Documentation improvements and minor code cleanups.
|
12
|
+
|
1
13
|
2008-10-09 Dima Sabanin <sdmitry@gmail.com>
|
2
14
|
* Fixed display of images with special symbols in the name,
|
3
15
|
like '2777-nipple-+-apple-napple.jpg'. + is reserved by HTTP.
|
data/README.textile
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
h1. "HasImage":http://github.com/norman/has_image
|
2
|
+
|
3
|
+
Image attachment gem/plugin for Ruby on Rails
|
4
|
+
|
5
|
+
HasImage allows Ruby on Rails applications to have attached images. It is very
|
6
|
+
small and lightweight: it only requires one column in your model to store the
|
7
|
+
uploaded image's file name.
|
8
|
+
|
9
|
+
HasImage was created as a smaller, simpler, lighter alternative to
|
10
|
+
"attachment_fu":http://github.com/technoweenie/attachment_fu for applications
|
11
|
+
that need to handle uploaded images.
|
12
|
+
|
13
|
+
It is, by design, very simplistic: It only supports using a filesystem for
|
14
|
+
storage, and only supports
|
15
|
+
"MiniMagick":http://github.com/probablycorey/mini_magick as an image
|
16
|
+
processor. However, its code is very small, clean and hackable, so adding
|
17
|
+
support for other backends or processors should be fairly easy.
|
18
|
+
|
19
|
+
Some typical use cases are: websites that want to create photo galleries with
|
20
|
+
fixed-dimension thumbnails, or that want to store user profile pictures
|
21
|
+
without creating a separate model for the images.
|
22
|
+
|
23
|
+
It creates only one database record per image, and uses ImageMagick's
|
24
|
+
"crop":http://www.imagemagick.org/script/command-line-options.php#crop and
|
25
|
+
"center gravity":http://www.imagemagick.org/script/command-line-options.php#gravity
|
26
|
+
functions to produce thumbnails that generally look acceptable, unless the
|
27
|
+
image is a panorama, or the subject matter is close to one of the margins,
|
28
|
+
etc. For most sites where people upload pictures of themselves the generated
|
29
|
+
thumbnails will look good almost all the time.
|
30
|
+
|
31
|
+
h2. Another image attachment library? Why?
|
32
|
+
|
33
|
+
<blockquote>
|
34
|
+
The three chief virtues of a programmer are: Laziness, Impatience and Hubris. - "Larry Wall":http://en.wikipedia.org/wiki/Larry_Wall
|
35
|
+
</blockquote>
|
36
|
+
|
37
|
+
Attachment_fu is too large and general for some of the places I want to use
|
38
|
+
images. I sometimes found myself writing more code to hack attachment_fu than
|
39
|
+
it took to create this gem. In fact, most of the code here has been plucked
|
40
|
+
from my various projects that use attachment_fu.
|
41
|
+
|
42
|
+
The other image attachment libraries I found fell short of my needs for
|
43
|
+
various other reasons, so I decided to roll my own.
|
44
|
+
|
45
|
+
h2. HasImage vs. attachment_fu
|
46
|
+
|
47
|
+
h3. Advantages
|
48
|
+
|
49
|
+
* Simpler, smaller, more easily hackable codebase - and specialized for
|
50
|
+
images only.
|
51
|
+
* Installable via Ruby Gems. This makes version dependencies easy when using
|
52
|
+
Rails 2.1.
|
53
|
+
* Creates only one database record per image.
|
54
|
+
* Has built-in facilities for making distortion-free, fixed-size thumbnails.
|
55
|
+
* Doesn't regenerate the thumbnails every time you save your model. This means
|
56
|
+
you can easily use it, for example, inside a Member model to store member
|
57
|
+
avatars.
|
58
|
+
|
59
|
+
h3. Disadvantages
|
60
|
+
|
61
|
+
* Doesn't save image dimensions in the database. However, if you're using
|
62
|
+
fixed-sized images, you can read the size from MyModel.thumbnails[:my_size].
|
63
|
+
* No support for AWS or DBFile storage, only filesystem.
|
64
|
+
* Only supports "MiniMagick":http://github.com/probablycorey/mini_magick/tree as an image processor, no RMagick, GD, CoreImage, etc.
|
65
|
+
* No support for anything other than image attachments.
|
66
|
+
* Not as popular as attachment_fu, but then again if you use it you'll be cooler (until HasImage becomes popular).
|
67
|
+
|
68
|
+
h2. Examples
|
69
|
+
|
70
|
+
Point-and-drool use case. It's probably not what you want, but it may be
|
71
|
+
useful for bootstrapping.
|
72
|
+
|
73
|
+
class Member < ActiveRecord::Base
|
74
|
+
has_image
|
75
|
+
end
|
76
|
+
|
77
|
+
Single image, no thumbnails, with some size limits:
|
78
|
+
|
79
|
+
class Picture < ActiveRecord::Base
|
80
|
+
has_image :resize_to => "200x200",
|
81
|
+
:max_size => 3.megabytes,
|
82
|
+
:min_size => 4.kilobytes
|
83
|
+
end
|
84
|
+
|
85
|
+
Image with some thumbnails:
|
86
|
+
|
87
|
+
class Photo < ActiveRecord::Base
|
88
|
+
has_image :resize_to => "640x480",
|
89
|
+
:thumbnails => {
|
90
|
+
:square => "200x200",
|
91
|
+
:medium => "320x240"
|
92
|
+
},
|
93
|
+
:max_size => 3.megabytes,
|
94
|
+
:min_size => 4.kilobytes
|
95
|
+
end
|
96
|
+
|
97
|
+
It also provides a view helper to make displaying the images extremely simple:
|
98
|
+
|
99
|
+
<%= image_tag_for(@photo) # show the full-sized image %>
|
100
|
+
<%= image_tag_for(@photo, :thumb => :square) # show the square thumbnail %>
|
101
|
+
|
102
|
+
The image_tag_for helper calls Rails' image_tag, so you can pass in all the
|
103
|
+
regular options to set the alt property, CSS class, etc:
|
104
|
+
|
105
|
+
<%= image_tag_for(@photo, :alt => "my cool picture", :class => "photo") %>
|
106
|
+
|
107
|
+
Setting up forms for HasImage is simple, too:
|
108
|
+
|
109
|
+
<pre>
|
110
|
+
<% form_for(@photo, :html => {:multipart => true}) do |f| %>
|
111
|
+
<p>
|
112
|
+
<%= f.label :image_data %>
|
113
|
+
<%= f.file_field :image_data %>
|
114
|
+
</p>
|
115
|
+
<p>
|
116
|
+
<%= f.submit %>
|
117
|
+
</p>
|
118
|
+
<% end %>
|
119
|
+
</pre>
|
120
|
+
|
121
|
+
h2. Getting it
|
122
|
+
|
123
|
+
Has image can be installed as a gem, or as a Rails plugin. Gem installation
|
124
|
+
is easiest, and recommended:
|
125
|
+
|
126
|
+
gem install has_image
|
127
|
+
|
128
|
+
and add
|
129
|
+
|
130
|
+
require 'has_image'
|
131
|
+
|
132
|
+
to your environment.rb file.
|
133
|
+
|
134
|
+
Alternatively, you can install it as a Rails plugin:
|
135
|
+
|
136
|
+
./script plugin install git://github.com/norman/has_image.git
|
137
|
+
|
138
|
+
Rails versions before 2.1 do not support plugin installation using Git, so if
|
139
|
+
you're on 2.0 (or earlier), then please install the gem rather than the
|
140
|
+
plugin.
|
141
|
+
|
142
|
+
Then, make sure the model has a column named "has_image_file."
|
143
|
+
|
144
|
+
"Git repository":http://github.com/norman/has_image: git://github.com/norman/has_image.git
|
145
|
+
|
146
|
+
h2. Hacking it
|
147
|
+
|
148
|
+
Don't like the way it makes images? Want to pipe the images through some
|
149
|
+
"crazy fast seam carving library written in OCaml":http://eigenclass.org/hiki/seam-carving-in-ocaml, or watermark them
|
150
|
+
with your corporate logo? Happiness is just a "monkey-patch":http://en.wikipedia.org/wiki/Monkey_patch away:
|
151
|
+
|
152
|
+
module HasImage
|
153
|
+
class Processor
|
154
|
+
def resize_image(size)
|
155
|
+
# your new-and-improved thumbnailer code goes here.
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
HasImage follows a philosophy of ""skinny model, fat plugin":http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model."
|
161
|
+
This means that it tries to pollute your ActiveRecord model with as little
|
162
|
+
functionality as possible, so that in a sense, the model is acts like a
|
163
|
+
"controller" and the plugin like a "model" as regards the image handling
|
164
|
+
functionality. This makes it easier to test, hack, and reuse, because the
|
165
|
+
storage and processing functionality is largely independent of your model, and
|
166
|
+
of Rails.
|
167
|
+
|
168
|
+
My goal for HasImage is to keep it very small. If you need *a lot* of
|
169
|
+
functionality that's not here, instead of patching this code, you will likely
|
170
|
+
be better off using attachment_fu, which is more powerful, but also more
|
171
|
+
complex.
|
172
|
+
|
173
|
+
h2. Bugs
|
174
|
+
|
175
|
+
Please report them on "Lighthouse":http://randomba.lighthouseapp.com/projects/14674-has_image.
|
176
|
+
|
177
|
+
Copyright (c) 2008 "Norman Clarke":mailto:norman@randomba.org, released under
|
178
|
+
the MIT license
|
179
|
+
|
180
|
+
h2. Is anyone using this thing?
|
181
|
+
|
182
|
+
HasImage powers "FotoBlog":http://fotoblog.ciudad.com.ar, one of the largest
|
183
|
+
Rails sites in Argentina. If you're using it in your project let me know and
|
184
|
+
I'll add your link here.
|
185
|
+
|
186
|
+
h2. Acknowledgements
|
187
|
+
|
188
|
+
I'd like to thank the following contributors:
|
189
|
+
|
190
|
+
* "Adrian Mugnolo":http://github.com/xymbol
|
191
|
+
* "Gerrit Keiser":http://github.com/gerrit
|
192
|
+
* the folks from "Tricycle Developments":http://github.com/tricycle
|
193
|
+
* "Dima Sabanin":http://github.com/railsmonk
|
data/Rakefile
CHANGED
@@ -5,6 +5,8 @@ require 'rake/rdoctask'
|
|
5
5
|
desc 'Default: run unit tests.'
|
6
6
|
task :default => :test
|
7
7
|
|
8
|
+
task :all_tests => [:test, :test_rails]
|
9
|
+
|
8
10
|
desc 'Test the non-Rails part of has_image.'
|
9
11
|
Rake::TestTask.new(:test) do |t|
|
10
12
|
t.libs << 'lib'
|
@@ -40,7 +42,7 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
40
42
|
rdoc.rdoc_dir = 'rdoc'
|
41
43
|
rdoc.title = 'HasImage'
|
42
44
|
rdoc.options << '--line-numbers' << '--inline-source' << '-c UTF-8'
|
43
|
-
rdoc.rdoc_files.include('README')
|
45
|
+
rdoc.rdoc_files.include('README.textile')
|
44
46
|
rdoc.rdoc_files.include('FAQ')
|
45
47
|
rdoc.rdoc_files.include('CHANGELOG')
|
46
48
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
data/init.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'has_image'
|
1
|
+
require 'has_image'
|
data/lib/has_image.rb
CHANGED
@@ -4,63 +4,73 @@ require 'has_image/view_helpers'
|
|
4
4
|
|
5
5
|
# = HasImage
|
6
6
|
#
|
7
|
-
# HasImage allows
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# HasImage
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
7
|
+
# HasImage allows you to very easily attach images to a Rails model. For some
|
8
|
+
# more basic info on what it does, please see its {project
|
9
|
+
# page}[http://github.com/norman/has_image] on GitHub.
|
10
|
+
#
|
11
|
+
# Install HasImage by using Ruby Gems:
|
12
|
+
#
|
13
|
+
# sudo gem install has_image
|
14
|
+
#
|
15
|
+
# To use HasImage in your project, you must add a varchar column to your
|
16
|
+
# model. By default, this column should be named "has_image_file," though you
|
17
|
+
# may easily change this. For option defaults, see
|
18
|
+
# HasImage#default_options_for and ClassMethods#has_image.
|
19
|
+
#
|
20
|
+
# == Basic Examples
|
21
|
+
##
|
22
|
+
# Uses all default options. This works, but is likely not what you need.
|
23
|
+
#
|
24
|
+
# class Photo < ActiveRecord::Base
|
25
|
+
# has_image
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Resize the uploaded image to 800x800 and create a 150x150 thumbnail.
|
29
|
+
#
|
30
|
+
# has_image :resize_to "800x800", :thumbnails => {:square => "150x150"}
|
31
|
+
#
|
32
|
+
# Resize the image and set a max file size to 4 megabytes.
|
33
|
+
#
|
34
|
+
# has_image :resize_to "100x150", :max_size => 4.megabytes
|
35
|
+
#
|
36
|
+
# == Some slightly more advanced examples
|
37
|
+
#
|
38
|
+
# === Localizing HasImage
|
39
|
+
#
|
40
|
+
# has_image :invalid_image_message => "No se puede procesar la imagen."
|
41
|
+
#
|
42
|
+
# === Using has_image with Capistrano
|
43
|
+
#
|
44
|
+
# When deploying using Capistrano, you will likely want to keep images
|
45
|
+
# under a "system" directory so that newly deployed versions have access
|
46
|
+
# to them:
|
47
|
+
#
|
48
|
+
# has_image :resize_to => "150x150",
|
49
|
+
# :thumbnails => {
|
50
|
+
# :square => "75x75",
|
51
|
+
# },
|
52
|
+
# :base_path => File.join(Rails.root, 'public', 'system')
|
53
|
+
#
|
54
|
+
# === Testing with HasImage:
|
55
|
+
#
|
56
|
+
# If you want your tests to actually run the image processing, you should
|
57
|
+
# make sure your tests write the image files somewhere outside your public
|
58
|
+
# directory. Add something like this to your config/environments/test.rb:
|
59
|
+
#
|
60
|
+
# config.after_initialize do
|
61
|
+
# MyClass.has_image_options[:base_path] = File.join(RAILS_ROOT, "tmp")
|
38
62
|
# end
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
# * Doesn't regenerate the thumbnails every time you save your model. This means
|
51
|
-
# you can easily use it, for example, inside a Member model to store member
|
52
|
-
# avatars.
|
53
|
-
#
|
54
|
-
# = Disadvantages:
|
55
|
-
#
|
56
|
-
# * Doesn't save image dimensions. However, if you're using fixed-sized images,
|
57
|
-
# this is not a problem because you can just read the size from MyModel.thumbnails[:my_size]
|
58
|
-
# * No support for AWS or DBFile storage, only filesystem.
|
59
|
-
# * Only supports MiniMagick[http://github.com/probablycorey/mini_magick/tree] as an image processor, no RMagick, GD, CoreImage,
|
60
|
-
# etc.
|
61
|
-
# * No support for anything other than image attachments.
|
62
|
-
# * Not as popular as attachment_fu, which means fewer bug reports, and
|
63
|
-
# probably more bugs. Use at your own risk!
|
63
|
+
#
|
64
|
+
# If you want to stub out calls to has_image so that your tests don't do
|
65
|
+
# the (slow) image processing, here's an example using Test::Unit and
|
66
|
+
# Mocha:
|
67
|
+
#
|
68
|
+
# def setup
|
69
|
+
# Photo.any_instance.stubs(:image_data=).returns(true)
|
70
|
+
# Photo.any_instance.stubs(:install_images).returns(true)
|
71
|
+
# Photo.any_instance.stubs(:image_data_valid?).returns(true)
|
72
|
+
# end
|
73
|
+
#
|
64
74
|
module HasImage
|
65
75
|
|
66
76
|
class ProcessorError < StandardError ; end
|
@@ -68,9 +78,9 @@ module HasImage
|
|
68
78
|
class FileTooBigError < StorageError ; end
|
69
79
|
class FileTooSmallError < StorageError ; end
|
70
80
|
class InvalidGeometryError < ProcessorError ; end
|
71
|
-
|
81
|
+
|
72
82
|
class << self
|
73
|
-
|
83
|
+
|
74
84
|
def included(base) # :nodoc:
|
75
85
|
base.extend(ClassMethods)
|
76
86
|
end
|
@@ -97,23 +107,29 @@ module HasImage
|
|
97
107
|
#
|
98
108
|
# * :resize_to => "200x200",
|
99
109
|
# * :thumbnails => {},
|
110
|
+
# * :auto_generate_thumbnails => true,
|
111
|
+
# * :delete => true,
|
100
112
|
# * :max_size => 12.megabytes,
|
101
113
|
# * :min_size => 4.kilobytes,
|
102
|
-
# * :path_prefix => klass.
|
114
|
+
# * :path_prefix => klass.table_name,
|
103
115
|
# * :base_path => File.join(RAILS_ROOT, 'public'),
|
116
|
+
# * :column => :has_image_file,
|
104
117
|
# * :convert_to => "JPEG",
|
105
118
|
# * :output_quality => "85",
|
106
119
|
# * :invalid_image_message => "Can't process the image.",
|
107
120
|
# * :image_too_small_message => "The image is too small.",
|
108
|
-
# * :image_too_big_message => "The image is too big."
|
121
|
+
# * :image_too_big_message => "The image is too big."
|
109
122
|
def default_options_for(klass)
|
110
123
|
{
|
111
124
|
:resize_to => "200x200",
|
112
125
|
:thumbnails => {},
|
126
|
+
:auto_generate_thumbnails => true,
|
127
|
+
:delete => true,
|
113
128
|
:max_size => 12.megabytes,
|
114
129
|
:min_size => 4.kilobytes,
|
115
|
-
:path_prefix => klass.
|
130
|
+
:path_prefix => klass.table_name,
|
116
131
|
:base_path => File.join(RAILS_ROOT, 'public'),
|
132
|
+
:column => :has_image_file,
|
117
133
|
:convert_to => "JPEG",
|
118
134
|
:output_quality => "85",
|
119
135
|
:invalid_image_message => "Can't process the image.",
|
@@ -121,68 +137,67 @@ module HasImage
|
|
121
137
|
:image_too_big_message => "The image is too big."
|
122
138
|
}
|
123
139
|
end
|
124
|
-
|
140
|
+
|
125
141
|
end
|
126
142
|
|
127
143
|
module ClassMethods
|
128
|
-
|
129
|
-
#
|
130
|
-
#
|
131
|
-
# The different setting options are described below.
|
132
|
-
#
|
133
|
-
# Options:
|
144
|
+
|
145
|
+
# === Options
|
146
|
+
#
|
134
147
|
# * <tt>:resize_to</tt> - Dimensions to resize to. This should be an ImageMagick {geometry string}[http://www.imagemagick.org/script/command-line-options.php#resize]. Fixed sizes are recommended.
|
135
148
|
# * <tt>:thumbnails</tt> - A hash of thumbnail names and dimensions. The dimensions should be ImageMagick {geometry strings}[http://www.imagemagick.org/script/command-line-options.php#resize]. Fixed sized are recommended.
|
149
|
+
# * <tt>:auto_generate_thumbnails</tt> - Flag to indicate whether to automatically generate thumbnails when the image_data changes (e.g. on create). If you set this to false, your application code needs to take care of generating thumbnails, e.g. using +#generate_thumbnail+
|
150
|
+
# * <tt>:delete</tt> - Flag to indicate if the images should be deleted from the storage (e.g. the filesystem) when the record is destroyed.
|
136
151
|
# * <tt>:min_size</tt> - Minimum file size allowed. It's recommended that you set this size in kilobytes.
|
137
152
|
# * <tt>:max_size</tt> - Maximum file size allowed. It's recommended that you set this size in megabytes.
|
138
|
-
# * <tt>:base_path</tt> - Where to install the images.
|
139
|
-
# * <tt>:path_prefix</tt> - Where to install the images, relative to basepath.
|
140
|
-
# * <tt>:convert_to</tt> - An ImageMagick format to convert images to.
|
153
|
+
# * <tt>:base_path</tt> - Where to install the images.
|
154
|
+
# * <tt>:path_prefix</tt> - Where to install the images, relative to basepath.
|
155
|
+
# * <tt>:convert_to</tt> - An ImageMagick format to convert images to.
|
141
156
|
# * <tt>:output_quality</tt> - Image output quality passed to ImageMagick.
|
142
157
|
# * <tt>:invalid_image_message</tt> - The message that will be shown when the image data can't be processed.
|
143
158
|
# * <tt>:image_too_small_message</tt> - The message that will be shown when the image file is too small. You should ideally set this to something that tells the user what the minimum is.
|
144
159
|
# * <tt>:image_too_big_message</tt> - The message that will be shown when the image file is too big. You should ideally set this to something that tells the user what the maximum is.
|
145
|
-
#
|
146
|
-
# Examples:
|
147
|
-
# has_image # uses all default options
|
148
|
-
# has_image :resize_to "800x800", :thumbnails => {:square => "150x150"}
|
149
|
-
# has_image :resize_to "100x150", :max_size => 500.kilobytes
|
150
|
-
# has_image :invalid_image_message => "No se puede procesar la imagen."
|
151
160
|
def has_image(options = {})
|
152
|
-
options.assert_valid_keys(
|
153
|
-
:path_prefix, :base_path, :convert_to, :output_quality,
|
154
|
-
:invalid_image_message, :image_too_big_message, :image_too_small_message)
|
161
|
+
options.assert_valid_keys(HasImage.default_options_for(self).keys)
|
155
162
|
options = HasImage.default_options_for(self).merge(options)
|
156
163
|
class_inheritable_accessor :has_image_options
|
157
164
|
write_inheritable_attribute(:has_image_options, options)
|
158
|
-
|
165
|
+
|
159
166
|
after_create :install_images
|
160
167
|
after_save :update_images
|
161
168
|
after_destroy :remove_images
|
162
|
-
|
169
|
+
|
163
170
|
validate_on_create :image_data_valid?
|
164
|
-
|
171
|
+
|
165
172
|
include ModelInstanceMethods
|
166
173
|
extend ModelClassMethods
|
167
|
-
|
174
|
+
|
168
175
|
end
|
169
|
-
|
176
|
+
|
170
177
|
end
|
171
178
|
|
172
179
|
module ModelInstanceMethods
|
173
|
-
|
180
|
+
|
174
181
|
# Does the object have an image?
|
175
182
|
def has_image?
|
176
|
-
!
|
183
|
+
!send(has_image_options[:column]).blank?
|
177
184
|
end
|
178
|
-
|
185
|
+
|
179
186
|
# Sets the uploaded image data. Image data can be an instance of Tempfile,
|
180
187
|
# or an instance of any class than inherits from IO.
|
188
|
+
# aliased as uploaded_data= for compatibility with attachment_fu
|
181
189
|
def image_data=(image_data)
|
182
190
|
return if image_data.blank?
|
183
191
|
storage.image_data = image_data
|
184
192
|
end
|
185
|
-
|
193
|
+
alias_method :uploaded_data=, :image_data=
|
194
|
+
# nil placeholder in case this field is used in a form.
|
195
|
+
# Aliased as uploaded_data for compatibility with attachment_fu
|
196
|
+
def image_data
|
197
|
+
nil
|
198
|
+
end
|
199
|
+
alias_method :uploaded_data, :image_data
|
200
|
+
|
186
201
|
# Is the image data a file that ImageMagick can process, and is it within
|
187
202
|
# the allowed minimum and maximum sizes?
|
188
203
|
def image_data_valid?
|
@@ -195,62 +210,81 @@ module HasImage
|
|
195
210
|
errors.add_to_base(self.class.has_image_options[:invalid_image_message])
|
196
211
|
end
|
197
212
|
end
|
198
|
-
|
213
|
+
|
199
214
|
# Gets the "web path" for the image, or optionally, its thumbnail.
|
215
|
+
# Aliased as +public_filename+ for compatibility with attachment-Fu
|
200
216
|
def public_path(thumbnail = nil)
|
201
217
|
storage.public_path_for(self, thumbnail)
|
202
218
|
end
|
219
|
+
alias_method :public_filename, :public_path
|
203
220
|
|
204
221
|
# Gets the absolute filesystem path for the image, or optionally, its
|
205
222
|
# thumbnail.
|
206
223
|
def absolute_path(thumbnail = nil)
|
207
224
|
storage.filesystem_path_for(self, thumbnail)
|
208
225
|
end
|
209
|
-
|
226
|
+
|
210
227
|
# Regenerates the thumbails from the main image.
|
211
|
-
def regenerate_thumbnails
|
212
|
-
storage.
|
228
|
+
def regenerate_thumbnails!
|
229
|
+
storage.generate_thumbnails(has_image_id, send(has_image_options[:column]))
|
230
|
+
end
|
231
|
+
alias_method :regenerate_thumbnails, :regenerate_thumbnails! #Backwards compat
|
232
|
+
|
233
|
+
def generate_thumbnail!(thumb_name)
|
234
|
+
storage.generate_thumbnail(has_image_id, send(has_image_options[:column]), thumb_name)
|
213
235
|
end
|
214
|
-
|
236
|
+
|
237
|
+
def width
|
238
|
+
self[:width] || storage.measure(absolute_path, :width)
|
239
|
+
end
|
240
|
+
|
241
|
+
def height
|
242
|
+
self[:height] || storage.measure(absolute_path, :height)
|
243
|
+
end
|
244
|
+
|
245
|
+
def image_size
|
246
|
+
[width, height] * 'x'
|
247
|
+
end
|
248
|
+
|
215
249
|
# Deletes the image from the storage.
|
216
250
|
def remove_images
|
217
|
-
return if
|
251
|
+
return if send(has_image_options[:column]).blank? || !has_image_options[:delete]
|
218
252
|
self.class.transaction do
|
219
253
|
begin
|
220
|
-
storage.remove_images(self,
|
254
|
+
storage.remove_images(self, send(has_image_options[:column]))
|
221
255
|
# The record will be frozen if we're being called after destroy.
|
222
256
|
unless frozen?
|
223
257
|
# Resorting to SQL here to avoid triggering callbacks. There must be
|
224
258
|
# a better way to do this.
|
225
|
-
self.connection.execute("UPDATE #{self.class.table_name} SET
|
226
|
-
self.
|
259
|
+
self.connection.execute("UPDATE #{self.class.table_name} SET #{has_image_options[:column]} = NULL WHERE id = #{id}")
|
260
|
+
self.send("#{has_image_options[:column]}=", nil)
|
227
261
|
end
|
228
262
|
rescue Errno::ENOENT
|
229
263
|
logger.warn("Could not delete files for #{self.class.to_s} #{to_param}")
|
230
264
|
end
|
231
265
|
end
|
232
266
|
end
|
233
|
-
|
267
|
+
|
234
268
|
# Creates new images and removes the old ones when image_data has been
|
235
269
|
# set.
|
236
270
|
def update_images
|
237
271
|
return if storage.temp_file.blank?
|
238
272
|
remove_images
|
239
|
-
|
273
|
+
populate_attributes
|
240
274
|
end
|
241
275
|
|
242
276
|
# Processes and installs the image and its thumbnails.
|
243
277
|
def install_images
|
244
278
|
return if !storage.temp_file
|
245
|
-
|
279
|
+
populate_attributes
|
246
280
|
end
|
247
|
-
|
281
|
+
|
248
282
|
# Gets an instance of the underlying storage functionality. See
|
249
283
|
# HasImage::Storage.
|
250
284
|
def storage
|
251
285
|
@storage ||= HasImage::Storage.new(has_image_options)
|
252
286
|
end
|
253
|
-
|
287
|
+
|
254
288
|
# By default, just returns the model's id. Since this id is used to divide
|
255
289
|
# the images up in directories, you can override this to return a related
|
256
290
|
# model's id if you want the images to be grouped differently. For example,
|
@@ -259,7 +293,17 @@ module HasImage
|
|
259
293
|
def has_image_id
|
260
294
|
id
|
261
295
|
end
|
262
|
-
|
296
|
+
|
297
|
+
private
|
298
|
+
|
299
|
+
def populate_attributes
|
300
|
+
send("#{has_image_options[:column]}=", storage.install_images(self))
|
301
|
+
self[:width] = storage.measure(absolute_path, :width) if self.class.column_names.include?('width')
|
302
|
+
self[:height] = storage.measure(absolute_path, :height) if self.class.column_names.include?('height')
|
303
|
+
save!
|
304
|
+
end
|
305
|
+
|
306
|
+
|
263
307
|
end
|
264
308
|
|
265
309
|
module ModelClassMethods
|
@@ -270,6 +314,10 @@ module HasImage
|
|
270
314
|
has_image_options[:thumbnails]
|
271
315
|
end
|
272
316
|
|
317
|
+
def from_partitioned_path(path)
|
318
|
+
find HasImage::Storage.id_from_path(path)
|
319
|
+
end
|
320
|
+
|
273
321
|
end
|
274
322
|
|
275
323
|
end
|