我确信这是一个常见的问题,但它让我感到难过。
我在'Step'模型上有一个has_many:through表:
has_many :questions, :through => :question_step
该question_step模型在question_id和step_id字段中具有在线验证器:
validates_presence_of :question_id, :step_id
还有一些复选框可以确定哪些问题属于哪个步骤
td= check_box_tag "step[question_ids][]", question.id, @step.question_ids.include?(question.id)
现在,除非我想在 new 步骤中添加问题,否则此功能正常。由于step_id为空,因此question_step模型无法通过验证。如果我删除了question_step模型中的validate_presence_of:step_id参数,它可以正常工作,但我实际上做想要确保step_id在那里。
我确信这是一个常见问题。 ......有什么想法吗?
答案 0 :(得分:1)
您可以检查是否存在问题和步骤对象,而不是验证步骤和问题ID。
validates_presence_of :question, :step
如果这不起作用,您应该考虑删除应用程序级别验证并添加数据库约束,您只需要在迁移中向列添加非空约束:
def up
change_column question_steps, :question_id, :integer, :null => false
change_column question_steps, :step_id, :integer, :null => false
end
答案 1 :(得分:0)
我有一个非常类似的问题。根据{{3}},存在竞争条件。
在我的控制器的创建动作中,我决定创建我的主模型,而没有关联首先使用params排除关联参数。然后使用关联参数更新模型。
所以在你的情况下可能是
def create
@step = Step.create(create_params)
@step.update_attributes(association_params) unless @step.errors.any?
respond_to do |format|
if @step.errors.empty?
format.html #etc..
else
format.html#...etc..
end
end
end
private
def create_params
perm_params = step_params
perm_params.delete :question_ids
perm_params
end
def association_params
params.require(:step).permit(question_ids: [])
end
def step_params
params.require(:step).permit(:name, :other_attributes, question_ids: [])
end
这样您就不必将验证移动到数据库。您仍然可以在更新方法中使用正常的step_params。
params方法可能会被干掉一点,我想知道为什么我需要为了简单地在rails 3中运行的东西而去做所有这些大惊小怪的事情,但它现在适用于我。