has_image 0.2.3 → 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.
- 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
|