渲染无法在rescue_from ActiveRecord :: Rollback方法中呈现正确的模板

我正在为电子商务网站构建结帐页面,我有一个相当长的事务,它创建了一个新的用户模型和一个新的订单模型。 我将这些模型的创建包装在一个事务中,这样如果一个模型的validation失败,另一个不会在数据库中闲逛。 这是我的OrdersController中的修剪代码:

rescue_from ActiveRecord::Rollback, with: :render_new def render_new render action: 'new' end ActiveRecord::Base.transaction do @user = User.new params[:user] unless @user.save raise ActiveRecord::Rollback end //More stuff ... @order = Order.new params[:order] ... unless @order.save raise ActiveRecord::Rollback end end 

我看到的错误是这样的:

缺少模板订单/创建,应用/创建{:locale => [:en],:formats => [:html],:handlers => [:erb,:builder,:coffee]}

我很困惑为什么它试图渲染模板命令/创建和应用程序/创建而不是渲染订单/新。

有没有更好的方法来强制事务失败,以便发生回滚?

我认为将事务包装在开始/救援块中时,意图会更清晰一些。

 def create begin ActiveRecord::Base.transaction do @user = User.new params[:user] unless @user.save raise ActiveRecord::Rollback end //More stuff ... @order = Order.new params[:order] ... unless @order.save raise ActiveRecord::Rollback end end rescue ActiveRecord::Rollback render action: "new" and return end end 

您需要在create方法中返回 ,否则它的执行将继续到方法的结尾,并且将发生Rails默认渲染(在这种情况下,它意味着尝试查找create.___模板)

如果你不喜欢开始/救援区,你可以添加一个and returnraise线

 raise ActiveRecord::Rollback and return 

以上答案是正确的,但渲染操作需要进行一些修改。

像这样做:-

 def create is_project_saved = false is_proposal_saved = false ActiveRecord::Base.transaction do is_project_saved = @project.save is_proposal_saved = @proposal.save if is_project_saved && is_proposal_saved # Do nothing else raise ActiveRecord::Rollback end end if is_project_saved && is_proposal_saved # You can add more nested conditions as per you need. flash[:notice] = "Proposal Created Successfully." redirect_to project_show_path(:job_id => @project.job_id) else render :new end end 

resque不会捕获ActiveRecord :: Rollback 。 所以它需要在事务块之外完成。

您还可以在嵌套的ActiveRecord::Base.transaction使用save_point :requires_new => true

您需要引发ActiveRecord :: Rollback并根据需要管理渲染/重定向。 正如@WasimKhan所说,ActiveRecord :: Rollback不会被救援抓住。

 def create @user = User.new params[:user] ActiveRecord::Base.transaction do if @user.save @order = Order.new params[:order] if @order.save redirect_to :index else raise ActiveRecord::Rollback end else render :new end end render :new if @user.id.nil? end