在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
这很好用,home
和profile
是 pages_controller.rb 中两个动作的名称,而show
和new
是 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
答案 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会变得很混乱>