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

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

app/views/_nav.html.erb

или в пространстве имен admin:

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