norman-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 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 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