Ruby on rails 在更新属性时保存引用的资源(在编辑时创建嵌套资源)

Ruby on rails 在更新属性时保存引用的资源(在编辑时创建嵌套资源),ruby-on-rails,ruby-on-rails-3,activerecord,nested,Ruby On Rails,Ruby On Rails 3,Activerecord,Nested,我有一个类似问题跟踪系统的东西,其中有问题,他们有一些意见 现在在一个页面上,我想给用户一个选项来编辑一些“问题”的内容以及添加评论。编辑和发布是一个标准的东西,比如in/edit,但是我想创建一个注释并验证它是否为空 我已经发现我可以构建一个评论并为其生成一个表单,但是我应该如何同时检查issue属性和comment属性是否有效?因为每次更新之后都应该有一个新的注释,但是如果问题属性无效,我不想创建新的注释。我会首先向您的问题和注释模型添加验证失败?方法来检查问题 其次,您必须从params[

我有一个类似问题跟踪系统的东西,其中有问题,他们有一些意见

现在在一个页面上,我想给用户一个选项来编辑一些“问题”的内容以及添加评论。编辑和发布是一个标准的东西,比如in/edit,但是我想创建一个注释并验证它是否为空


我已经发现我可以构建一个评论并为其生成一个表单,但是我应该如何同时检查issue属性和comment属性是否有效?因为每次更新之后都应该有一个新的注释,但是如果问题属性无效,我不想创建新的注释。

我会首先向您的
问题
注释
模型添加
验证失败?
方法来检查问题

其次,您必须从
params[]
手动加载
@issue
表单数据,并在保存之前对其进行验证(不能使用
更新属性(params[:issue])
)创建新的
注释
并通过
params[]
加载它。然后,您可以在两个模型上测试验证,如果其中一个失败,则返回到
edit
操作

如果两者都通过,您可以正常保存
@issue
,然后保存
@comment

def update
  @issue = Issue.find(params[:id])
  # manually transfer form data to the issue model
  @issue.title = params[:issue][:title]
  @issue.body = params[:issue][:body]
  #...

  @comment = @issue.comments.new(params[:comment])

  # validate both @issue and @comment
  if @issue.fails_validation? || @comment.fails_validation?
    flash[:error] =  "Your edits or your comment did not pass validation."
    render :action => "edit", 
  end

  # validation passed, save @issue then @comment
  respond_to do |format|
    if @issue.save
      @comment.save
      format.html { redirect_to @issue, notice: 'Issue successfully updated. Comment created' }
      format.json { head :ok }
    else
      format.html { render action: "edit" }
      format.json { render json: @issue.errors, status: :unprocessable_entity }
    end
  end
end

不是最优雅的解决方案,但它应该可以工作。

您可以在各自的类中验证注释模型和问题模型。 我不清楚您是否使用问题中的“accepts_nested_attributes_for”作为注释。如果是,则如果问题无效,则标准IssueController#update不会保存记录,因此也不会创建注释记录

以下是标准的IssueController更新:

class IssueController
为什么说更新属性不会检查验证错误?它在内部调用save来运行验证。这是一个逻辑流问题,而不是update_attributes()功能问题。如果使用update_attributes(),它将从params[]加载模型并保存它(您是正确的)。但是,在这个问题中,您希望从params[]加载模型,但在对通过params[]传入的数据执行验证之前不保存它。这就是为什么我评论说您不能使用update_attributes(),因为它将在您验证param[]更新之前保存您的模型。@salil-我假设他没有使用嵌套属性,因此需要单独的验证过程。如果他使用嵌套属性,那么您的答案显然是首选方法。问题的措辞是“…同时检查问题属性和注释属性是否有效…”使用传统的Rails模型验证无法满足此要求。update_attributes将在验证第二个模型之前保存第一个模型的更新(除非您正在执行嵌套属性,正如您所指出的)。这就是为什么我指出,他需要编写独立于保存功能的自己的验证例程。您是对的。对于他想要做的事情,如果他只使用嵌套的_属性并一次性验证整个@issue对象,就会容易得多。
class IssueController < ApplicationController

  def update
    @issue = Issue.find(params[:id])
    if @issue.update_attributes(params[:issue])
      redirect_to issues_path, notice: 'issue updated'
    else
      render action: 'edit'
    end
  end