FileColumn

画像ファイルなどのファイルの扱いが簡単にできるFileColumnを紹介します。
ベースとするプロジェクトを「i18nによる日本語化」で使用したproj001とします。


1.file_columnのインストール

コマンド プロンプト

D:\Rails_Projects\proj001>ruby script/plugin install http://filecolumn.googlecode.com/svn/tags/file_column
./CHANGELOG
./README
./Rakefile
./TODO
./init.rb
./lib/file_column.rb
./lib/file_column_helper.rb
./lib/file_compat.rb
./lib/magick_file_column.rb
./lib/rails_file_column.rb
./lib/test_case.rb
./lib/validations.rb
./test/abstract_unit.rb
./test/connection.rb
./test/file_column_helper_test.rb
./test/file_column_test.rb
./test/fixtures/entry.rb
./test/fixtures/invalid-image.jpg
./test/fixtures/kerb.jpg
./test/fixtures/mysql.sql
./test/fixtures/schema.rb
./test/fixtures/skanthak.png
./test/magick_test.rb
./test/magick_view_only_test.rb


2.項目の追加
  NetBeansで[生成]を選択します。
   ジェネレータ(G):migration
   引数(A):add_image_to_addresses image:string
    



3.マイグレーションファイルの確認
  db/migrate/yyyymmddhhmmss_add_image_to_addresses.rbを確認してみましょう。
  項目imageが追加されています。
/db/migrate/yyyymmddhhmmss_add_image_to_addresses.rb

class AddImageToAddresses < ActiveRecord::Migration
def self.up
add_column :addresses, :image, :string
end

def self.down
remove_column :addresses, :image
end
end



4.マイグレーションの実行
  [データベースマイグレーション]より[現在のバージョンへ]を選択します。


5.モデルの修正
/app/models/address.rb

class Address < ActiveRecord::Base
file_column :image

validates_presence_of :namae
validates_uniqueness_of :namae
validates_length_of :namae, :maximum => 12
validates_presence_of :yubin
validates_length_of :yubin, :within => 3..8
validates_presence_of :jusho
validates_presence_of :denwa
validates_format_of :denwa, :with => /\d{3}-\d{3}-\d{4}|\d{4}-\d{2}-\d{4}/
end


6.ビューの修正
追加した項目imageをそれぞれのビュープログラムに埋め込みます。


/app/views/index.html.erb

<r/>
<h1><%= t('label.Listing_addresses') %></h1>


<table>
 <tr>
  <th><%= t('label.Namae') %></th>
  <th><%= t('label.Yubin') %></th>
  <th><%= t('label.Jusho') %></th>
  <th><%= t('label.Denwa') %></th>
  <th><%= t('label.Image') %></th>
 </tr>


<% for address in @addresses %>
 <tr>
  <td><%=h address.namae %></td>
  <td><%=h address.yubin %></td>
  <td><%=h address.jusho %></td>
  <td><%=h address.denwa %></td>
  <td><%=h address.image %></td>
  <td><%= link_to t('link.Show'), address %></td>
  <td><%= link_to t('link.Edit'), edit_address_path(address) %></td>
  <td><%= link_to t('link.Destroy'), address,
      :confirm => t('label.Are_you_sure?'), :method => :delete %></td>
 </tr>
<% end %>
</table>


<div class="pagination_link">
 <%= will_paginate @addresses, :prev_label => "« 前", :next_label => "次 »" %>
</div>


<br />


<%= link_to t('link.New_address'), new_address_path %>




/app/views/new.html.erb

<br/>
<h1><%= t('label.New_address') %></h1>


<% form_for(@address, :html => {:multipart => true}) do |f| %>
 <%= f.error_messages %>


 <p>
  <%= f.label t('label.Namae') %><br />
  <%= f.text_field :namae %>
 </p>
 <p>
  <%= f.label t('label.Yubin') %><br />
  <%= f.text_field :yubin %>
 </p>
 <p>
  <%= f.label t('label.Jusho') %><br />
  <%= f.text_field :jusho %>
 </p>
 <p>
  <%= f.label t('label.Denwa') %><br />
  <%= f.text_field :denwa %>
 </p>
 <p>
  <%= f.label t('label.Image') %><br />
  <%= f.file_field :image %>
 </p>



 <p>
  <%= f.submit t('button.Create') %>
 </p>
<% end %>


<%= link_to t('link.Back'), addresses_path %>




/app/views/edit.html.erb

<br/>
<h1><%= t('label.Editing_address', :html => {:multipart => true}) %></h1>


