Rails抽象自定义destroy方法(或默认情况下向模型错误添加例外)

时间:2012-11-04 12:32:02

标签: ruby-on-rails-3 activerecord

我想要做的是在无法销毁特定​​模型时返回错误,而不是异常。目前,它会引发ActiveRecord::DeleteRestrictionError,但不会返回到Flash消息,也不会添加到模型的errors集合中。

我所做的就是在我的资源丰富的控制器中设置它:

  def destroy
    begin
      resource.destroy
    rescue ActiveRecord::DeleteRestrictionError => e
      resource.errors.add(:base, e)
    end
  end

我宁愿不在每个需要这种特殊行为的控制器中管理它。我怎么抽象呢?我认为覆盖ActiveRecord::Base的destroy方法不是一个好主意,但也许不会有任何陷阱?

我正在使用inherited_resources gem,所以也许有办法通过扩展它来回答这个问题?

我的另一个想法是使用ActiveRecord::Base(从这里:Rails extending ActiveRecord::Base)扩展ActiveSupport::Concern,然后在模型到模型的基础上将destroy方法委托给自定义销毁。想法?

2 个答案:

答案 0 :(得分:2)

首先我会说我同意不重写ActiveRecord :: Base方法的态度,比如destroy。为了干这种行为你有几个选择,我将列出其中两个:

第一个 - 不是在特定控制器中编写rescue子句,而是可以将它嵌入到ApplicationController中,因此行为将在应用程序范围内进行:

# ApplicationController.rb

rescue_from ActiveRecord::DeleteRestrictionError do |exception|
  resource.errors.add(:base, exception) if resource
end

另一个选择是创建一个模块并将其包含在您想要具有此行为的不同控制器中:

module SafeDestroyer
  def safe_destroy(resource)
   begin
      resource.destroy
    rescue ActiveRecord::DeleteRestrictionError => e
      resource.errors.add(:base, e)
    end
  end
end

class MyController < ApplicationController
  include SafeDestroyer

  def destroy
    safe_destroy(resource)
  end

end

答案 1 :(得分:0)

我最终做的是从主资源控制器继承我的控制器,我发现它比所讨论的其他选项更清晰,更强大(在此处找到:http://roberto.peakhut.com/2010/09/27/admin-controllers-with-inherited-resources/)。

// controllers/resources_controller.rb
class ResourcesController < ApplicationController
  load_and_authorize_resource
  inherit_resources

  def destroy
    begin
      resource.destroy
    rescue ActiveRecord::DeleteRestrictionError => e
      resource.errors.add(:base, e)
    end
  end
end

然后,只需从此控制器而不是ApplicationController继承您的资源控制器:

// controllers/models_controller.rb
class ModelsController < ResourcesController

end

希望能帮助处于类似情况的人。