我在Rails模型中有自定义属性设置器,我在其中添加了验证错误。但是当记录属性被更新时,'true'会返回结果,这对我来说有点混乱。任何提示如何在自定义setter中使用验证错误?
型号:
class Post < ActiveRecord::Base
attr_accessible :body, :hidden_attribute, :title
def hidden_attribute=(value)
self.errors.add(:base, "not accepted")
self.errors.add(:hidden_attribute, "not_accepted")
write_attribute :hidden_attribute, value unless errors.any?
end
end
控制台输出:
1.9.3p194 :024 > Post.last
Post Load (0.2ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT 1
=> #<Post id: 1, title: "asdsaD", body: "la", hidden_attribute: nil, created_at: "2013-11-13 16:55:44", updated_at: "2013-11-13 16:56:06">
1.9.3p194 :025 > Post.last.update_attribute :hidden_attribute, "ka"
Post Load (0.2ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT 1
(0.0ms) begin transaction
(0.0ms) commit transaction
=> true
我为此case.
制作了一个示例应用程序答案 0 :(得分:3)
好的,我理解了这个问题的核心。我不可能做我想要实现的目标,因为一旦验证过程开始,所有验证错误就会被清除。
自定义设置器太早启动:(
答案 1 :(得分:2)
这应该有效。请注意从update_attribute到update_attributes的更改。 update_attribute跳过验证。
Post.last.update_attributes(:hidden_attribute => "ka")
def hidden_attribute=(value)
self.errors.add(:base, "not accepted")
self.errors.add(:hidden_attribute, "not_accepted")
write_attribute :hidden_attribute, value #removed the condition here because save doesn't do anything when the object is not changed
end
当你不写属性时,对象没有变化,save只会返回true。
答案 2 :(得分:0)
在设置器中,您可以将错误消息存储在临时哈希中。然后,您可以创建ActiveRecord验证方法来检查此临时哈希是否为空并将错误消息复制到errors
。
例如,
def age=(age)
raise ArgumentError unless age.is_a? Integer
self.age = age
rescue ArgumentError
@setter_errors ||= {}
@setter_errors[:age] ||= []
@setter_errors[:age] << 'invalid input'
end
这是ActiveRecord验证
validate :validate_no_setter_errors
def validate_no_setter_errors
@setter_errors.each do |attribute, messages|
messages.each do |message|
errors.add(attribute, message)
end
end
@setter_errors.empty?
end
要查看实际效果:
[2] pry(main)> p.age = 'old'
=> "old"
[3] pry(main)> p.save!
(1.0ms) BEGIN
(1.2ms) ROLLBACK
ActiveRecord::RecordInvalid: Validation failed: Age invalid input
[4] pry(main)> p.errors.details
=> {:age=>[{:error=>"invalid input"}]}