プログラマとプロマネのあいだ

プログラマもやるし、プロマネもやるし、たまに似非アーキとか営業っぽいこともやる

「RailsによるアジャイルWebアプリケーション開発」19章読み中

集中力が続かないので、またも途中でブログに書いてしまう。

19章は、Active Recordその3
検証その他に関するお話。

データベースに保存する前にモデルを検証する

valid?を呼ぶ。

サンプルコード。

require 'rubygems'
require 'activerecord'

ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "../db/development.sqlite3")

class Order < ActiveRecord::Base
  # 住所は必須
  validates_presence_of :address
end

# save(create or update)する前に検証するには、valid?を呼ぶ
order1 = Order.new(
       :name => 'taka_2',
       :address => 'kanagawa',
       :email => 'hoge@fuga.com',
       :payment_type_id => 2
)

puts order1.valid?

order2 = Order.new(
       :name => 'taka_2',
       :address => '',
       :email => 'hoge@fuga.com',
       :payment_type_id => 2
)

puts order2.valid?

結果はこう。

true
false

新規作成(insert)、または、更新(update)のときのみ検証したい

それぞれ、validate_on_create、validate_on_updateを実装する。
なお、どちらの場合も検証したい場合は、validateを実装する。

サンプル。

require 'rubygems'
require 'activerecord'

ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "../db/development.sqlite3")

class Order < ActiveRecord::Base
  def validate_on_create
      # Insert時には、名前必須
      if name.blank?
      	 errors.add(:name, "が入力されていません。")
      end
  end

  def validate_on_update
      # Update時には、住所必須
      if address.blank?
      	 errors.add(:address, "が入力されていません。")
      end
  end
end

# 名前なしでcreateしてみる
order1 = Order.new(
       :name => '',
       :address => '',
       :email => 'hoge@fuga.com',
       :payment_type_id => 1
)

begin
  order1.save!
  puts "order1 saved."
rescue
  puts order1.errors
end

# 名前を入れてcreateしてみる
order1.name = 'taka_2'

begin
  order1.save!
  puts "order1 saved."
rescue
  puts order1.errors
end

# 住所なしでupdateしてみる
begin
  order1.save!
  puts "order1 saved."
rescue
  puts order1.errors
end

# 住所を入れてupdateしてみる
order1.address = 'kanagawa'

begin
  order1.save!
  puts "order1 saved."
rescue
  puts order1.errors
end

# 後始末
Order.delete(order1.id)

結果はこう。

#<ActiveRecord::Errors:0x30246b4>
order1 saved.
#<ActiveRecord::Errors:0x30246b4>
order1 saved.

デフォルトの検証エラーメッセージを変える

まず、デフォルトの検証エラーメッセージを表示するコード。

require 'rubygems'
require 'activerecord'
require 'pp'

pp ActiveRecord::Errors.default_error_messages

結果はこう。

{:not_a_number=>"is not a number",
 :odd=>"must be odd",
 :blank=>"can't be blank",
 :greater_than=>"must be greater than %d",
 :inclusion=>"is not included in the list",
 :even=>"must be even",
 :too_long=>"is too long (maximum is %d characters)",
 :greater_than_or_equal_to=>"must be greater than or equal to %d",
 :exclusion=>"is reserved",
 :too_short=>"is too short (minimum is %d characters)",
 :empty=>"can't be empty",
 :equal_to=>"must be equal to %d",
 :invalid=>"is invalid",
 :wrong_length=>"is the wrong length (should be %d characters)",
 :less_than=>"must be less than %d",
 :confirmation=>"doesn't match confirmation",
 :taken=>"has already been taken",
 :less_than_or_equal_to=>"must be less than or equal to %d",
 :accepted=>"must be accepted"}

試しにエラーメッセージを差し替えてみる。

require 'rubygems'
require 'activerecord'

# エラーメッセージを差し替え
ActiveRecord::Errors.default_error_messages[:blank] = 'は空にできません。'

ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "../db/development.sqlite3")

class Order < ActiveRecord::Base
  validates_presence_of :name
end

# 名前なしでcreateしてみる
order1 = Order.new(
       :name => '',
       :address => 'kanagawa',
       :email => 'hoge@fuga.com',
       :payment_type_id => 1
)

begin
  order1.save!
  puts "order1 saved."
rescue
  puts order1.errors[:name]
end

# エラーメッセージを差し替え(ここではうまくいかない!)
ActiveRecord::Errors.default_error_messages[:blank] = 'は空にできません。。'

begin
  order1.save!
  puts "order1 saved."
rescue
  puts order1.errors[:name]
end

結果はこう。

は空にできません。
は空にできません。

やってみて分かったのだが、establish_connection以降にメッセージを差し替えてもダメらしい。本書中にも、environment.rbに書き込むよう書いてあります。