[問題] Rails Guide 的範例程式碼問題
節錄自:http://guides.rubyonrails.org/active_record_validations_callbacks.html#custom-validators
問題一:
class MyValidator < ActiveModel::Validator
def validate(record)
unless record.name.starts_with? 'X'
record.errors[:name] << 'Need a name starting with X please!'
end
end
end
class Person
include ActiveModel::Validations
validates_with MyValidator
end
這段程式碼中,為什麼需要 include ActiveModel::Validations?
問題二:
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
record.errors[attribute] << (options[:message] || "is not an email")
end
end
end
class Person < ActiveRecord::Base
validates :email, :presence => true, :email => true
end
為什麼這回又不用 include 了?
---------------------------------------------
總覺得這兩段程式碼看得我好亂啊……而且文中也沒有交待清楚,是否有人也有同樣的疑惑?
這是來自 PTT 的回覆:
→ m※※※6:雖然跟ActiveRecord不熟,不過應該是因為沒有繼承吧? 01/23 00:46
→ a※※※y:因為問題一的Person只是一個一般的Ruby Class 01/23 04:34
→ a※※※y:它不知道validates_with是在哪邊定義的 01/23 04:34
→ a※※※y:所以需要特別標示來源 :) 01/23 04:35
感謝樓上前輩回答=)
話說我另外還找到一篇,我想對一些人也許有幫助:
http://tinyurl.com/4x7jbd5
可是我還有一個問題是,為何第二段的用法只需要寫:
validates :email, :presence => true, :email => true
就會呼叫到 EmailValidator 的 validate_each?
意思是如果我有其他 attribute ,只要定義一個 class 名叫 AttrNameValidator 就可以了嗎?
1. class Person 只是一個 class ,並沒有繼承自 ActiveRecord::Base。所以他必須手動 include ActiveModel::Validations。
2. class Person 這時候繼承自 ActiveRecord::Base,已經從繼承內獲得了 include ActiveModel::Validations 的效果。
#2樓 @xdite 敬受教哉,我已經知道了我第一個問題的答案。
此外我對我其他的問題來自問自答了:
我剛剛看了一下 PresenceValidator 的繼承關係:
ActiveModel::Validations::PresenceValidator < ActiveModel::EachValidator
所以我想當我們寫出如下的程式碼時:
validates :attr_name, :presence => true
Rails 就會去找有沒有 PresenceValidator。
也就是當我寫
validates :attr_name, :abc => ture
Rails 就會去找有沒有 AbcValidator
但還不曉得若找不到會發生什麼事情,所以等等就實驗看看。確實擲出了如下的異常:
ArgumentError: Unknown validator: 'AbcValidator'