如何将验证错误消息传递给另一个控制器中的方法?

时间:2011-04-01 11:43:43

标签: ruby-on-rails

我刚刚开始使用拥有父模型和子模型的rails 3应用程序(父母has_many:children)。

我正在尝试进行设置,以便在创建新父级之后,用户将被带到该父级的显示操作(/ parent / id)。在这个视图中,我包括部分显示任何孩子和表单来创建一个新孩子。创建新子项后,用户将被重定向到将显示新子项的父项的show操作。这一切都按预期工作。

但是,如果我尝试验证新子窗体中的字段,则出现的任何错误消息都不会出现在窗体中(视图中的必要行是正确的 - 从生成的脚手架代码中剪切并粘贴)。有没有办法将孩子的这些错误消息成功传递给父节目动作?

以下是相关代码的片段;

来自我的父控制器:

def show
  @parent = Parent.find(params[:id])
  @child = @parent.children.new

  respond_to do |format|
    format.html # show.html.erb
    format.xml  { render :xml => @admission }
  end
end

来自我的孩子控制器:

def create
  @child = Child.new(params[:parent])

  respond_to do |format|
    if @child.save
      format.html { redirect_to(parent_path(params[:child][:parent_id]), :notice => 'Child was successfully created.') }
               #This works as intended
      format.xml  { render :xml => @child, :status => :created, :location => @child }
    else
      format.html { redirect_to parent_path(params[:child][:patient_id]) }
               #This redirects where I want it to go when validation fails but error messages are lost
      format.xml  { render :xml => @child.errors, :status => :unprocessable_entity }
    end
  end
end

2 个答案:

答案 0 :(得分:11)

好吧,我自己解决了这个问题。感谢Terw的回答。由于缺少重定向,它与提供错误的URL不同。

这只是通过会话哈希传递错误然后将它们添加到父控制器中的子模型的问题。

我正在发布代码,因为我找不到任何其他的例子。也许有一种更简单的方法,但到目前为止这种方法完美无缺。如果有人认为我疯了,请解释一下。

在我的孩子控制器中

def create
  @parent = Parent.find(params[:child][:parent_id])
  @child = @parent.child.build(params[:child])

  respond_to do |format|
    if @child.save
      format.html { redirect_to(parent_path(params[:admission][:parent_id]), :notice => 'Child was successfully created.') }
      format.xml  { render :xml => @child, :status => :created, :location => @child }
    else
      if @child.errors.any?
        session[:child_errors] = @child.errors
      end
      format.html { redirect_to(parent_path(params[:child][:parent_id])) }
      format.xml  { render :xml => @child.errors, :status => :unprocessable_entity }
    end
  end
end

在我的父控制器中

def show
  @parent = Parent.find(params[:id])
  @child = @parent.children.new
  if session[:child_errors]
    session[:child_errors].each {|error, error_message| @child.errors.add error, error_message}
    session.delete :child_errors
  end
  respond_to do |format|
    format.html # show.html.erb
    format.xml  { render :xml => @parent }
  end
end

答案 1 :(得分:1)

如果孩子无效,您只是渲染父母的节目页面会怎样?

def create
  @child = Child.new(params[:parent])

  respond_to do |format|
    if @child.save
      format.html { redirect_to(parent_path(params[:child][:parent_id]), :notice => 'Child was successfully created.') }
               #This works as intended
      format.xml  { render :xml => @child, :status => :created, :location => @child }
    else
      format.html { render :controller => :parent, :action => :show }
               # Display the parent's show page to display the errors
      format.xml  { render :xml => @child.errors, :status => :unprocessable_entity }
    end
  end
end

您可能还希望对crate操作执行类似的操作,以确保父项存在。

@parent = Parent.find(params[:parent][:parent_id])
@child  = @parent.children.build(params[:parent])

然后,您的用户无法创建无效的子级,并且您让父级再次呈现该显示页面。您不应该让用户能够将parent_id设置为selfes。