has_image 0.3.0 → 0.4.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.md ADDED
@@ -0,0 +1,100 @@
1
+ ## 0.4.0 (2010-09-29)
2
+
3
+ We have picked up maintainence of has\_image after a few years of neglect. This
4
+ is a transitional release which adds Rails 3 compatibility and a few small bug
5
+ fixes, as well as the following:
6
+
7
+ * Allow passing `nil` to avoid resizing.
8
+
9
+ ## Older changes
10
+
11
+ ### 2009-03-11
12
+
13
+ * Fix a critical problem with image updates breaking when used together with
14
+ Rails' partial updates feature (now "on" by default). Thanks to Juan
15
+ Schwindt <juan@schwindt.org> for the report.
16
+ * Replaced a raw SQL call with update_all.
17
+
18
+ ### 2008-10-22
19
+
20
+ * Added option to not delete images on destroy
21
+ * Made thumbnail name separator configurable
22
+ * Added height/width methods to storage
23
+ * Allowed regenerating only one thumbnail size
24
+ * Made has_image column configurable
25
+ * Added some compatibility with attachment_fu
26
+ * General refactorings and overall code improvement
27
+
28
+ ### 2008-10-22
29
+
30
+ * Documentation improvements and minor code cleanups.
31
+
32
+ ### 2008-10-09
33
+
34
+ * Fixed display of images with special symbols in the name,
35
+ like '2777-nipple-+-apple-napple.jpg'. + is reserved by HTTP.
36
+ Now escaping filenames before giving them back in #public_path()
37
+
38
+ ### 2008-09-10
39
+
40
+ * Fixed images not being converted to target format.
41
+
42
+ ### 2008-08-29
43
+
44
+ * Fixed bad call to has_image_file
45
+
46
+ ### 2008-08-28
47
+
48
+ * Added ability to regenerate a model's thumbnails.
49
+ * Changed a few methods in storage to accept the model rather than the id.
50
+ This makes storage more hackable as regards generating paths and file names.
51
+ * Added "has_image_id" method to model instance methods to facilitate
52
+ grouping the images under a directory structure based on a related model's
53
+ ids.
54
+ * Made the generated file name simply by the image object's id - this
55
+ is better adherance to the principle of least surprise.
56
+
57
+ ### 2008-08-25
58
+
59
+ * Fixed bad call to resize_to in view helper.
60
+
61
+ ### 2008-08-19
62
+
63
+ * Made storage work more correctly with tempfiles.
64
+
65
+ ### 2008-08-18
66
+
67
+ * Fixed ability to set the path for storing image files.
68
+
69
+ ### 2008-08-01
70
+
71
+ * Improved partitioned path handling to avoid collisions when the id is
72
+ very high, which can happen if you use db:fixtures:load.
73
+
74
+ ### 2008-08-01
75
+
76
+ * Fixed a bug where overwriting a previous image triggered callbacks more
77
+ than once, causing errors.
78
+
79
+ ### 2008-07-29
80
+
81
+ * Downcased generated file names to avoid potential issues on
82
+ case-insensitive filesystems.
83
+ * Added "absolute path" method to model instances.
84
+ * Made image deletion nullify the "has_image_file" field.
85
+ * Added "has_image?" method to model instances.
86
+ * Fixed ENONENT error with record update when there are no images yet.
87
+ * Reverted thumbnail sorting feature - it's fast but makes terrible quality
88
+ thumbnails. It's just not worth it.
89
+
90
+ ### 2008-07-28
91
+
92
+ * Added sorted thumbnail processing. This improves thumbnail generation
93
+ speed by about 25% for 4.5 meg jpegs with 5 thumbnails.
94
+ * Fixed broken resize for non-fixed-width thumbnails.
95
+ * Added check for bad geometry strings.
96
+ * Added dependencies and Rubyforge project to gemspec, updated docs.
97
+
98
+ ### 2008-07-25
99
+
100
+ * First public release.
data/MIT-LICENSE CHANGED
@@ -1,20 +1,18 @@
1
- Copyright (c) 2008 [name of plugin creator]
1
+ Copyright (c) 2008-2010 Norman Clarke and Adrián Mugnolo
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
10
9
 
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
13
12
 
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # has\_image - An Image attachment library for Active Record
2
+
3
+ The has\_image library extends Active Record to allow Rails applications to have
4
+ attached images. It is very small and lightweight: it only requires one column
5
+ in your model to store the uploaded image's file name.
6
+
7
+ It was originally created as a smaller, simpler, lighter alternative to
8
+ [attachment_fu](http://github.com/technoweenie/attachment_fu) for applications
9
+ that need to handle uploaded images.
10
+
11
+ It only supports using a filesystem for storage, and only supports
12
+ [MiniMagick](http://github.com/probablycorey/mini_magick) as an image processor.
13
+ However, its code is very small, clean and hackable, so adding support for other
14
+ backends or processors should be fairly easy.
15
+
16
+ Some typical use cases are: websites that want to create photo galleries with
17
+ fixed-dimension thumbnails, or that want to store user profile pictures without
18
+ creating a separate model for the images.
19
+
20
+ It creates only one database record per image, and uses ImageMagick's
21
+ [crop](http://www.imagemagick.org/script/command-line-options.php#crop) and
22
+ [center
23
+ gravity](http://www.imagemagick.org/script/command-line-options.php#gravity)
24
+ functions to produce thumbnails that generally look acceptable, unless the image
25
+ is a panorama, or the subject matter is close to one of the margins, etc. For
26
+ most sites where people upload pictures of themselves the generated thumbnails
27
+ will look good almost all the time.
28
+
29
+ ## Examples
30
+
31
+ Point-and-drool use case. It's probably not what you want, but it may be useful
32
+ for bootstrapping.
33
+
34
+ class Member < ActiveRecord::Base
35
+ has_image
36
+ end
37
+
38
+ Single image, no thumbnails, with some size limits:
39
+
40
+ class Picture < ActiveRecord::Base
41
+ has_image :resize_to => "200x200",
42
+ :max_size => 3.megabytes,
43
+ :min_size => 4.kilobytes
44
+ end
45
+
46
+ Image with some thumbnails:
47
+
48
+ class Photo < ActiveRecord::Base
49
+ has_image :resize_to => "640x480",
50
+ :thumbnails => {
51
+ :square => "200x200",
52
+ :medium => "320x240"
53
+ },
54
+ :max_size => 3.megabytes,
55
+ :min_size => 4.kilobytes
56
+ end
57
+
58
+ It also provides a view helper to make displaying the images extremely simple:
59
+
60
+ <%= image_tag_for(@photo) # show the full-sized image %>
61
+ <%= image_tag_for(@photo, :thumb => :square) # show the square thumbnail %>
62
+
63
+ The image_tag_for helper calls Rails' image_tag, so you can pass in all the
64
+ regular options to set the alt property, CSS class, etc:
65
+
66
+ <%= image_tag_for(@photo, :alt => "my cool picture", :class => "photo") %>
67
+
68
+ Setting up forms for has\_image is simple, too:
69
+
70
+ <% form_for(@photo, :html => {:multipart => true}) do |f| %>
71
+ <p>
72
+ <%= f.label :image_data %>
73
+ <%= f.file_field :image_data %>
74
+ </p>
75
+ <p>
76
+ <%= f.submit %>
77
+ </p>
78
+ <% end %>
79
+
80
+ ## Compatibility
81
+
82
+ Has\_image is compatible with Rails 2.1.x - 3.0.x.
83
+
84
+ ## Getting it
85
+
86
+ Install has_image via RubyGems:
87
+
88
+ gem install has_image
89
+
90
+ and add it to your Gemfile (Rails 3.0.x) or environment.rb (Rails 2.x).
91
+
92
+ Then, add a column named `has_image_file` to your model.
93
+
94
+ ## Source code
95
+
96
+ [http://github.com/norman/has_image](http://github.com/norman/has_image)
97
+
98
+ ## FAQ
99
+
100
+ ### How do I validate the mime type of my uploaded images?
101
+
102
+ You don't. Rather than examine the mime type, has\_image runs the "identify"
103
+ command on the file to determine if it is processable by ImageMagick, and if it
104
+ is, converts it to the format you specify, which defaults to JPEG.
105
+
106
+ This is better than checking for mime types, because your users may upload
107
+ exotic image types that you didn't even realize would work, such as Truevision
108
+ Targa images, or Seattle Film Works files.
109
+
110
+ If you wish to give users a list of file types they can upload, a good start
111
+ would be jpeg, png, bmp, and maybe gif and ttf if your installation of
112
+ ImageMagick understands them. You can find out what image types your ImageMagick
113
+ understands by running:
114
+
115
+ identify -list format
116
+
117
+ Ideally, if your users just upload files that "look like" images on their
118
+ computers, it has\_image should "just work."
119
+
120
+ ## Hacking it
121
+
122
+ Don't like the way it makes images? Want to pipe the images through some [crazy
123
+ fast seam carving library written in
124
+ OCaml](http://eigenclass.org/hiki/seam-carving-in-ocaml), or watermark them with
125
+ your corporate logo? Happiness is just a
126
+ [monkey-patch](http://en.wikipedia.org/wiki/Monkey_patch) away:
127
+
128
+ module HasImage
129
+ class Processor
130
+ def resize_image(size)
131
+ # your new-and-improved thumbnailer code goes here.
132
+ end
133
+ end
134
+ end
135
+
136
+ Has\_image follows a philosophy of [skinny model, fat
137
+ plugin](http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model.)
138
+ This means that it tries to pollute your ActiveRecord model with as little
139
+ functionality as possible, so that in a sense, the model is acts like a
140
+ "controller" and the plugin like a "model" as regards the image handling
141
+ functionality. This makes it easier to test, hack, and reuse, because the
142
+ storage and processing functionality is largely independent of your model, and
143
+ of Rails.
144
+
145
+ ## Bugs
146
+
147
+ Please report them on the Github issue tracker.
148
+
149
+ Copyright (c) 2008-2010 Norman Clarke and Adrian Mugnolo. Released under the MIT
150
+ License.
151
+
152
+ ## Acknowledgements
153
+
154
+ We'd like to thank the following contributors for their help with has\_image:
155
+
156
+ * [Juan Schwindt](http://github.com/jschwindt)
157
+ * [Gerrit Keiser](http://github.com/gerrit)
158
+ * the folks from [Tricycle Developments](http://github.com/tricycle)
159
+ * [Dima Sabanin](http://github.com/railsmonk)
data/Rakefile CHANGED
@@ -1,11 +1,12 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
- require 'rake/rdoctask'
3
+ require "rake/gempackagetask"
4
+ require "rake/clean"
4
5
 
5
- desc 'Default: run unit tests.'
6
- task :default => :test
6
+ CLEAN << "pkg" << "doc" << "coverage"
7
+ Rake::GemPackageTask.new(eval(File.read("has_image.gemspec"))) { |pkg| }
7
8
 
8
- task :all_tests => [:test, :test_rails]
9
+ task :default => :test
9
10
 
10
11
  desc 'Test the non-Rails part of has_image.'
11
12
  Rake::TestTask.new(:test) do |t|
@@ -13,37 +14,4 @@ Rake::TestTask.new(:test) do |t|
13
14
  t.libs << 'test'
14
15
  t.pattern = 'test/**/*_test.rb'
15
16
  t.verbose = true
16
- end
17
-
18
- desc 'Test the Rails part of has_image.'
19
- Rake::TestTask.new(:test_rails) do |t|
20
- t.libs << 'lib'
21
- t.libs << 'test_rails'
22
- t.pattern = 'test_rails/**/*_test.rb'
23
- t.verbose = true
24
- end
25
-
26
- desc "Run rcov"
27
- task :rcov do
28
- rm_f "coverage"
29
- rm_f "coverage.data"
30
- if PLATFORM =~ /darwin/
31
- exclude = '--exclude "gems"'
32
- else
33
- exclude = '--exclude "rubygems"'
34
- end
35
- rcov = "rcov --rails -Ilib:test --sort coverage --text-report #{exclude} --no-validator-links"
36
- cmd = "#{rcov} #{Dir["test/**/*.rb"].join(" ")}"
37
- sh cmd
38
- end
39
-
40
- desc 'Generate documentation for has_image.'
41
- Rake::RDocTask.new(:rdoc) do |rdoc|
42
- rdoc.rdoc_dir = 'rdoc'
43
- rdoc.title = 'HasImage'
44
- rdoc.options << '--line-numbers' << '--inline-source' << '-c UTF-8'
45
- rdoc.rdoc_files.include('README.textile')
46
- rdoc.rdoc_files.include('FAQ')
47
- rdoc.rdoc_files.include('CHANGELOG')
48
- rdoc.rdoc_files.include('lib/**/*.rb')
49
- end
17
+ end
data/lib/has_image.rb CHANGED
@@ -1,3 +1,14 @@
1
+ require "cgi"
2
+ require "active_support"
3
+
4
+ # AR < 3 would autoload everything
5
+ unless "".respond_to? :to_param
6
+ require "active_support/core_ext/object/blank"
7
+ require "active_support/core_ext/object/to_param"
8
+ require "active_support/core_ext/numeric/bytes"
9
+ require "active_support/core_ext/class/inheritable_attributes"
10
+ end
11
+
1
12
  require 'has_image/processor'
2
13
  require 'has_image/storage'
3
14
  require 'has_image/view_helpers'
@@ -58,7 +69,7 @@ require 'has_image/view_helpers'
58
69
  # directory. Add something like this to your config/environments/test.rb:
59
70
  #
60
71
  # config.after_initialize do
61
- # MyClass.has_image_options[:base_path] = File.join(RAILS_ROOT, "tmp")
72
+ # MyClass.has_image_options[:base_path] = File.join(RAILS_ROOT, "tmp")
62
73
  # end
63
74
  #
64
75
  # If you want to stub out calls to has_image so that your tests don't do
@@ -90,7 +101,6 @@ module HasImage
90
101
  def enable # :nodoc:
91
102
  return if ActiveRecord::Base.respond_to? :has_image
92
103
  ActiveRecord::Base.send(:include, HasImage)
93
- return if ActionView::Base.respond_to? :image_tag_for
94
104
  ActionView::Base.send(:include, ViewHelpers)
95
105
  end
96
106
 
@@ -243,7 +253,7 @@ module HasImage
243
253
  end
244
254
 
245
255
  def image_size
246
- [width, height] * 'x'
256
+ self[:image_size] || [width, height].join('x')
247
257
  end
248
258
 
249
259
  # Deletes the image from the storage.
@@ -254,9 +264,11 @@ module HasImage
254
264
  storage.remove_images(self, send(has_image_options[:column]))
255
265
  # The record will be frozen if we're being called after destroy.
256
266
  unless frozen?
257
- # Resorting to SQL here to avoid triggering callbacks. There must be
258
- # a better way to do this.
259
- self.connection.execute("UPDATE #{self.class.table_name} SET #{has_image_options[:column]} = NULL WHERE id = #{id}")
267
+ # FIXME: although this is cleaner now, it introduces a new issue
268
+ # with partial updates.
269
+ updates = "#{connection.quote_column_name(has_image_options[:column])} = NULL"
270
+ conditions = "#{connection.quote_column_name(self.class.primary_key)} = #{connection.quote(id)}"
271
+ self.class.update_all(updates, conditions)
260
272
  self.send("#{has_image_options[:column]}=", nil)
261
273
  end
262
274
  rescue Errno::ENOENT
@@ -297,17 +309,22 @@ module HasImage
297
309
  private
298
310
 
299
311
  def populate_attributes
312
+ # FIXME: this is a quick and dirty work around for image updates
313
+ # breaking when running with Rails' partial updates. This is originated
314
+ # by the update_all call in the remove_images method which bypasses
315
+ # ActiveRecord::Dirty attribute change tracking.
316
+ attribute_will_change!(has_image_options[:column].to_s) if respond_to?(:attribute_will_change!, true)
317
+
300
318
  send("#{has_image_options[:column]}=", storage.install_images(self))
301
319
  self[:width] = storage.measure(absolute_path, :width) if self.class.column_names.include?('width')
302
320
  self[:height] = storage.measure(absolute_path, :height) if self.class.column_names.include?('height')
321
+ self[:image_size] = [storage.measure(absolute_path, :width), storage.measure(absolute_path, :height)].join('x') if self.class.column_names.include?('image_size')
303
322
  save!
304
323
  end
305
324
 
306
-
307
325
  end
308
326
 
309
327
  module ModelClassMethods
310
-
311
328
  # Get the hash of thumbnails set by the options specified when invoking
312
329
  # HasImage::ClassMethods#has_image.
313
330
  def thumbnails
@@ -317,11 +334,13 @@ module HasImage
317
334
  def from_partitioned_path(path)
318
335
  find HasImage::Storage.id_from_path(path)
319
336
  end
320
-
321
337
  end
322
-
323
338
  end
324
339
 
325
- if defined?(Rails) and defined?(ActiveRecord) and defined?(ActionController)
326
- HasImage.enable
340
+ if defined?(Rails)
341
+ if Rails.version >= "3"
342
+ require "has_image/railtie"
343
+ else
344
+ HasImage.enable
345
+ end
327
346
  end