これは非常に簡単です。Orionの提案を実装できますが、以下に示すより広範な手法を実装することもできます。これにより、任意のモデルから現在のコントローラーにアクセスでき、MVC分離を解除することを決定した目的(フラグメントキャッシュの操作、アクセスcurrent_user
、生成など)が可能になります。パス/URLなど)
任意のモデルから現在のリクエストのコントローラー(存在する場合)にアクセスするには、次を新しいプラグインに追加するenvironment.rb
か、できれば新しいプラグインに追加します(たとえばvendor/plugins/controller_from_model/init.rb
、以下のコードを含むcreate)。
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
ようにすることができますが、何かを機能させるためにそうする必要はありません(醜くて維持するのは難しいですが。)
楽しむ!