2a01ae9942939ee2b3954a6727d2bb92

[問題] Rails Guide 的範例程式碼問題

2012-01-23 00:06:21 +0800tonytonyjanRuby on Rails 節點 中發起
最後由 tonytonyjan2012-01-23 13:54:34 +0800回應 , 125次閱讀

節錄自: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 了?
---------------------------------------------
總覺得這兩段程式碼看得我好亂啊……而且文中也沒有交待清楚,是否有人也有同樣的疑惑?

截至 2012-01-23 13:54:34 +0800,共收到 3 條回應
2a01ae9942939ee2b3954a6727d2bb92
tonytonyjan 1樓, 於2012-01-23 13:34:03 +0800回應

這是來自 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 就可以了嗎?

19e786a2a74377ff6e052d87fd8d1fa8
xdite 2樓, 於2012-01-23 13:35:56 +0800回應

1. class Person 只是一個 class ,並沒有繼承自 ActiveRecord::Base。所以他必須手動 include ActiveModel::Validations。

2. class Person 這時候繼承自 ActiveRecord::Base,已經從繼承內獲得了 include ActiveModel::Validations 的效果。

2a01ae9942939ee2b3954a6727d2bb92
tonytonyjan 3樓, 於2012-01-23 13:54:34 +0800回應

#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'

需要 登入 後方可回應,如果你還沒有帳號按這裡 註冊