has_image 0.1.11 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,5 +1,12 @@
1
1
  2008-08-28 Norman Clarke <norman@randomba.org>
2
2
  * Added ability to regenerate a model's thumbnails.
3
+ * Changed a few methods in storage to accept the model rather than the id.
4
+ This makes storage more hackable as regards generating paths and file names.
5
+ * Added "has_image_id" method to model instance methods to facilitate
6
+ grouping the images under a directory structure based on a related model's
7
+ ids.
8
+ * Made the generated file name simply by the image object's id - this
9
+ is better adherance to the principle of least surprise.
3
10
 
4
11
  2008-08-25 Norman Clarke <norman@randomba.org>
5
12
  * Fixed bad call to resize_to in view helper.
@@ -25,14 +25,11 @@ module HasImage
25
25
  ["%04d" % ((id.to_i / 1e4) % 1e4), "%04d" % (id.to_i % 1e4)].concat(args)
26
26
  end
27
27
 
28
- # Generates a 4-6 character random file name to use for the image and
29
- # its thumbnails. This is done to avoid having files with unfortunate
30
- # names. On one of my sites users frequently upload images with Arabic
31
- # names, and they end up being hard to manipulate on the command line.
32
- # This also helps prevent a possibly undesirable sitation where the
33
- # uploaded images have offensive names.
34
- def generated_file_name
35
- Zlib.crc32(Time.now.to_s + rand(10e10).to_s).to_s(36).downcase
28
+ # By default, simply accepts and returns the id of the object. This is
29
+ # here to allow you to monkey patch this method, for example, if you
30
+ # wish instead to generate and return a UUID.
31
+ def generated_file_name(*args)
32
+ return args.first.to_param.to_s
36
33
  end
37
34
 
38
35
  end
@@ -76,10 +73,10 @@ module HasImage
76
73
 
77
74
  # Invokes the processor to resize the image(s) and the installs them to
78
75
  # the appropriate directory.
79
- def install_images(id)
80
- generated_name = Storage.generated_file_name
81
- install_main_image(id, generated_name)
82
- install_thumbnails(id, generated_name) if !options[:thumbnails].empty?
76
+ def install_images(object)
77
+ generated_name = Storage.generated_file_name(object)
78
+ install_main_image(object.has_image_id, generated_name)
79
+ install_thumbnails(object.has_image_id, generated_name) if !options[:thumbnails].empty?
83
80
  return generated_name
84
81
  ensure
85
82
  @temp_file.close! if !@temp_file.closed?
@@ -94,8 +91,10 @@ module HasImage
94
91
  end
95
92
 
96
93
  # Deletes the images and directory that contains them.
97
- def remove_images(id)
98
- FileUtils.rm_r path_for(id)
94
+ def remove_images(object, name)
95
+ FileUtils.rm Dir.glob(File.join(path_for(object.has_image_id), name + '*'))
96
+ Dir.rmdir path_for(object.has_image_id)
97
+ rescue SystemCallError
99
98
  end
100
99
 
101
100
  # Is the uploaded file within the min and max allowed sizes?
@@ -133,7 +132,7 @@ module HasImage
133
132
  #
134
133
  # /var/sites/example.com/production/public/photos/0000/0001/3er0zs.jpg
135
134
  def filesystem_path_for(object, thumbnail = nil)
136
- File.join(path_for(object.id), file_name_for(object.has_image_file, thumbnail))
135
+ File.join(path_for(object.has_image_id), file_name_for(object.has_image_file, thumbnail))
137
136
  end
138
137
 
139
138
  # Write the main image to the install directory - probably somewhere under
data/lib/has_image.rb CHANGED
@@ -209,7 +209,7 @@ module HasImage
209
209
 
210
210
  # Regenerates the thumbails from the main image.
211
211
  def regenerate_thumbnails
212
- storage.regenerate_thumbnails(id, has_image_file)
212
+ storage.regenerate_thumbnails(has_image_id, has_image_file)
213
213
  end
