カテゴリー:
Rails
タグ:
 Rails 画像 Paperclip 添付ファイル アップロード

このエントリーをはてなブックマークに追加
更新日時:
2014年02月12日(水)
作成日時:
2013年04月22日(月)

前の記事 / 次の記事

Railsで画像やその他ファイルのアップロードを実装する場合、
アップロードするだけならサクっと書けるのだけど、

どこのディレクトリに保存して削除するときはこうしてとか色々考えてると
段々遠くに放り投げたくなって来るのでPaperclipを使ってみた時のメモ。

参考

モデル

各モデルに直接紐付けてもいいんだけど
画像の表示位置とかファイル自体の属性として持たせたいものがあるので分ける。
(ファイル専用のモデルをつくってそれをファイルを持たせたいモデルに belongs_to させる。)

Migration

class CreateImages < ActiveRecord::Migration
  def change
    create_table :images do |t|
      t.string :align
      t.attachment :value

      t.timestamps
    end
  end
end

この時、アップロードファイルの属性名として file という値を使ってはいけない。
調べてないけどRailsかPaperclipの予約語っぽくて微妙にバグる。

Model

class Bgimage < ActiveRecord::Base
  attr_accessible :align, :value

  has_attached_file :value,
    :styles      => { :medium => "300x300>", :thumb => "100x100>" },
    :default_url => "/images/:style/missing.png"
end

この時、 :styles => で指定しているのはImageMagickのオプションなので
指定方法についてはImageMagickのオプションの指定方法を参照する。ここでは特に触れない。

また1つのオブジェクトが 複数のファイルに対応する可能性のある場合
(1つのプロフィールが複数のプロフィール画像を持つような場合)は、

デフォルトのままだと正常に動作しないので、例えば次のように:path と :url を指定する必要がある。
(デフォルトの状態ではオブジェクトとファイルが必ず1対1で対応することが想定されている。)

以下はPaperclipインストール時に出力される注意書き

has_attached_file :avatar,
  :path => ":rails_root/public/system/:attachment/:id/:style/:filename",
  :url => "/system/:attachment/:id/:style/:filename"

今回は必ず1対1で対応することを想定しているのでこの注意書きはスルー。

ビュー

-# haml
=f.text_field :align
=f.file_field :value

とか。後は普通にオブジェクトを保存すればファイルも保存される。

また、削除する場合はPaperclipの説明だと、

@image.value = nil
@image.save

とすれば削除出来ると書いてあって、もちろんそうしても削除出来るのだけど、
紐付いてるオブジェクトが削除された場合は自動的にファイルの方も削除される。

@image.destroy

でアップロードされたファイルも削除される。

アマゾンS3にも簡単に保存出来るっぽいけどそれはまだ試してない。

オプション

保存するファイルの大きさを指定する

次の指定はいずれもアスペクト比は維持される。

has_attached_file :value,
  styles: { large: "2048x<", medium: "1024x768", thumb: "100x100>" }

ビューで次のように使える。

-# haml
- Image.all.each do |image|
  %p=image.name
  %ul
    %li=image_tag image.value(:large)
    %li=image_tag image.value(:medium)
    %li=image_tag image.value(:thumb)

各ディレクションについて

"2048x"<

  • 横のサイズが 2048px より小さければこの範囲内に拡大した画像を作成する。
  • 横のサイズが 2048px より大きければオリジナル画像を使用する。

"1024x768"

  • 1024px x 768px の画像を作成する。
  • オリジナル画像の解像度に関わらず作成する。

"100x100>"

  • 100px x 100px より大きければこの範囲内に縮小した画像を作成する。
  • 縦横がぞれぞれ 100px より小さければオリジナル画像を使用する。

保存場所を指定する

has_attached_file :value,
  url: "/system/:class/:id/:style/:filename"

image.url(:large) #=> "/system/images/1/large/mountain.jpg"

デフォルト値は

:rails_root/public/system/:class/:attachment/:id_partition/:style/:filename

image.url(:large) #=> "/style/images/values/000/000/001/large/mountain.jpg"

:id_partition が何をやっているのかというのは
同じディレクトリの中にファイル多過ぎ問題を解決するために
idによって保存するディレクトリを分ける役割をしている。

idが 10 の場合

000/000/010

idが 23050980 の場合

023/050/980

ファイル名を難読化する

has_attached_file :value,
  hash_secret: "NankaTekidoniNagaiMojiretsu",
  url: "/system/:class/:id/:style/:hash.:extension"