ActiveRecord验证和回调3

阅读更多

5 有条件的验证
有时要满意一些条件才进行数据验证,这就可以使用:if和:unless选项,并指定一个符号,字符串或者Proc对象给选项。

5.1 使用符号的:if和:unless
给:if和:unless选项,指定一个符号,在验证发生之前就会调用这个方法。
class Order < ActiveRecord::Base
validates_presence_of :card_number, :if => :paid_with_card?

def paid_with_card?
    payment_type == "crad"
end
end

5.2 使用字符串的:if和:unless
可以指定一个字符串给:if和:unless选项,字符串是Ruby代码,通过eval执行。
class Person < ActiveRecord::Base
validates_presence_of :surname, :if => "name.nil?"
end

5.3 使用过Proc对象
给:if和:unless指定一个Proc对象,就可以写一个内联条件,而不是单独的方法。此选项最合适在一行。
class Account < ActiveRecord::Base
validates_confirmation_of :password,
    :unless => Proc.new{|a| a.password.black?}
end


6 创建自定义验证方法
当内建的验证辅助方法不能满足需要时,就可以自己编写验证方法。

在模型中创建验证方法,当验证无效时,错误信息会添加到errors集合中。必须用验证方法的符号名字给注册validate, validate_on_create或者validate_on_update注册。

class Invoice < ActiveRecord::Base
validate :expiration_date_cannot_be_in_the_past, :discount_cannot_be_greater_than_total_vlaue

def expiration_date_cannot_be_in_the_past
    errors.add(:expiration_date, "can't be in the past") if
      !expiration_date.blank? and expiration_date < Date.today 
end

def discount_cannot_be_greater_than_total_value
    errors.add(:discount, "can't be greater than total value") if
      discount > total_value
end
end


甚至还可以创建自己的验证辅助方法,在其它模型中使用。例如:
ActiveRecord::Base.class_eval do
def self.validates_as_radio(attr_name, n, options={})
    validates_inclusion_of attr_name, {:in => 1.. n}.merge(options)
end
end
例子中是重新把ActiveRecord::Base打开,并定义了一个类方法。上面的代码可以放在config/initializers中。
class Movie < ActiveRecord::Base
validates_as_radio :rating, 5
end

7 工作与验证错误
Rails为验证对象的有效性提供了一些方法与错误的集合。
下面列出来常用的使用方法:

7.1 errors.add_to_base
该方法给对象状态增加错误信息,并看作是一个整体。当要描述对象是无效时可以使用这个方法,不用去管属性的值。方法参数接受一个字符串。
class Person < ActiveRecord::Base
def a_method_used_for_validation_purposes
    errors.add_to_base("This person is invalid because ...")
end
end

7.2 errors.add
该方法让你手动添加与特定属性相关的信息,可以使用full_messages方法显示信息。在特定信息的前面加上首字母大写的名称。
class Person < ActiveRecord::Base
def a_method_used_for_validation_purposes
    errors.add(:name, "cannot contain the characters !@#%*()_-+=") 
end
end
person = Person.create(:name => "!@#")
person.errors.on(:name)
# => "cannot contain the characters !@#%*()_-+="

person.errors.full_message
# => ["Name cannot contain the characters !@#%*()_-+="]

7.3 errors.on
当检测特定属性的错误信息时,就可以使用这个方法。根据属性错误集合的状态返回不同的对象。如果没有错误就返回nil。当有两个或者更多的错误信息时,就返回数组。
class Person < ActiveRecord::Base
validates_presence_of :name
validates_length_of :name, :minimum => 3
end

person = Person.new(:name => "John Doe")
person.valid? #=> true
person.errors.on(:name) # => nil

person = Person.new(:name => "JD")
person.valid? # => false
person.errors.on(:name)
# => "is too short (minimum is 3 characters)"

person = Person.new
person.valid? # => false
# => ["can't be blank", "is too short (minimum is 3 characters)"]

7.4 errors.clear
当想要清除errors中的信息时,就可以使用这个方法。当然,无效的对象依然是无效的,只是errors集合被清空了,当再次调用valid?或者尝试保存对象到数据库时,仍然要进行验证。如果验证失败,错误信息就保存在errors集合中。
class Person < ActiveRecord::Base
validates_presence_of :name
validates_length_of :name, :minimum => 3

7.5 errors.size
返回对象的错误信息的总数。
class Person < ActiveRecord::Base
validates_presence_of :name
validates_length_of :name, :minimum => 3
validates_presence :email
end

person = Person.new
person.valid? # => false
person.errors.size # => 3

person = Person.new(:name => "Andrea", :email => "[email protected]")
person.valid? # => true
person.errors.size # => 0


8 在视图中显示验证错误
Rails提供了一些内建的辅助方法用来在视图中显示错误信息。

8.1 error_messags and error_messages_for
当用form_for辅助方法创建一个表单时,就可以使用error_messages方法在表单中为当前的模型对象渲染所有验证的错误信息。

class Product < ActiveRecord::Base
validates_presence_of :description, :value
validates_numericality_of :value, :allow_nil => true
end


<% form_for(@product) do |f| %>
<%= f.error_messages %>


    <%= f.label :description %>

    <%= f.text_field :value %>



    <%= f.label :value %>
    <%= f.text_field :value %>



    <%= f.submit "Create" %>


<% end %>


也可以在视图中使用error_messages_for辅助方法显示验证错误信息。

<%= error_messages_for :product %>

这两个方法都接受自定义信息的头部和信息提示。
<%= f.error_messages :header_message => "Invalid product!", :message => "You'll need to fix the following fields:", :header_tag => :h3 %>

8.2 自定义错误信息的CSS风格
错误信息的CSS选择器:
* .fieldWithErrors 表单栏目的标签风格
* #errorExplanation 错误信息div元素的风格
* #errorExplanation h2 错误信息div元素头部的风格
* #errorExplanation p 错误信息div元素中出现在头部下面段落的风格
* errorExplanation ul li 个别错误信息的列表风格

8.3 自定义错误信息的HTML
默认情况下,表单栏目的错误信息是通过CSS中的fieldWithErrors样式附在div元素中的。然而,这是可以改变的。
表单栏目的错误信息通过ActionView::Base.field_error_proc来定义。这是一个一个Proc接受两个参数:
* 一个HTML标记的字符串
* 一个ActionView::Helpers::InstanceTag对象
下面是一个简单的例子:
ActiveView::Base.field_error_proc = Proc.new do |html_tag, instance|
if instance.error_message.kind_of?(Array)
    %(#{html_tag}
     #{instance.error_message.join(',')})

else
    %(#{html_tag}
      #{instance.error_message})   

end
end

你可能感兴趣的:(activerecord,rails,ruby)