214
214
 
215
215
  # Deletes the image from the storage.
@@ -217,11 +217,14 @@ module HasImage
217
217
  return if has_image_file.blank?
218
218
  self.class.transaction do
219
219
  begin
220
- # Resorting to SQL here to avoid triggering callbacks. There must be
221
- # a better way to do this.
222
- self.connection.execute("UPDATE #{self.class.table_name} SET has_image_file = NULL WHERE id = #{id}")
223
- self.has_image_file = nil
224
- storage.remove_images(self.id)
220
+ storage.remove_images(self, has_image_file)
221
+ # The record will be frozen if we're being called after destroy.
222
+ unless frozen?
223
+ # Resorting to SQL here to avoid triggering callbacks. There must be
224
+ # 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
227
+ end
225
228
  rescue Errno::ENOENT
226
229
  logger.warn("Could not delete files for #{self.class.to_s} #{to_param}")
227
230
  end
@@ -233,13 +236,13 @@ module HasImage
233
236
  def update_images
234
237
  return if storage.temp_file.blank?
235
238
  remove_images
236
- update_attribute(:has_image_file, storage.install_images(self.id))
239
+ update_attribute(:has_image_file, storage.install_images(has_image_id))
237
240
  end
238
241
 
239
242
  # Processes and installs the image and its thumbnails.
240
243
  def install_images
241
244
  return if !storage.temp_file
242
- update_attribute(:has_image_file, storage.install_images(self.id))
245
+ update_attribute(:has_image_file, storage.install_images(self))
243
246
  end
244
247
 
245
248
  # Gets an instance of the underlying storage functionality. See
@@ -248,6 +251,15 @@ module HasImage
248
251
  @storage ||= HasImage::Storage.new(has_image_options)
249
252
  end
250
253
 
254
+ # By default, just returns the model's id. Since this id is used to divide
255
+ # the images up in directories, you can override this to return a related
256
+ # model's id if you want the images to be grouped differently. For example,
257
+ # if a "member" has_many "photos" you can override this to return
258
+ # member.id to group images by member.
259
+ def has_image_id
260
+ id
261
+ end
262
+
251
263
  end
252
264
 
253
265
  module ModelClassMethods
data/test/storage_test.rb CHANGED
@@ -26,7 +26,7 @@ class StorageTest < Test::Unit::TestCase
26
26
  end
27
27
 
28
28
  def test_generated_file_name
29
- assert_match(/[a-z0-9]{4,6}/i, HasImage::Storage.generated_file_name)
29
+ assert_equal("1", HasImage::Storage.generated_file_name(stub(:to_param => 1)))
30
30
  end
31
31
 
32
32
  def test_path_for
@@ -36,7 +36,7 @@ class StorageTest < Test::Unit::TestCase
36
36
 
37
37
  def test_public_path_for
38
38
  @storage = HasImage::Storage.new(default_options.merge(:base_path => '/public'))
39
- pic = stub(:has_image_file => "mypic", :id => 1)
39
+ pic = stub(:has_image_file => "mypic", :has_image_id => 1)
40
40
  assert_equal "/tests/0000/0001/mypic_square.jpg", @storage.public_path_for(pic, :square)
41
41
  end
42
42
 
@@ -64,8 +64,8 @@ class StorageTest < Test::Unit::TestCase
64
64
  @storage = HasImage::Storage.new(default_options.merge(:thumbnails => {
65
65
  :one => "100x100", :two => "200x200"}))
66
66
  @storage.image_data = temp_file("image.jpg")
67
- assert @storage.install_images(1)
68
- assert @storage.remove_images(1)
67
+ @name = @storage.install_images(stub(:has_image_id => 1))
68
+ assert @storage.remove_images(stub(:has_image_id => 1), @name)
69
69
  end
70
70
 
71
71
  def test_image_not_too_small
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_image
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.11
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Norman Clarke