以下のフィルターで名前空間またはモジュール「Foo」の名前を見つけるにはどうすればよいですか?
class ApplicationController < ActionController::Base
def get_module_name
@module_name = ???
end
end
class Foo::BarController < ApplicationController
before_filter :get_module_name
end
これらのソリューションはいずれも、複数の親モジュールを持つ定数を考慮していません。例えば:
A::B::C
Rails 3.2.xの時点で、次のことが簡単にできます。
"A::B::C".deconstantize #=> "A::B"
Rails 3.1.xの場合:
constant_name = "A::B::C"
constant_name.gsub( "::#{constant_name.demodulize}", '' )
これは、#demodulizeが#deconstantizeの反対であるためです。
"A::B::C".demodulize #=> "C"
本当にこれを手動で行う必要がある場合は、これを試してください:
constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]
単純なケースでは、次を使用できます。
self.class.parent
これは、コントローラーにモジュール名がある場合は機能しますが、ない場合はコントローラー名を返します。
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
ただし、これを少し変更すると:
class ApplicatioNController < ActionController::Base
def get_module_name
my_class_name = self.class.name
if my_class_name.index("::").nil? then
@module_name = nil
else
@module_name = my_class_name.split("::").first
end
end
end
クラスにモジュール名があるかどうかを判断し、テストできるクラス名以外の何かを返すことができます。
my_class.name.underscore.split('/').slice(0..-2)
または
my_class.name.split('::').slice(0..-2)
私はこれが古いスレッドであることを知っていますが、コントローラーの名前空間に応じて個別のナビゲーションを行う必要があることに気付きました。私が思いついた解決策は、私のアプリケーションレイアウトでこれでした:
<%= render "#{controller.class.name[/^(\w*)::\w*$/, 1].try(:downcase)}/nav" %>
これは少し複雑に見えますが、基本的に次のことを行います。名前空間のないコントローラーの場合は「People」、名前空間のコントローラーの場合は「Admin :: Users」などのコントローラークラス名を使用します。 2つのコロンの前に何かを返す正規表現で[]文字列メソッドを使用するか、何もない場合はnil。次に、それを小文字に変更します(名前空間がなく、nilが返される場合は「try」があります)。これにより、名前空間またはnilが残ります。次に、名前空間の有無にかかわらず、たとえば名前空間なしでパーシャルをレンダリングします。
app/views/_nav.html.erb
またはadmin名前空間で:
app/views/admin/_nav.html.erb
もちろん、これらのパーシャルは名前空間ごとに存在する必要があります。存在しない場合、エラーが発生します。これで、コントローラーまたはビューを変更することなく、各名前空間のナビゲーションがすべてのコントローラーに表示されます。
cleanerの方法はないと思いますが、これはどこかで見たことがあります
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.name.split("::").first
end
end
gsub
の代わりにsplit
をお勧めします。他のモジュール名は必要ないので、split
よりも効果的です。
class ApplicationController < ActionController::Base
def get_module_name
@module_name = self.class.to_s.gsub(/::.*/, '')
end
end
多くのサブモジュールで:
module ApplicationHelper
def namespace
controller.class.name.gsub(/(::)?\w+Controller$/, '')
end
end
例:Foo::Bar::BazController
=> Foo::Bar