has_image 0.1.11 → 0.2.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,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