【ruby on rails】file_columnを使った画像ファイルのアップロード

image_uploadプラグインを使ってみたけど、やはり画像のテーブルを独立しているためDBアクセスが非常に多く気になってしょうがない。画像のアップロードのサンプルを探したところimage_uploadにいきなり辿りついたのでとびついて使ってみたのだけど、どうやらfile_columnプラグインというのがよく使われているものらしい。file_columnではimage_uploadと同じでImageMagickとRMagickが必須らしい。(というか画像のサイズ変更などが面倒だからプラグインを使うわけで、そうでないなら自分でアップろーどするわな)それらは、既にインストールしてあるので、file_columnのみいれればよさそう。

というわけで、さっそくインストール

# ruby script/plugin install http://opensvn.csie.org/rails_file_column/plugins/file_column/trunk
# mv vendor/plugins/trunc vendor/plugins/file_column
# 

インストールは以上で完了


まずは画像を管理したいテーブルに以下のimageカラムを追加する。

image varchar(255) NOT NULL

このカラムには、画像のファイル名が入り画像データ自体はディスク上に保存されます。

テーブルを変更したら当然modelも変更。該当するmodelに、file_columnの定義を追加する。このfile_columnの定義が奥が深い。どうやらfile_columnにアップロードファイルを代入するのと同時にファイルが保存される仕組みのようだ。

class Hogehoge < ActiveRecord::Base
  file_column :image
end

サムネイルなどをアップロードと同時に作りたい場合は以下のようにmodelに定義する。

class Hogehoge < ActiveRecord::Base
  file_column :image, :magick => {
    :versions => {
      :icon => "16x16",
      :thumb => "40x40",
      :midle => "120x120",
    }
  }
end

アップロードした画像ファイルはpublic/[モデル名/[カラム名/[id]/ディレクトリの下に作られます。上記例だと

public/hogehoge/image/[id]/[オリジナルファイル名]
public/hogehoge/image/[id]/icon/[オリジナルファイル名]
public/hogehoge/image/[id]/thum/[オリジナルファイル名]
public/hogehoge/image/[id]/midle/[オリジナルファイル名]

といった具合に、public直下にmodel単位にディレクトリを掘っていきます><
さすがにどこか1つのディレクトリにまとめたいのでweb_rootとroot_pathを指定する。

web_rootってのはHelperで画像へのパスを取得する際に利用するらしいです。root_pathがファイルの保存先です。

class Hogehoge < ActiveRecord::Base
  file_column :image, :magick => { 
      :versions => {
        :icon  => "16x16",
        :thumb => "40x40",
        :medium => "120x120"
      }
    },
    :web_root => "attached_files/", 
    :root_path => File.join(RAILS_ROOT, "public", "attached_files")
end


続いてViewですが、uploadフォームは以下のHelperで利用可能
file_column_field("hogehoge", "image")

画像へのパスは以下のHelperで利用可能
url_for_file_column("hogehoge", "image")

画像サイズを指定する場合は以下のようにmodelのversionsで指定した名前を記述。
url_for_file_column("hogehoge", "image", "thumb")

Controllerに至ってはそのまま代入して保存するだけ。

def picture
    @hogehoge = Hogehoge.new(@params[:hogehoge])
    @hogehoge.save
end
[code]

非常に簡単でいい感じです。


注意が2点
まず、1点目
Viewにて以下のようなeach処理で利用する場合、nilのオブジェクトにアクセスしたエラーが発生します。
[code]
<% for hoge in @hogehoges %>
<% unless hoge.image.blank? %>
  <img src="<%= url_for_file_column("hoge", "image") %>" />
<% end %>
<% end %>

発生するエラーはこんなの

You have a nil object when you didn't expect it!
The error occurred while evaluating nil.image_relative_path

どうやら、url_for_file_columnがインスタンス変数でないとアクセスできないらしい。each処理の中で使う場合は以下のようにインスタンス変数につっこめば大丈夫でした。

<% for hoge in @hogehoges %>
<% @hoge = hoge %>
<% unless hoge.image.blank? %>
  <img src="<%= url_for_file_column("hoge", "image") %>" />
<% end %>
<% end %>


続いて2点目
どうもfile_columnを入れてから、アプリが異常に重くなった。
しかもたまに、以下のようなデバッグ文らしきものが出力される時がある。

Loaded suite xxxxxxxxxxxx dispatch.cgi
Started

中略

Finished in xxx seconds.
0 tests, 0 assertions, 0 failures, 0 errors

なんだこれは!
と思っていたら、vendor/plugins/file_column/init.rbにある
require 'test_case'
コメントアウトすればいいらしいんだけど
これなんて罠だよ!

関連:
http://wiki.rubyonrails.org/rails/pages/HowToUseFileColumn

タグ:[ruby on rails

このログへのコメント(558件)

コメント回数がひどいことに

海外スパムうぜえ

またか

この記事ロックオンされてるな

またか orz

コメント投稿フォーム

コメント

※半角英数字だけのコメントは投稿できません。

トラックバック

関連ログ