我想做两个简单的自定义验证:
if project.end < project.start, raise an exception.
if project.start, set project.active to equal true
我的代码(可能非常不正常)不起作用:
class Project < ActiveRecord::Base
before_save :check_data # now changed to before_validation
def check_data
if end < start
errors.add(:base, 'Project end date must be after project start date.')
end
if start
active = true
end
end
错误正在添加,但是但是我没有被带回错的消息 - 在用户方面似乎一切都很好。
此外,数据库中的字段active
没有变化。
控制器代码:
@project = Project.find(params[:id])
if @project.update_attributes(params[:project])
redirect_to home_url
else
flash[:error] = "There was an error saving your form."
redirect_to edit_project_url
end
我将上面的代码更改为before_validation,但是active
字段仍未在数据库中进行更改。如何使上述模型代码有效?
self.active
。答案 0 :(得分:5)
要使错误条件正常工作,请使用before_validation
代替before_save
。
成功条件不正常,因为active
赋值有局部变量,而不是模型属性。您必须在此处明确使用“自我”,例如self.active = true
。
答案 1 :(得分:4)
如果您正在验证,则应该使用before_validation
。原因是,如果您有其他验证失败,您的check_data将永远不会运行,因此用户永远不会看到这些错误。这可能导致他们输入项目数据,获得验证错误,修复该错误,然后check_data运行并告诉他们另一个验证错误的情况。如果您使用before_validation,那么他们将立即看到所有错误。
我不知道这是否会实际修复您遇到的主动不保存的错误,但您注意到错误未显示在表单中的错误是由于您使用了redirect_to edit_project_url
- 您应该使用
render :edit
来自您的更新操作和
render :new
来自您的创建操作。 errors
实际上是@project
对象的一部分,因此当您将(而不是渲染)重定向到新操作时,会创建一个新对象。重定向到编辑页面时,将从数据库加载现有对象。这就是你的错误数组正在消失的方式。如果渲染而不是重定向,则您的错误将保留在对象上并显示在视图中(假设您已正确设置了所有内容)。
希望有所帮助,祝你好运找出活跃的国家问题!