1 Active Model 簡介
Active Model 是一個函式庫,由許多用來與 Action Pack 互動的模組組成。以下簡單介紹幾個 Active Model 的模組。
1.1 AttributeMethods
用來給方法加上前綴或後綴。
class Person
include ActiveModel::AttributeMethods
attribute_method_prefix 'reset_'
attribute_method_suffix '_highest?'
define_attribute_methods 'age'
attr_accessor :age
private
def reset_attribute(attribute)
send("#{attribute}=", 0)
end
def attribute_highest?(attribute)
send(attribute) > 100
end
end
person = Person.new
person.age = 110
person.age_highest? # true
person.reset_age # 0
person.age_highest? # false
1.2 回呼
Active Record 風格的回呼。讓我們可以在運行期定義回呼。定義回呼後便有 before_*、after_* 與 around_* 方法可用。
class Person
extend ActiveModel::Callbacks
define_model_callbacks :update
before_update :reset_me
def update
run_callbacks(:update) do
# This method is called when update is called on an object.
end
end
def reset_me
# This method is called when update is called on an object as a before_update callback is defined.
end
end
1.3 Conversion
如果一個類別有定義 persisted? 與 id 方法,則你可引入 Conversion 模組,並對此類別的物件呼叫 Rails 的 conversion 方法(to_model、to_key、to_param)。
class Person
include ActiveModel::Conversion
def persisted?
false
end
def id
nil
end
end
person = Person.new
person.to_model == person # => true
person.to_key # => nil
person.to_param # => nil
1.4 Dirty
物件有一個或多個改動,卻未儲存,則稱物件變“dirty”了。這讓我們可以檢查物件是否有變動。以下是 Person 類別,有 first_name 與 last_name 這兩個屬性:
require 'active_model'
class Person
include ActiveModel::Dirty
define_attribute_methods :first_name, :last_name
def first_name
@first_name
end
def first_name=(value)
first_name_will_change!
@first_name = value
end
def last_name
@last_name
end
def last_name=(value)
last_name_will_change!
@last_name = value
end
def save
# do save work...
changes_applied
end
end
1.4.1 查詢物件修改過屬性的列表
person = Person.new
person.changed? # => false
person.first_name = "First Name"
person.first_name # => "First Name"
# returns if any attribute has changed.
person.changed? # => true
# returns a list of attributes that have changed before saving.
person.changed # => ["first_name"]
# returns a hash of the attributes that have changed with their original values.
person.changed_attributes # => {"first_name"=>nil}
# returns a hash of changes, with the attribute names as the keys, and the values will be an array of the old and new value for that field.
person.changes # => {"first_name"=>[nil, "First Name"]}
1.4.2 Attribute based accessor methods
檢查 first_name 這個屬性是否有變動,first_name_changed?:
Track whether the particular attribute has been changed or not.
# attr_name_changed? person.first_name # => "First Name" person.first_name_changed? # => true
檢查屬性上一次的數值: Track what was the previous value of the attribute.
# attr_name_was accessor person.first_name_was # => "First Name"
檢查屬性上次與當前的值,有變化回傳 Array,沒變化回傳 nil:
# attr_name_change person.first_name_change # => [nil, "First Name"] person.last_name_change # => nil
1.5 驗證
給類別加入 Active Record 風格的驗證功能:
class Person
include ActiveModel::Validations
attr_accessor :name, :email, :token
validates :name, presence: true
validates_format_of :email, with: /\A([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})\z/i
validates! :token, presence: true
end
person = Person.new(token: "2b1f325")
person.valid? # => false
person.name = 'vishnu'
person.email = 'me'
person.valid? # => false
person.email = '[email protected]'
person.valid? # => true
person.token = nil
person.valid? # => raises ActiveModel::StrictValidationFailed
1.6 ActiveModel::Naming
Naming 模組加入幾個幫助管理命名和路由的模組。這個模組定義了 model_name 類別方法,這個方法用 ActiveSupport::Inflector 定義了許多存取器(accessor)方法。
class Person extend ActiveModel::Naming end Person.model_name.name # => "Person" Person.model_name.singular # => "person" Person.model_name.plural # => "people" Person.model_name.element # => "person" Person.model_name.human # => "Person" Person.model_name.collection # => "people" Person.model_name.param_key # => "person" Person.model_name.i18n_key # => :person Person.model_name.route_key # => "people" Person.model_name.singular_route_key # => "person"
反饋
歡迎幫忙改善指南的品質。
如發現任何錯誤之處,歡迎修正。開始貢獻前,可以先閱讀貢獻指南:文件。
翻譯如有錯誤,深感抱歉,歡迎 Fork 修正,或至此處回報。
文章可能有未完成或過時的內容。請先檢查 Edge Guides 來確定問題在 master 是否已經修掉了。再上 master 補上缺少的文件。內容參考 Ruby on Rails 指南準則來了解行文風格。
最後,任何關於 Ruby on Rails 文件的討論,歡迎至 rubyonrails-docs 郵件論壇。