Reputation: 1375
I want to use dynamic path in my controller in rails gem.
I've added to
module MyGem
class FooController < Config.controller
before_action ->{ append_view_path "app/views/my_gem/#{wizard_name}" }
...
and in views I need to specify path like
app/views/my_gem/#{wizard_name}/my_gem/foo/some.erb
is in Rails some way, to cut the relative path of gem namespace, and get lookup path like?
app/views/my_gem/#{wizard_name}/some.erb
# or
foo/bar/some.erb
Thank you!
UPD:
I understand, that there is way with disabling isolate_namespace
in Engine
, but I believe, that it is not best and only option.
UPD2: For Rails4 this idea was very useful https://coderwall.com/p/p_yelg/render-view-outside-of-a-controller-in-rails-4
Upvotes: 33
Views: 1798
Reputation: 19
Usually, you should only override the partial views or the functions from that gem, do not load from the gem lib like this, because when deploying to the real server it will raise many troubles for you to debug and improve.
Upvotes: 0
Reputation: 109
The Devise gem has a way of adding views lookup path by overriding the _prefixes method:
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
Can this be applied to your use case?
See source:
https://github.com/plataformatec/devise/blob/master/app/controllers/devise_controller.rb
Upvotes: 1
Reputation: 1637
Assuming your gem is an engine, you should be able to simply call render :some
in the engine. If the app has a view called <gem_name>/<controller_name>/some.html.erb
it will be used.
Also, you can provide a version of that view in your gem that will be used if the app does not yet provide one.
If you need the wizard_name
to also be looked up, I think the best way to do that would be to move that portion of the view path to the to the end where you are calling render.
So in your gem's controller you would write render "#{wizard_name}/some"
and it would look for that view both in our app's app/views/<gem_name>/<controller_name>/<wizard_name>/some.html.erb
and in your gem's app/views/<controller_name>/<wizard_name>/some.html.erb
.
Upvotes: -1
Reputation: 23989
You could make your how render method that reads an arbitrary file, interpret the ERB and render it as an HTML page for instance.
ERB.new(File.read(Rails.root.join('foo', bar', 'some.erb'))).result(binding)
By passing binding
, the template will have access to the all the variables in the current context.
See ERB docs for more details: http://apidock.com/ruby/ERB
Upvotes: -1