という話をメモしておきます。
[環境]
CentOS6.2
Rails 3.2.2
Ruby 1.9.3-p125
CentOS6.2
Rails 3.2.2
Ruby 1.9.3-p125
(1)テスト対象のModel
前回に引き続き簡易blog(食べたもの記録)アプリの記事本体部分を想定。
Modelの名前はDiningとします。
app_root/db/migrate/[date]_dinings.rbより抜粋すると
class CreateDinings < ActiveRecord::Migration def change create_table :dinings do |t| t.date :date #日付 t.string :time #「朝」「昼」「夜」が入る t.string :menu #「食べたもの」 t.integer :price #「お値段」 t.string :shop #「店」 t.string :place #「店の場所」 t.integer :evaluetion #1~5の5段階評価 t.string :impression #感想 t.string :ctype # 写真が指定されている時写真のcontent_type t.binary :photo #写真 t.timestamps end end end写真データを直接DBに格納するモデルです。 ここでは ・画像ファイルのcontent-typeが画像で無い時バリデーションエラーになること をテストしていきます。
(2)テスト
app_root/spec/model/dining_spec.rbより抜粋describe "写真(photo)" do it "content-typeが画像の時バリデーションエラーが発生しないこと" do @dining.data = Rack::Test::UploadedFile.new(Rails.root.join("test/fixtures/test.jpg"), "image/jpeg") @dining.should be_valid end it "content-typeが画像以外の時バリデーションエラーが発生すること" do @dining.data = Rack::Test::UploadedFile.new(Rails.root.join("test/fixtures/test.jpg"), "image/text") @dining.should be_valid end end
Rack::Test::UploadedFile.new()が仮想アップロードファイルをテストするためのメソッドで 第1引数にテスト画像,第2引数にcontent-typeを設定します。
(3)バリデーションの実装
テストがでけたので。 app_root/app/model/dining.rbにバリデーションを実装していきます。#coding:utf-8 class Dining < ActiveRecord::Base #中略 validate :file_invalid? #写真のバリデート def data=(data) self.ctype = data.content_type self.photo = data.read end def file_invalid? if !self.photo.nil? then #写真が指定されてる時 ps = ['image/jpeg', 'image/gif', 'image/png'] errors.add(:photo, 'は画像ファイルではありません') if !ps.include?(self.ctype) end end endテスト/実装コードにもある通りフォーム側で画像をアップロードする時に、 直接model上のカラムである:imageではなく、:dataという仮のパラメータにセットして アップロード時に:ctypeと:imageを:dataから抽出してセットしている点が注意が必要。 form側では
という記述でアップロードフォームを実現しています。<%= f.label :data, "写真" %> <%= f.file_field :data %>