3.Validation Options
3.1 :allow_nil
当验证值为nil时:allow_nil选项会跳过验证
ruby
class Coffee < ApplicationRecord
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} is not a valid size" }, allow_nil: true
end
ruby
irb> Coffee.create(size: nil).valid?
=> true
irb> Coffee.create(size: "mega").valid?
=> false
3.1 :allow_blank
如果属性值为blank?,则跳过验证。
ruby
class Topic < ApplicationRecord
validates :title, length: { is: 5 }, allow_blank: true
end
ruby
irb> Topic.create(title: "").valid?
=> true
irb> Topic.create(title: nil).valid?
=> true
irb> Topic.create(title: "short").valid?
=> false # 'short' is not of length 5, so validation fails even though it's not blank
3.3 :message
允许指定验证失败时添加到errors集合中的消息,否则,会使用默认错误消息。
ruby
class Person < ApplicationRecord
# Hard-coded message
validates :name, presence: { message: "must be given please" }
# Message with dynamic attribute value. %{value} will be replaced
# with the actual value of the attribute. %{attribute} and %{model}
# are also available.
validates :age, numericality: { message: "%{value} seems wrong" }
end
Proc :message值有两个参数:正在验证的对象以及包含:model、:attribute 和 :value 键值对的hash。
ruby
class Person < ApplicationRecord
validates :username,
uniqueness: {
# object = person object being validated
# data = { model: "Person", attribute: "Username", value: <username> }
message: ->(object, data) do
"Hey #{object.name}, #{data[:value]} is already taken."
end
}
end
3.4 :on
on 选项允许你指定验证发生时间。默认情况下设置的验证会在save时运行,可以根据需要修改
ruby
class Person < ApplicationRecord
# it will be possible to update email with a duplicated value
validates :email, uniqueness: true, on: :create
# it will be possible to create the record with a non-numerical age
validates :age, numericality: true, on: :update
# the default (validates on both create and update)
validates :name, presence: true
end
4. Conditional Validations
有时,只有在满足给定条件时才能验证对象,这可以通过:if 和 :unless 选项来实现。
ruby
class Order < ApplicationRecord
validates :card_number, presence: true, if: :paid_with_card?
def paid_with_card?
payment_type == "card"
end
end
或者
ruby
class Account < ApplicationRecord
validates :password, confirmation: true,
unless: Proc.new { |a| a.password.blank? }
end
:if 和 :unless也可以同时验证
ruby
class Computer < ApplicationRecord
validates :mouse, presence: true,
if: [Proc.new { |c| c.market.retail? }, :desktop?],
unless: Proc.new { |c| c.trackpad.present? }
end
5 自定义验证
ruby
class Invoice < ApplicationRecord
validate :expiration_date_cannot_be_in_the_past,
:discount_cannot_be_greater_than_total_value
def expiration_date_cannot_be_in_the_past
if expiration_date.present? && expiration_date < Date.today
errors.add(:expiration_date, "can't be in the past")
end
end
def discount_cannot_be_greater_than_total_value
if discount > total_value
errors.add(:discount, "can't be greater than total value")
end
end
end
6. 在视图中显示验证错误
定义模型并添加验证后,当通过网络表单创建model时验证失败,需要显示信息。
由于每个应用程序处理显示验证错误不同,因此Rails不包含任何用于生成这些信息的视图助手,需要自己写。比如:
ruby
<% if @article.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved:</h2>
<ul>
<% @article.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>