Hatena::ブログ(Diary)

challenge Ruby on Rails

2009-09-10

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

    f:id:challengeRoR:20090910155830j:image:w400


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が発生します。

    f:id:challengeRoR:20090910165626j:image:w400

これの対処法は、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」の場合)

    f:id:challengeRoR:20090910170912j:image:w400

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

    f:id:challengeRoR:20090910171000j:image:w400

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」の場合)

    f:id:challengeRoR:20090910172248j:image:w400

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

    f:id:challengeRoR:20090910172315j:image:w400


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 %>


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

    f:id:challengeRoR:20090911091317j:image:w400


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"と書くことができます。

  これにより横幅を揃えたり、高さを揃えたりすることができます。


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

    f:id:challengeRoR:20090911113725j:image:w400


スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/challengeRoR/20090910/1252564565