这很容易做到。您可以实现 Orion 的建议,但您也可以实现下面说明的更广泛的技术,这使您可以从任何模型访问当前控制器,以及您决定打破 MVC 分离的任何目的(例如,弄乱片段缓存、访问current_user
、生成路径/URL 等)
为了从任何模型访问当前请求的控制器(如果有的话),请将以下内容添加到新插件中environment.rb
,或者最好添加到新插件中(例如vendor/plugins/controller_from_model/init.rb
,包含以下代码的创建):
module ActiveRecord
class Base
protected
def self.thread_safe_current_controller #:nodoc:
Thread.current[:current_controller]
end
def self.thread_safe_current_controller=(controller) #:nodoc:
Thread.current[:current_controller] = controller
end
# pick up the correct current_controller version
# from @@allow_concurrency
if @@allow_concurrency
alias_method :current_controller, :thread_safe_current_controller
alias_method :current_controller=, :thread_safe_current_controller=
else
cattr_accessor :current_controller
end
end
end
那么,在app/controllers/application.rb
,
class ApplicationController < ActionController::Base
before_filter { |controller|
# all models in this thread/process refer to this controller
# while processing this request
ActiveRecord::Base.current_controller = controller
}
...
然后,从任何模型,
if controller = ActiveRecord::Base.current_controller
# called from within a user request
else
# no controller is available, didn't get here from a request - maybe irb?
fi
无论如何,在您的特定情况下,您可能希望在相关控制器类加载时将代码注入到您的各个ActiveRecord::Base
后代中,以便实际的控制器感知代码仍然驻留在 中app/controllers/*.rb
,但为了获得某些功能而不必这样做(虽然丑陋且难以维护。)
玩得开心!