Ruby on Rails でプログラム的に名前空間/モジュール名を見つけるにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/133357

  •  02-07-2019
  •  | 
  •  

質問

以下のフィルターで名前空間またはモジュール「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 が #decontantize の逆であるためです。

"A::B::C".demodulize #=> "C"

これを本当に手動で行う必要がある場合は、次のことを試してください。

constant_name = "A::B::C"
constant_name.split( '::' )[0,constant_name.split( '::' ).length-1]

他のヒント

これで済むはずです:

  def get_module_name
    @module_name = self.class.to_s.split("::").first
  end

単純な場合には、以下を使用できます。

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

クラスにモジュール名があるかどうかを判断し、テストできるクラス名以外の何かを返すことができます。

これが古いスレッドであることは承知していますが、コントローラーの名前空間に応じて個別のナビゲーションが必要であることに気づきました。私が思いついた解決策は、アプリケーションのレイアウトで次のとおりです。

<%= render "#{controller.class.name[/^(\w*)::\w*$/, 1].try(:downcase)}/nav" %>

これは少し複雑に見えますが、基本的に次のことを行います。コントローラー クラス名を受け取ります。たとえば、名前空間のないコントローラーの場合は「People」、名前空間のあるコントローラーの場合は「Admin::Users」になります。[] 文字列メソッドを正規表現で使用すると、2 つのコロンの前に何かが返されるか、何もない場合は nil が返されます。次に、それを小文字に変更します (名前空間がなく、nil が返された場合に備えて「try」が存在します)。これにより、名前空間または nil が残ります。次に、名前空間の有無にかかわらず、たとえば名前空間なしで部分を単純にレンダリングします。

app/views/_nav.html.erb

または、管理名前空間内で次のようにします。

app/views/admin/_nav.html.erb

もちろん、これらの部分は名前空間ごとに存在する必要があります。存在しないとエラーが発生します。これで、コントローラーやビューを変更しなくても、各名前空間のナビゲーションがすべてのコントローラーに表示されるようになります。

my_class.name.underscore.split('/').slice(0..-2)

または

my_class.name.split('::').slice(0..-2)

はないと思います クリーナー ああ、これはどこかで見たことがある

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top