1 对象的生命周期
在操作Rails应用程序期间,对象能够create, update和destroyed。ActvieRecord在这些对象的生命周期中提供了钩子,让你能控制应用程序的数据。
验证允许你只把有效的数据写入数据库,callbacks和observers允许你在改变对象状态的前后触发业务逻辑。
2 验证概述
2.1 为什么要使用验证?
验证能够让你只把有效的数据存入数据库。例如,在应用程序中要确保用户提供的email地址和邮寄地址正确。
在把数据存入数据库之前,有几个方法可以验证数据。包括:数据库限制,客户端验证,控制器层验证和模型层验证。
* 使用数据库限制验证数据,构造验证数据库依赖,测试和维护是相当困难的。如果你的数据库被其他应用使用,在数据库层使用限制可能是一个好主意。数据库层验证可以安全的处理一些事(比如验证唯一性),其他方法可能难以实施。
* 客户端验证是有用的,但是单独使用,通常是不可靠的。如果它们使用JavaScript来实现,要是用户关闭掉浏览器的JavaScript解释器,那这些验证就会被忽略掉。然而如果配合其它的一些技巧,客户端验证能够立即给用户提供反馈。
* 控制器层验证的使用是很诱人的。但是通常给测试和维护带来困难。无论何时,让控制器保持小是一个好主意。因为可以让你的应用程序长时间轻松的工作。
* 模型层验证是确保正确的数据存入数据库最好的方法。这些验证不能被用户忽略,并且能很方便的测试和维护。Rails构造模型层验证是相当容易的,它为普通的需求提供了内建的辅助方法,并允许创建你自己的验证方法。
2.2 当验证时发生了什么?
当你创建一个新对象时,对象符合数据库表中的行。例如使用new方法,这些对象并没有马上存到数据库中,要保存到数据库表,还要调用save方法。Active Record使用new_record?实例方法来判断对象是否已经在数据库中了。看一下下面的例子?
class Person < ActiveRecord::Base
end
我们使用script/console来看看它是怎么工作的。
>> p = Person.new(:name => "John Doe")
=> #<Person id: nil, name: "John Doe", created_at: nil, :updated_at: nil>
>> p.new_record?
=> true
>> p.save
=> true
>> p.new_record?
=> false
创建和保存一条新记录将发送一条SQL的INSERT操作给数据库,更新一条记录会发送一条SQL的UPDATE操作给数据库。验证是在这些命令发送到数据库之前运行的。如果验证失败,对象就会被标记为无效的,Active Record将不会执行INSERT或UPDATE操作。这些辅助方法就不会把无效的数据保存到数据库中。当一个对像被创建、保存或更新时,可以选择具体的验证方法。
在数据库中,有很多方法可以改变对象的状态。一些方法会触发验证,一些则不会。如果不小心使用,会把无效的数据写入数据库的。
下列方法会触发验证,如果对象是有效的,便会保存到数据库中。
* create
* create!
* save
* save!
* update
* update_attributes
* update_attributes!
如果记录是无效的,有叹号的方法会抛出一个异常。没有叹号的方法就不会了。save和update_attributes返回false,create和update返回对象。
2.3 跳过验证
下面的方法会跳过验证,不管数据是否有效,都保存到数据库,这些方法要小心使用:
* decrement!
* decrement_counter
* increment!
* increment_counter
* toggle!
* update_all
* update_attribute
* update_counters
注意:如果save方法通过false参数也可以跳过验证的。
* save(false)
2.4 valid?和invalid?
Rails使用valid?方法来验证数据是否有效。如果没有返回错误,会返回true,否则返回false。
class Person < ActiveRecord::Base
validates_presence_of :name
end
Person.create(:name => "John Doe").valid? # => true
Person.create(:name => nil).valid? #=> false
注意使用new时,如果数据无效,将不会产生错误报告。因为当使用new时,验证并没有运行。
class Person < ActiveRecord::Base
validates_presence_of :name
end
>> p = Person.new
=> #<Person id:nil, name:nil>
>> p.erros
=> #<ActiveRecord::Errors..., @errors={}>
>> p.valid?
=> false
>> p.erros
=> #<ActiveRecord::Errors..., @errors={"name"=>["can't be blank"]}>
>> p = Person.create
=> #<Person id: nil, name: nil>
>> p.errors
=> #<ActiveRecord::Errors..., @errors={"name"=>["can't be blank"]}>
>> p.save
=> false
>> p.save!
=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
>> Person.create!
=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
invalid?是valid?的逆操作。如果添加对产生错误,就触发验证并回true。
2.5 errors.invalid?
为了验证对象的属性是否为有效,可有使用erros.invalid?方法。这个方法仅在验证之后运行。因为它仅检查错误,并不触发验证。这和ActiveRecord::Base:invalid?方法是不同的,因为它不检查数据的有效性。它仅检测对象的具体属性是否有错误。
class Person < ActiveRecord::Base
validates_presence_of :name
end
>> Person.new.errors.invalid?(:name) #=> false
>> Person.create.errors.invalid?(:name) #=> true
form:http://hi.baidu.com/haifreeidea/blog/item/d83675c97f7f321f7d3e6f64.html