has_image 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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