【问题标题】:Rails exception handling when submitting a formRails 提交表单时的异常处理
【发布时间】:2011-03-18 16:53:55
【问题描述】:

我想知道在表单提交期间保存模型时发生的异常处理的最佳方法是什么。我目前正在使用这样的代码 sn-p。

class Mycontroller def edit @customer = Customer.new @permissions = Hash.new @permissions['save'] = true @permissions['clear'] = true @permissions['some_other'] = false end def submit_handler @customer = Customer.find(params[:id]) @customer.update_attributes!(params[:customer]) redirect_to(:controller => 'XXXXXX', :action => 'edit', :id=>params[:id]) rescue ActiveRecord::RecordInvalid => e render :action => :edit, :id => params[:id] end end

这是我的视图,名为 edit.html.erb

<% form_for :customer, :url => {:action =>"submit_handler", :id=>id} do |acc|%>
<%= render :partial => 'fields', :locals => { :acc => acc } %>  
<table align="center">
<tr align="center">
<% if @permissions['some_other'] == true %>
<td id='some_other' align="center"><%= submit_tag "Some other" %></td>
<%end%>
<% if @permissions['save'] == true %>
<td id='save'align="center"><%= submit_tag "Save" %></td>
<%end%>
<% if @permissions['clear'] == true %>
<td id='clear' align="center"><%= button_to "Clear", :action => :clear %></td>
<%end%>
</table>
<%end%>

我对上面代码sn-p的理解是render方法在调用模板'edit'之前不会调用动作'edit'。我将一个对象(@permissions)从“编辑”的操作处理程序传递给模板“编辑”。当我重定向到编辑操作而不是在渲染期间,事情工作正常,因为我从控制器传递到模板的对象(@permissions)在渲染期间不可用。我做的事情对吗?这是 Rails 处理异常的方式吗?如果是这样,当我调用渲染方法时,如何将对象(@permissions)传递给模板?任何指针将不胜感激。

谢谢。

【问题讨论】:

  • 到底发生了什么错误?如果您在edit 函数和视图(表单)中命名对象@customer,则不会出现错误,因为@customer 对象也是在submit_handler 操作中创建的..
  • @rubyprince:我已经编辑了代码以使其更清晰。让我知道这是否有助于理解我的问题。感谢您的努力。

标签: ruby-on-rails exception-handling render


【解决方案1】:

这段代码是多余的:

@customer.update_attributes!(params[:customer])
@customer.save!

update_attributes 也将保存,因此对save! 的调用不会执行任何操作。在 Rails 中更惯用的方法是这样的:

def submit_handler
  @customer = Customer.find(params[:id])

  # Update your attributes
  if @customer.update_attributes(params[:customer])
    # Redirect on success
    redirect_to(:controller => 'XXXXXX', :action => 'edit', :id=>params[:id])
  else
    # Render the action template -- no need to reset the ID here
   render :action => :edit
  end
end

当保存无法完成时,是否有某些原因需要引发异常?

【讨论】:

  • 很抱歉我在添加@customer.save 时犯了错误!它实际上不在原始代码中。实际的代码要复杂得多。该表单包含多个模型,所有模型都保存在一个事务中。我试图给出我的问题的简化版本。使用控制器中的事务逻辑,我想我唯一的方法是引发异常。有没有办法将@permission 对象传递给模板??
  • 如果您想将@permissions 对象传递回else 条件下的视图,您需要重建它(因为它不再作为控制器上的实例变量存在) .有几种方法可以做到这一点。就个人而言,除非这些字段需要一些额外的安全性,否则我会将它们存储为hidden_field_tags,然后重置else 块中的值。否则,您可以将它们藏在 session 中。
  • 另外,如果您要保存多个对象,您可能需要查看一些涵盖该主题的 Railscast:railscasts.com/episodes/196-nested-model-form-part-1
【解决方案2】:

您正在调用 save!update_attributes! 方法,如果任何验证失败,这些方法将引发 ActiveRecord 异常。此外,您的代码在执行update_attributes!save! 时也是多余的。你最好用传统的脚手架方式编写这个方法。

class Mycontroller
  def submit_handler
    @customer = Customer.find(params[:id])        
    if @customer.update_attributes(params[:customer])
      redirect_to(:controller => 'XXXXXX', :action => 'edit', :id=>params[:id])
    else
      get_edit_permissions()    
      render :action => :edit
    end
  end

  def edit
    @customer = Customer.find(params[:id])
    get_edit_permissions()
  end

  def get_edit_permissions
    @permissions = Hash.new
    @permissions['save'] = true
    @permissions['clear'] = true
    @permissions['some_other'] = false
    # @permissions = {'save' => true, 'clear' => true, 'some_other' => false}
  end
end

实际上,您可以通过在 routes.rb(Rails 2.3.5 中为map.resources :customer)中将customer 声明为资源并将submit_handler 方法命名为create 来使您的生活更轻松,因为这将遵循restful Rails 提倡的路由。

【讨论】:

  • 很抱歉我在添加@customer.save 时犯了错误!它实际上不在原始代码中。实际的代码要复杂得多。该表单包含多个模型,所有模型都保存在一个事务中。我试图给出我的问题的简化版本。使用控制器中的事务逻辑,我想我唯一的方法是引发异常。有没有办法将@permission 对象传递给模板??
  • 正如@jerhinesmith 所说,您还必须在submit_handler 操作中重新创建edit 重建中使用的变量。您可以将其设为单独的方法并在editsubmit_handler 中调用它。我已经更新了我的帖子。
【解决方案3】:

在此处查看有关如何挽救控制器操作中引发的异常的信息: http://apidock.com/rails/v2.3.8/ActiveSupport/Rescuable/ClassMethods/rescue_from

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-17
    • 2016-11-10
    • 1970-01-01
    相关资源
    最近更新 更多