<% form_for(@address) do |f| %>
 <%= f.error_messages %>


 <p>
  <%= f.label t('label.Namae') %><br />
  <%= f.text_field :namae %>
 </p>
 <p>
  <%= f.label t('label.Yubin') %><br />
  <%= f.text_field :yubin %>
 </p>
 <p>
  <%= f.label t('label.Jusho') %><br />
  <%= f.text_field :jusho %>
 </p>
 <p>
  <%= f.label t('label.Denwa') %><br />
  <%= f.text_field :denwa %>
 </p>
 <p>
  <%= f.label t('label.Image') %><br />
  <%= f.file_field :image %>
 </p>



 <p>
  <%= f.submit t('button.Update') %>
 </p>
<% end %>


<%= link_to t('link.Show', @address %> |
<%= link_to t('link.Back'), addresses_path %>




/app/views/show.html.erb

<p>
 <b><%= t('label.Namae') %>:</b>
 <%=h @address.namae %>
</p>


<p>
 <b><%= t('label.Yubin') %>:</b>
 <%=h @address.yubin %>
</p>


<p>
 <b><%= t('label.Jusho') %>:</b>
 <%=h @address.jusho %>
</p>


<p>
 <b><%= t('label.Denwa') %>:</b>
 <%=h @address.denwa %>
</p>


<p>
 <b><%= t('label.Image') %>:</b>
 <%=h @address.image %>
</p>



<%= link_to t('link.Edit'), edit_address_path(@address) %> |
<%= link_to t('link.Back'), addresses_path %>

7.file_columnプラグインプログラムの修正
これで実行をするとNameErrorが発生します。
    

これの対処法は、http://d.hatena.ne.jp/aki-s-119/20081201/1228168584に詳しいですが、
次の部分を書き換えることでエラーは回避できます。

/vender/plugins/file_column/lib/file_column.rb

require 'fileutils'
require 'tempfile'
require 'magick_file_column'

module FileColumn # :nodoc:


def file_column(attr, options={})
options = DEFAULT_OPTIONS.merge(options) if options

my_options = FileColumn::init_options(options,
self.name.to_s.underscore,
attr.to_s)


end


end


8.動作確認
  実際にプログラムを実行してみます。
  ファイル名が英字の場合はうまくアップロードされますが、漢字の場合うまくいきません。
  (アップロードするファイル名が「顔写真-画像02.jpg」の場合)
    

  (アップロードされたファイル名が「___-__02.jpg」となってしまう)
    

9.file_columnプラグインプログラムの修正
日本語のファイル名も使用できるようにするために、ふたたびfile_columnを修正します。

/vender/plugins/file_column/lib/file_column.rb

require 'fileutils'
require 'tempfile'
require 'magick_file_column'

module FileColumn # :nodoc:



def self.sanitize_filename(filename)

filename = File.basename(filename.gsub("\\", "/")) # work-around for IE
filename.gsub!(/[^\w\.\-\+_]/,"_")
filename = "_#{filename}" if filename =~ /^\.+$/
filename = "unnamed" if filename.size == 0
filename

end

end


10.動作確認
   これで日本語のファイル名も扱うことができます。
  (アップロードするファイル名が「顔写真-画像03.jpg」の場合)
    

  (アップロードされたファイル名も「顔写真-画像03.jpg」となる)
    



11.画像の表示
   さらに画像については表示するようにします。
   

/app/views/show.html.erb

<p>
 <b><%= t('label.Namae') %>:</b>
 <%=h @address.namae %>
</p>


<p>
 <b><%= t('label.Yubin') %>:</b>
 <%=h @address.yubin %>
</p>


<p>
 <b><%= t('label.Jusho') %>:</b>
 <%=h @address.jusho %>
</p>


<p>
 <b><%= t('label.Denwa') %>:</b>
 <%=h @address.denwa %>
</p>


<p>
 <b><%= t('label.Image') %>:</b>
 <%= image_tag url_for_file_column(@address, :image) %>
</p>



<%= link_to t('link.Edit'), edit_address_path(@address) %> |
<%= link_to t('link.Back'), addresses_path %>

  (実際に画像を表示した場合)
    


12.画像の拡大縮小
   表示される画像の大きさを制御しましょう。

/app/views/show.html.erb

<p>
 <b><%= t('label.Namae') %>:</b>
 <%=h @address.namae %>
</p>


<p>
 <b><%= t('label.Yubin') %>:</b>
 <%=h @address.yubin %>
</p>


<p>
 <b><%= t('label.Jusho') %>:</b>
 <%=h @address.jusho %>
</p>


<p>
 <b><%= t('label.Denwa') %>:</b>
 <%=h @address.denwa %>
</p>


<p>
 <b><%= t('label.Image') %>:</b>
 <%= image_tag url_for_file_column(@address, :image), :size=>"50x50" %>
</p>



<%= link_to t('link.Edit'), edit_address_path(@address) %> |
<%= link_to t('link.Back'), addresses_path %>


  なお、ここで:size=>"50x50"を:width=>"50"や:hight=>"50"と書くことができます。
  これにより横幅を揃えたり、高さを揃えたりすることができます。

  (縮小された画像を表示)