Ruby关联模型复制报错:Formulaire与Question复制时出现NoMethodError
解决复制关联模型时的NoMethodError问题
我来帮你搞定这个报错问题!首先咱们先定位错误根源:你代码里的template2 = Question.where(formulaire_id: 47)返回的是ActiveRecord::Relation对象集合(也就是一组Question实例),而不是单个模型实例。dup和save都是单个ActiveRecord实例才有的方法,直接给集合调用这两个方法,自然会抛出undefined method 'save'的错误。而且硬编码formulaire_id:47也很不灵活,应该关联到你刚复制出来的新@formulaire。
修正后的duplicate方法代码
def duplicate # 开启事务,保证复制操作的原子性(要么全成功,要么全回滚) Formulaire.transaction do template = Formulaire.find(params[:id]) @formulaire = template.dup @formulaire.save! # 用save!替代save,失败时会抛出异常,方便排查问题 # 遍历原模板的所有问题,逐个复制并关联到新表单 template.questions.each do |original_question| new_question = original_question.dup new_question.formulaire_id = @formulaire.id # 关键:把新问题关联到新复制的表单 new_question.save! end end redirect_to @formulaire, notice: "Formulaire dupliqué" rescue ActiveRecord::RecordInvalid => e # 捕获验证失败的异常,给用户友好提示 redirect_to template, alert: "复制失败:#{e.message}" end
关键优化点说明:
- 抛弃硬编码ID:直接用
template.questions遍历原表单的所有关联问题,不管复制哪个表单都能正常工作,不用手动改ID。 - 绑定关联关系:复制出来的新问题必须设置
formulaire_id为新表单的ID,否则会丢失关联,变成无归属的问题。 - 事务保护:用
Formulaire.transaction包裹所有操作,避免出现“表单复制成功但问题复制失败”的无效数据。 - 用
save!排查问题:save!在模型验证不通过时会抛出明确的异常(比如Question的nom为空),比只返回false的save更容易定位问题。
其实你之前注释掉的那段遍历代码思路是对的,只是少了绑定新表单的步骤,调整一下就能正常运行啦。
内容的提问来源于stack exchange,提问作者user9007028
相关产品推荐
相关产品推荐

