Как вы находите имя пространства имен/модуля программно в Ruby on Rails?
Как найти имя пространства имен или модуля ' Foo ' в фильтре ниже?
class ApplicationController < ActionController::Base
def get_module_name
@module_name = ???
end
end
class Foo::BarController < ApplicationController
before_filter :get_module_name
end
9 ответов:
ни одно из этих решений не рассматривает константу с несколькими родительскими модулями. Например:
A::B::Cпо состоянию на рельсы 3.2.X вы можете просто:
"A::B::C".deconstantize #=> "A::B"по состоянию на рельсы 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]
это будет работать, если контроллер имеет имя модуля, но вернет имя контроллера, если это не так.
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" %>который выглядит немного сложным, но в основном делает следующее - он принимает имя класса контроллера, которое было бы, например, "люди" для контроллера без пространства имен и "Admin::Users" для пространства имен. Использование строкового метода [] с регулярным выражение, которое возвращает что-либо до двух двоеточий, или ноль, если ничего нет. Затем он изменяет это на нижний регистр ("try" есть в случае, если нет пространства имен и возвращается nil). Это тогда оставляет нам либо пространство имен, либо ноль. Затем он просто отображает частичное с пространством имен или без него, например No namespace:
app/views/_nav.html.erbили в пространстве имен администратора:
app/views/admin/_nav.html.erbконечно, эти партиалы должны существовать для каждого пространства имен в противном случае возникает ошибка. Теперь навигация для каждого пространства имен будет отображаться для каждого контроллера без необходимости изменять какой-либо контроллер или представление.
Я не думаю, что есть пылесос путь, и я видел это где-то еще
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
Comments