railsでPaperclipを使ってみる
PaperclipはRailsで画像を扱うためのプラグインです。
http://www.thoughtbot.com/projects/paperclip/
Railsで画像を扱うプラグインにはattachment_fuなどがあるのですが
attachment_fuでは画像を取り扱うために専用のモデルを必要としているのですが
こちらは専用のモデルが必要がなく、自分で定義するモデルに自由に画像を取り込めるようです。
さっそく使ってみる。
プラグインのインストール
script/plugin install git://github.com/thoughtbot/paperclip.git
とりあえずrdocを読んでみる
less vendor/plugins/paperclip/README.rdoc
色々書いてあるが押さえておきたいのは画像の保存場所に関しての説明
画像の保存場所はモデルに追加するオプションで指定するか
:path
デフォルト設定にまかせてpubulic/system以下の下記のパスに保存させることができる。
:rails_root/public/system/:attachment/:id/:style/:basename.:extension
Imageモデルを作成してみる。その際、様々なモデルに関連付けできるようにしておく
$ script/generate model Image type:sting parent_type:string parent_id:integer image_file_name:string image_content_type:string image_file_size:integer image_updated_at:datetime #長いので途中で改行してます
こんな感じのマイグレーションファイルができる
class CreateImages < ActiveRecord::Migration def self.up create_table :images do |t| t.sting :type t.string :parent_type t.integer :parent_id t.string :image_file_name t.string :image_content_type t.integer :image_file_size t.datetime :image_updated_at t.timestamps end end def self.down drop_table :images end end
次にモデルを書き換える
class Image < ActiveRecord::Base belongs_to :parent, :polymorphic => true # Paperclip has_attached_file :image, :styles => { :medium => "250x250>", # >はリサイズ :thumb => "100x100#" # #はトリミング }, # :url => "/store/:attachment/:id/:style/:basename.:extension", # 表示用url # :path => ":rails_root/public/store/:attachment/:id/:style/:basename.:extension" # 画像保存path # 拡張子の制限 validates_attachment_content_type :image, :content_type => ['image/jpg', 'image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png'], :message => "JPG, GIF, PNGのみアップロードできます" # ファイルサイズ制限 validates_attachment_size :image, :less_than => 2.megabytes, :message => "ファイルサイズが大きすぎます(最大 :max バイトまで)" end
次にエントリーモデルの作成
class Entry < ActiveRecord::Base has_many :images, :as => :parent, :dependent => :destroy end
parentでポリモーフィック関連させる。
次にmodels/image/entry_image.rbを作成
class Image::EntryImage < Image end
あとはビューとコントローラをちょいちょいと修正する
コントローラ
class EntriesController < ApplicationController #その他省略 # POST /entries # POST /entries.xml def create @entry = Entry.new(params[:entry]) @image = Image::EntryImage.new(params[:image]) respond_to do |format| if @entry.save @entry.images << @image # 追加 flash[:notice] = 'Entry was successfully created.' # format.html { redirect_to(@entry) } format.html { redirect_to('/') } format.xml { render :xml => @entry, :status => :created, :location => @entry } else format.html { render :action => "new" } format.xml { render :xml => @entry.errors, :status => :unprocessable_entity } end end end # その他省略 end
投稿画面のview
multipartをtrueにして投稿できるようにする
<h1>新規投稿</h1> <% form_for(@entry, {}, { :html => { :multipart => true } }) do |f| %> <%= f.error_messages %> <p> <%= f.label '題名' %><br /> <%= f.text_field :title %> </p> <p> <%= f.label '本文' %><br /> <%= f.text_area :body %> </p> <p> <%= file_field :image, :image %> </p> <p> <%= f.submit '投稿' %> </p> <% end %>
閲覧ページのビュー
コントローラで@entry取得したら
こんな感じに記述すればいい
modelの中でdelegateしてあるからimage.urlとスマートな呼び出し方ができる
<p> <b>Photos:</b> <%- @entry.images.each do |image| -%> <%= image_tag image.url %> <%= image_tag image.url(:medium) %> <%= image_tag image.url(:thumb) %> <%- end -%> </p>
こんなかんじで動作確認してみたところ無事動きました。
参考
http://d.hatena.ne.jp/hichiriki/20081130
http://d.hatena.ne.jp/lov2much/20090105/1231173820