通过控制器为Rails过滤器指定异常(又名Action回调)

时间:2019-01-31 23:17:23

标签: ruby-on-rails

https://guides.rubyonrails.org/action_controller_overview.html#filters之后,我有一个方法pull_alerts,在执行许多操作之前需要运行该方法。这些动作在几个不同的控制器中,所以我在 application_controller.rb 中有代码:

class ApplicationController < ActionController::Base

  before_action :pull_alerts, only: [:home, :profile, :show, :new]

  private

    def pull_alerts
      @unread_notifications = <... some code here ...>
    end

end

这很好用,homeprofile pages_controller.rb 中两个动作的名称,而shownew widget_controller.rb 中的两个动作的名称。

我现在希望在第三个控制器中的pull_alerts操作之前运行show,例如 doodad_controller.rb -但在该控制器中new动作之前不是。我一直找不到在以下情况下如何指定此名称的参考(命名空间/范围?)。

before_action :pull_alerts, only: [:home, :profile, :show, :new]

构造这种安排的最佳方法是什么?我是否需要将其移出 application_controller.rb 并在每个单独的控制器(页面,小部件,装饰)中指定before_action?如果这样做,我可以在哪里放置该方法以使其干燥?还是最好像这样在 doodad_controller.rb 中添加它?

class DoodadsController < ApplicationController

  skip_before_action :pull_alerts, only: [:new]

end

1 个答案:

答案 0 :(得分:3)

正确的答案取决于您要权衡哪些。

权衡

在这种情况下,需要考虑以下几点:

  • 可读性/可理解性
  • 重复
  • 代码行数
  • 可扩展性

您最看重什么?

我的观点

我个人认为可读性比其他大多数事物(包括重复)要高。

根据我的经验,很容易沉迷于DRY并最终在三个月内使您感到困惑的代码。

解决方案

# application_controller.rb
class ApplicationController < ActionController::Base
  def pull_alerts
    @unread_notifications = <... some code here ...>
  end
end

# home_controller.rb
class HomeController < ActionController::Base
  before_action :pull_alerts, only: [:show, :new]
end

# profile_controller.rb
class ProfileController < ActionController::Base
  before_action :pull_alerts, only: [:show, :new]
end

# doodad_controller.rb
class DoodadController < ActionController::Base
  before_action :pull_alerts, only: :show
end

当然,有一些重复。但是,如果您阅读了代码,就可以在几秒钟内知道发生了什么。

相反

此代码:

class DoodadsController < ApplicationController
  skip_before_action :pull_alerts, only: :new
end

要求您查看以前调用过pull_alerts的操作。然后,您需要考虑“负数”-即被跳过。

这里的另一个缺点是可扩展性-如果您也想在pull_alerts之前调用:update,那么在知道DoodadsController的更新时是否仍调用pull_alerts会变得很混乱>