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 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.
@@ -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'
@@ -4,63 +4,73 @@ require 'has_image/view_helpers'
4
4
 
5
5
  # = HasImage
6
6
  #
7
- # HasImage allows Ruby on Rails applications to have attached images. It is very
8
- # small and lightweight: it only requires one column ("has_image_file") in your
9
- # model to store the uploaded image's file name.
10
- #
11
- # HasImage is, by design, very simplistic: It only supports using a filesystem
12
- # for storage, and only supports
13
- # MiniMagick[http://github.com/probablycorey/mini_magick] as an image processor.
14
- # However, its code is very small, clean and hackable, so adding support for
15
- # other backends or processors should be fairly easy.
16
- #
17
- # HasImage works best for sites that want to show image galleries with
18
- # fixed-size thumbnails. It uses ImageMagick's
19
- # crop[http://www.imagemagick.org/script/command-line-options.php#crop] and
20
- # {center
21
- # gravity}[http://www.imagemagick.org/script/command-line-options.php#gravity]
22
- # functions to produce thumbnails that generally look acceptable, unless the
23
- # image is a panorama, or the subject matter is close to one of the margins,
24
- # etc. For most sites where people upload pictures of themselves or their pets
25
- # the generated thumbnails will look good almost all the time.
26
- #
27
- # It's pretty easy to change the image processing / resizing code; you can just
28
- # override HasImage::Processor#resize_image to do what you wish:
29
- #
30
- # module HasImage::
31
- # class Processor
32
- # def resize_image(size)
33
- # @image.combine_options do |commands|
34
- # commands.my_custom_resizing_goes_here
35
- # end
36
- # end
37
- # end
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
- # Compared to attachment_fu, HasImage has advantages and disadvantages.
41
- #
42
- # = Advantages:
43
- #
44
- # * Simpler, smaller, more easily hackable codebase - and specialized for
45
- # images only.
46
- # * Installable via Ruby Gems. This makes version dependencies easy when using
47
- # Rails 2.1.
48
- # * Creates only one database record per image.
49
- # * Has built-in facilities for making distortion-free, fixed-size thumbnails.
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.to_s.tableize,
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.to_s.tableize,
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
- # To use HasImage with a Rails model, all you have to do is add a column
129
- # named "has_image_file." For configuration defaults, you might want to take
130
- # a look at the default options specified in HasImage#default_options_for.
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. You should probably leave this alone, except for tests.
139
- # * <tt>:path_prefix</tt> - Where to install the images, relative to basepath. You should probably leave this alone.
140
- # * <tt>:convert_to</tt> - An ImageMagick format to convert images to. Recommended formats: JPEG, PNG, GIF.
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(:resize_to, :thumbnails, :max_size, :min_size,
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
- !has_image_file.blank?
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.regenerate_thumbnails(has_image_id, has_image_file)
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 has_image_file.blank?
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, has_image_file)
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 has_image_file = NULL WHERE id = #{id}")
226
- self.has_image_file = nil
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
- update_attribute(:has_image_file, storage.install_images(self))
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
- update_attribute(:has_image_file, storage.install_images(self))
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