norman / has_image

A lightweight and opinionated but hackable library for attaching images to ActiveRecord models.

This URL has Read+Write access

has_image / README
100644 205 lines (152 sloc) 7.92 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
= HasImage[http://github.com/norman/has_image] -- Image attachment gem/plugin for Ruby on Rails
 
HasImage allows Ruby on Rails applications to have attached images. It is very
small and lightweight: it only requires one column ("has_image_file") in your
model to store the uploaded image's file name.
 
HasImage was created as a smaller, simpler, lighter alternative to
attachment_fu[http://github.com/technoweenie/attachment_fu] for applications
that need to handle uploaded images.
 
It is, by design, very simplistic: It only supports using a filesystem
for storage, and only supports
MiniMagick[http://github.com/probablycorey/mini_magick] as an image processor.
However, its code is very small, clean and hackable, so adding support for
other backends or processors should be fairly easy.
 
Some typical use cases are: websites that want to create photo galleries with
fixed-dimension thumbnails, or that want to store user profile pictures
without creating a separate model for the images.
 
It uses ImageMagick's
crop[http://www.imagemagick.org/script/command-line-options.php#crop] and
{center
gravity}[http://www.imagemagick.org/script/command-line-options.php#gravity]
functions to produce thumbnails that generally look acceptable, unless the
image is a panorama, or the subject matter is close to one of the margins,
etc. For most sites where people upload pictures of themselves or their pets
the generated thumbnails will look good almost all the time.
 
It creates only one database record per image, requires only one column in
your model, and creates great-looking fixed-dimension thumbnails by using
{ImageMagick's}[http://www.imagemagick.org/]
resize[http://www.imagemagick.org/script/command-line-options.php#resize],
crop[http://www.imagemagick.org/script/command-line-options.php#crop] and
gravity[http://www.imagemagick.org/script/command-line-options.php#gravity]
functions.
 
 
It supports only filesystem storage, and uses only MiniMagick[http://github.com/probablycorey/mini_magick] to process
images. However, the codebase is very small, simple, readable, and hackable.
So it should be easy to modify or enhance its functionality with different
storage or processor options.
 
== Another image attachment library? Why?
 
<em>The three chief virtues of a programmer are: Laziness, Impatience and Hubris.</em> - {Larry Wall}[http://en.wikipedia.org/wiki/Larry_Wall]
 
Attachment_fu is too large and general for some of the places I want to use
images. I sometimes found myself writing more code to hack attachment_fu than
it took to create this gem. In fact, most of the code here has been plucked
from my various projects that use attachment_fu.
 
The other image attachment libraries I found fell short of my needs for
various other reasons, so I decided to roll my own.
 
Compared to attachment_fu, HasImage has advantages and disadvantages.
 
=== Advantages:
 
  * Simpler, smaller, more easily hackable codebase - and specialized for
    images only.
  * Installable via Ruby Gems. This makes version dependencies easy when using
    Rails 2.1.
  * Creates only one database record per image.
  * Has built-in facilities for making distortion-free, fixed-size thumbnails.
  * Doesn't regenerate the thumbnails every time you save your model. This means
    you can easily use it, for example, inside a Member model to store member
    avatars.
 
=== Disadvantages:
 
  * Doesn't save image dimensions. However, if you're using fixed-sized images,
    this is not a problem because you can just read the size from MyModel.thumbnails[:my_size]
  * No support for AWS or DBFile storage, only filesystem.
  * Only supports MiniMagick[http://github.com/probablycorey/mini_magick/tree] as an image processor, no RMagick, GD, CoreImage,
    etc.
  * No support for anything other than image attachments.
  * Not as popular as attachment_fu, which means fewer bug reports, and
    probably more bugs. Use at your own risk!
 
== Examples
 
Point-and-drool use case. It's probably not what you want, but it may be
useful for bootstrapping.
 
  class Member < ActiveRecord::Base
    has_image
  end
 
Single image, no thumbnails, with some size limits:
 
  class Picture < ActiveRecord::Base
    has_image :resize_to => "200x200",
      :max_size => 3.megabytes,
      :min_size => 4.kilobytes
  end
 
Image with some thumbnails:
 
  class Photo < ActiveRecord::Base
    has_image :resize_to => "640x480",
      :thumbnails => {
        :square => "200x200",
        :medium => "320x240"
      },
      :max_size => 3.megabytes,
      :min_size => 4.kilobytes
  end
  
It also provides a view helper to make displaying the images extremely simple:
 
  <%= image_tag_for(@photo) # show the full-sized image %>
  <%= image_tag_for(@photo, :thumb => :square) # show the square thumbnail %>
 
The image_tag_for helper calls Rails' image_tag, so you can pass in all the
regular options to set the alt property, CSS class, etc:
  
  <%= image_tag_for(@photo, :alt => "my cool picture", :class => "photo") %>
  
Setting up forms for has_image is simple, too:
 
  <% form_for(@photo, :html => {:multipart => true}) do |f| %>
    <p>
      <%= f.label :image_data %>
      <%= f.file_field :image_data %>
    </p>
    <p>
      <%= f.submit %>
    </p>
  <% end %>
 
== Getting it
 
Has image can be installed as a gem, or as a Rails plugin. Gem installation
is easiest, and recommended:
 
  gem install has_image
 
and add
 
  require 'has_image'
 
to your environment.rb file.
 
Alternatively, you can install it as a Rails plugin:
 
  ./script plugin install git://github.com/norman/has_image.git
  
Rails versions before 2.1 do not support plugin installation using Git, so if
you're on 2.0 (or earlier), then please install the gem rather than the
plugin.
  
Then, make sure the model has a column named "has_image_file."
 
{Git repository}[http://github.com/norman/has_image]:
 
  git://github.com/norman/has_image.git
 
== Hacking it
 
Don't like the way it makes images? Want to pipe the images through some
{crazy fast seam carving library written in
OCaml}[http://eigenclass.org/hiki/seam-carving-in-ocaml], or watermark them
with your corporate logo? Happiness is just a monkey-patch[http://en.wikipedia.org/wiki/Monkey_patch] away:
 
  module HasImage
    class Processor
      def resize_image(size)
        # your new-and-improved thumbnailer code goes here.
      end
    end
  end
 
HasImage[http://github.com/norman/has_image] follows a philosophy of "{skinny
model, fat plugin}[http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model]."
This means that it tries to pollute your ActiveRecord model with as little
functionality as possible, so that in a sense, the model is acts like a
"controller" and the plugin like a "model" as regards the image handling
functionality. This makes it easier to test, hack, and reuse, because the
storage and processing functionality is largely independent of your model, and
of Rails.
 
My goal for HasImage[http://github.com/norman/has_image] is to keep it very
small. If you need *a lot* of functionality that's not here, instead of patching
this code, you will likely be better off using
attachment_fu[http://github.com/technoweenie/attachment_fu], which is much
more powerful, but also more complex.
 
== Bugs
 
Please report them on Lighthouse[http://randomba.lighthouseapp.com/projects/14674-has_image].
 
At the time of writing (July 2008),
HasImage[http://github.com/norman/has_image] is in its infancy. Your patches,
bug reports and withering criticism are more than welcome.
 
== Links
 
* {HasImage RDocs}[http://randomba.org/projects/has_image] (regenerated nightly)
* {HasImage on GitHub}[http://github.com/norman/has_image]
* {HasImage on Rubyforge}[http://rubyforge.org/projects/has-image/]
* {HasImage on Lighthouse}[http://randomba.lighthouseapp.com/projects/14674-has_image]
 
Copyright (c) 2008 {Norman Clarke}[mailto:norman@randomba.org], released under
the MIT license