如果有办法我可以在Rails中验证单个属性吗?
类似的东西:
ac_object.valid?(attribute_name)
我将把它用于特定模型字段的AJAX验证。将这些验证移动到Javascript会使代码变得非常丑陋。
答案 0 :(得分:37)
您可以在模型中实现自己的方法。像这样的东西
def valid_attribute?(attribute_name)
self.valid?
self.errors[attribute_name].blank?
end
或将其添加到ActiveRecord::Base
答案 1 :(得分:27)
有时会有相当昂贵的验证(例如需要执行数据库查询的验证)。在这种情况下,您需要避免使用valid?
,因为它只是比您需要的更多。
还有另一种解决方案。您可以使用ActiveModel::Validations
的{{3}}方法。
validators_on(* attributes)public
列出用于验证特定内容的所有验证程序 属性。
根据您可以手动验证您想要的属性
e.g。我们只想验证title
的{{1}}:
Post
class Post < ActiveRecord::Base
validates :body, caps_off: true
validates :body, no_swearing: true
validates :body, spell_check_ok: true
validates presence_of: :title
validates length_of: :title, minimum: 30
end
和no_swearing
是非常昂贵的复杂方法。
我们可以做到以下几点:
spell_check_ok
将仅验证title属性而不调用任何其他验证。
def validate_title(a_title)
Post.validators_on(:title).each do |validator|
validator.validate_each(self, :title, a_title)
end
end
我并不完全相信我们应该安全地使用p = Post.new
p.validate_title("")
p.errors.messages
#=> {:title => ["title can not be empty"]
所以我会考虑在validators_on
中以理智的方式处理异常。
答案 2 :(得分:4)
我在@ xlembouras的答案上结束了,并将此方法添加到我的ApplicationRecord
:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def valid_attributes?(*attributes)
attributes.each do |attribute|
self.class.validators_on(attribute).each do |validator|
validator.validate_each(self, attribute, send(attribute))
end
end
errors.none?
end
end
然后我可以在控制器中做这样的事情:
if @post.valid_attributes?(:title, :date)
render :post_preview
else
render :new
end
答案 3 :(得分:0)
基于@coreyward 的回答,我还添加了一个 validate_attributes!
方法:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def valid_attributes?(*attributes)
attributes.each do |attribute|
self.class.validators_on(attribute).each do |validator|
validator.validate_each(self, attribute, send(attribute))
end
end
errors.none?
end
def validate_attributes!(*attributes)
valid_attributes?(*attributes) || raise(ActiveModel::ValidationError.new(self))
end
end