今さらRails3メモ - 番外編その1: Paperclip and Dragonfly -

アップロード画像は変遷がいろいろ激しいみたい

画像をアップロードしてそれを表示に利用するのはとてもよくある処理だと思うんだけど、ゼロから実装するのは意外に面倒くさい。でも Rails には便利な plugin があるので大丈夫。

歴史的なことは知らないんだけど、最近は

の二択くらいな感じみたい。どちらも簡単に扱えるけどどっちかというと Dragonfly の方がより簡単で好きかも。ただし今のところ Dragonfly の方が情報は少ないけど。

Paperclip

thoughtbot/paperclip - GitHub

migration

README から抜粋すると以下の field を持つテーブルが必要らしい。らしいっていうか、実際試してみたんだけど、このエントリ書くまで日が空きすぎて忘れてしまった。

class AddAvatarColumnsToUser < ActiveRecord::Migration
  def self.up
    add_column :users, :avatar_file_name,    :string
    add_column :users, :avatar_content_type, :string
    add_column :users, :avatar_file_size,    :integer
    add_column :users, :avatar_updated_at,   :datetime
  end

  def self.down
    remove_column :users, :avatar_file_name
    remove_column :users, :avatar_content_type
    remove_column :users, :avatar_file_size
    remove_column :users, :avatar_updated_at
  end
end

Model

上の migration に対応する Model はこうなる。

class User < ActiveRecord::Base
  has_attached_file :avatar

  ...
end

ここで画像用の attribute は avatar になって、file_name やらなんやらは meta data としていい具合に処理してくれるようになる。

View

こんな感じ。

<%= image_tag @user.avatar.url %>
<%= image_tag @user.avatar.url(:medium) %>
<%= image_tag @user.avatar.url(:thumb) %>

今回の例は User モデルに avatar 関連の attribute をそのまま載せているが、分離して association でも処理できる。

form 側はこんな感じ。

<% form_for :user, @user, :url => user_path,
            :html => { :multipart => true } do |form| %>
  <%= form.file_field :avatar %>
<% end %>

単に file_field に当てはめるだけ。

参考

Dragonfly

http://markevans.github.com/dragonfly/

Paperclip のようにはドキュメントや紹介記事を見かけないけど、コードを覗いていくと storage として file, mongo, s3 が使えるみたい。

下準備

config/initializers/dragonfly.rb

require 'dragonfly/rails/images'

migration

最低限一つだけ field があればよいみたい。

class MyMigration < ActiveRecord::Migration

  def self.up
    add_column :albums, :cover_image_uid, :string
  end

  def self.down
    remove_column :albums, :cover_image_uid
  end

end

Model 上でどんな attribute に画像を紐づけるか決めて、

#{attribute}_uid

があれば ok.

Model

上の migration に対応する最低限の Model の記述は

class Album
  image_accessor :cover_image
end

image_accessor で attribute を指定するだけ。すると以下のような感じで meta data を取れる。

@album.cover_image.width
@album.cover_image.height
@album.cover_image.number_of_colours
@album.cover_image.mime_type

View

<%= image.caption %></th>
<%= image_tag( image.photo.process(:thumb, '240x240#').url,
               {:size => '240x240', :alt => image.caption} ) %>

こんな風に書ける。

form 側は

<% form_for @album, :html => {:multipart => true} do |f| %>
  ...
  <%= f.file_field :cover_image %>
  ...
<% end %>

同じ要領ですな。

注意

当たり前だけど image_tag を生成すること。でないと表示されない。

More