Rails 4 + append_view_path
Я хочу использовать динамический путь в моем контроллере в rails gem.
Я добавил в
module MyGem
class FooController < Config.controller
before_action ->{ append_view_path "app/views/my_gem/#{wizard_name}" }
...
и в представлениях мне нужно указать путь как
app/views/my_gem/#{wizard_name}/my_gem/foo/some.erb
находится в Rails каким-то образом, чтобы разрезать относительный путь пространства имен gem и получить путь поиска, например?
app/views/my_gem/#{wizard_name}/some.erb
# or
foo/bar/some.erb
Спасибо!
UPD:
Я понимаю, что есть способ отключить isolate_namespace
в Engine
, но я считаю, что это не лучший и единственный вариант.
UPD2: для Rails4 эта идея была очень полезной https://coderwall.com/p/p_yelg/render-view-outside-of-a-controller-in-rails-4
Ответы
Ответ 1
В геме Devise есть способ добавления пути поиска представлений путем переопределения метода _prefixes:
class DeviseController < Devise.parent_controller.constantize
include Devise::Controllers::ScopedViews
# Override prefixes to consider the scoped view.
# Notice we need to check for the request due to a bug in
# Action Controller tests that forces _prefixes to be
# loaded before even having a request object.
#
# This method should be public as it is is in ActionPack
# itself. Changing its visibility may break other gems.
def _prefixes #:nodoc:
@_prefixes ||= if self.class.scoped_views? && request && devise_mapping
["#{devise_mapping.scoped_path}/#{controller_name}"] + super
else
super
end
end
end
Может ли это быть применено к вашему варианту использования?
Смотрите источник:
https://github.com/plataformatec/devise/blob/master/app/controllers/devise_controller.rb
Ответ 2
Обычно вам следует переопределить только частичные представления или функции из этого гема, не загружайте их из библиотеки гемов, как это, потому что при развертывании на реальном сервере у вас возникнет много проблем с отладкой и улучшением.
Ответ 3
Вы можете сделать свой способ визуализации, который читает произвольный файл, интерпретировать ERB и отображать его как HTML-страницу, например.
ERB.new(File.read(Rails.root.join('foo', bar', 'some.erb'))).result(binding)
Передавая binding
, шаблон будет иметь доступ ко всем переменным в текущем контексте.
Подробнее см. документы ERB: http://apidock.com/ruby/ERB
Ответ 4
Предполагая, что ваш драгоценный камень является движком, вы можете просто вызвать render :some
из них. Если приложение имеет представление с именем <gem_name>/<controller_name>/some.html.erb
оно будет использовано.
Кроме того, вы можете предоставить версию этого представления в своем геме, которая будет использоваться, если приложение еще не предоставило ее.
Если вам нужно, чтобы имя wizard_name
также просматривалось, я думаю, что лучший способ сделать это - переместить эту часть пути к концу до конца, где вы вызываете render.
Таким образом, в вашем контроллере gem вы должны написать render "#{wizard_name}/some"
и он будет искать этот вид как в нашем приложении app/views/<gem_name>/<controller_name>/<wizard_name>/some.html.erb
и в вашем app/views/<controller_name>/<wizard_name>/some.html.erb
gem app/views/<controller_name>/<wizard_name>/some.html.erb
.