Как вы находите имя пространства имен/модуля программно в 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
601   9  

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]

Это должно сделать это:

  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" %>

который выглядит немного сложным, но в основном делает следующее - он принимает имя класса контроллера, которое было бы, например, "люди" для контроллера без пространства имен и "Admin::Users" для пространства имен. Использование строкового метода [] с регулярным выражение, которое возвращает что-либо до двух двоеточий, или ноль, если ничего нет. Затем он изменяет это на нижний регистр ("try" есть в случае, если нет пространства имен и возвращается nil). Это тогда оставляет нам либо пространство имен, либо ноль. Затем он просто отображает частичное с пространством имен или без него, например No namespace:

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

Comments

    Ничего не найдено.