How to change a template location for render_to_string method? - ruby-on-rails

I know render_to_string method searches a template in views folder by default, but can this be changed? I mean, does the template have to be located in the views folder or not? I don't like to have some XML templates in the views.
Now my template is in views/domains/fulfillment/template.xml.erb,
but I would prefer not to have it in views like app/domains/fulfillment/template.xml.erb.
My current code:
def query(params:, file_path:)
ActionController::Base.new.render_to_string(
layout: false,
template: "app/domains/fulfillment/#{file_path}",
locals: params,
).strip
end
I am getting an ActionView::MissingTemplate error now, when the its not in the views folder.
I have tried only to changed the template parameter in render_to_string method and can't find how to change it. Thanks.

You can use the file: option to specify an absolute path to a file instead of using the view paths:
ActionController::Base.new.render_to_string(
layout: false,
file: Rails.root.join("app", "domains", "fulfillment", file_path)
locals: params,
).strip

Related

How to access full asset_url path in Ruby on Rails

If I call render a view from the controller, then asset_url('file.png') returns the entire url, aka http://www.example.com/assets/file.png. However, if I try to render the view from anything outside of the controller, such as a service or a custom method defined in lib/, then the asset_url('file.png') just simply returns /assets/file.png.
It seems that the full URL for asset_url is only accessible when the controller is rendering a view, and that's it. Is there anything I can set so that asset_url will always return the full path? Or do I need to go in and manually convert 200+ asset_url links in my app?
View:
#app/views/path/to/view.html.erb
asset_url('file.png')
Rendering the view from controller:
html = render_to_string template: '/path/to/view', layout: false, locals: {report: #report}
Results:
http://www.example.com/assets/file.png
Rendering the view from a service or custom method:
# create an instance of ActionView, so we can use the render method outside of a controller
av = ActionView::Base.new()
av.view_paths = ActionController::Base.view_paths
# need these in case your view constructs any links or references any helper methods.
av.class_eval do
include Rails.application.routes.url_helpers
include ApplicationHelper
end
html = av.render template: '/path/to/view', layout: false, locals: {report: #report}
Results (missing domain):
/assets/file.png
Rather than calling asset_url within my views, I am now using a custom method called custom_asset_url, which checks to see if asset_url has the full URL in it. If not, it puts it in there and returns it.
def custom_asset_url(asset)
# This was defined because if you call asset_url outside of a controller, then the host doesn't
# render, therefore it just displays /assets/ instead of http://www.example.com/assets (which breaks PDF generation).
url = asset_url(asset)
if !url.include? "http"
if Rails.env.production?
url = "https://prod-url#{url}"
else
url = "http://dev-url:3000#{url}"
end
end
return url
end
Until I can figure out why asset_url is nil when called from outside of a controller, this is the workaround method.

Rails views helper don't seems to work with render_to_string

I try to convert rails views into pdf with the gem wicked_pdf.
But when I do a render_to_string like this
ActionController::Base.new.render_to_string(template: "templates/pdf_meteo.html.erb", locals: {communaute_meteo_id: id}, layout: 'pdf')
Methods like user_path don't work and return undefined method error... (note that the page work properly if I render it in html)
If someone can help me !
You can include helpers by using the following method
ac = ActionController::Base.new
ac.view_context_class.include(ActionView::Helpers, ApplicationHelper)
ac.render_to_string(template: "templates/pdf_meteo.html.erb", locals: {communaute_meteo_id: id}, layout: 'pdf')
Unfortunately, using render_to_string will not give you access to Rails URL helpers. One workaround is to include them directly in the locals that you pass into the PDF template using something like url: Rails.application.routes.url_helpers:
ActionController::Base.new.render_to_string(
template: "templates/pdf_meteo.html.erb",
locals: {url: Rails.application.routes.url_helpers, communaute_meteo_id: id}
layout: 'pdf'
)
And then inside of your PDF template you would call them with:
url.user_path
Keep in mind that by default the _path URL helpers will be relative, and not absolute paths. You can instead use the _url version of the helpers and set the host for them in a few different ways. You can configure them globally for your entire app:
# config/environments/development.rb
Rails.application.routes.default_url_options[:host] = 'www.mysite.com'
or set them individually on each helper inside of your PDF template:
url.user_url(host: 'www.mysite.com')
Hope that gets you what you need!
Simplest way is to use regular rails rendering flow - with view file your_action_name.pdf.erb, trick is in overriding formats for partials:
<%= render partial:"some_partial", formats:[:html] %>
Also you can run render_to_string in context of your controller to have helpers (because ActionController::Base knows nothing about your app)

Rails is Looking for a Partial in the Wrong Directory

I have a polymorphic Review model. The namespaced model User::Library::Publication is reviewable. The reviews are created properly, but when I try to display them through a partial, Rails looks up the wrong directory.
In my view:
<%= render #review %>
I get this error:
Missing partial user/library/reviews/review with {:locale=>[:en], :formats=>[:js, :html], :handlers=>[:erb, :builder]}
Rails is apparently looking for the review partial within the namespace's directory views/user/library instead of the /views/reviews. Any idea why this is happening?
If you want to remove namespacing from the partial template path, you can set the prefix_partial_path_with_controller_namespace variable in your config/application.rb:
# config/application.rb
config.action_view.prefix_partial_path_with_controller_namespace = false
This will load partial paths as you define them (without the namespace).
You can see the original Pull Request here.
If you use name spaces you have to create folders/sub folders so Rails is not looking at the wrong place.
If you want to force the partial path just use:
render :partial => "review"
And create rename the review.html.erb file to _review.html.erb

Rails - Rendering a Partial without having to use "_" in front of the filename?

How do I render a partial without having to supply the "_" in front of the file name? Is there a parameter I can call to not use it?
This problem popped up using RABL and Backbone - using RABL requires me to have a file in my views like "index.json.rabl". But, when I use embed the JSON right on the page load (as is usual with Backbone), I'm required to call the file "_index.json.rabl". These 2 files are the exact same thing, just required to have different names. I'm looking to use just 1 file, "index.json.rabl" and force the render() function to look for that file name, without the "_".
=> EDIT
The standard solutions that people have described below don't work. It's likely a RABL issue then? The below code always goes to the views/countries/_index.json.rabl file.
In my .erb file
countryList.reset(<%=get_json("countries", "index", #countries)%>);
In my application_helper.rb file
def get_json(view_path, view_action, object)
path = view_path + '/' + view_action + ".json"
return raw(render(path, object: object, :formats => [:rabl]))
end
You can render a file by doing the following:
render :file => "filename"
From the RailsCast #322 on RABL:
<div id="articles" data-articles="<%= render(template: "articles/index.json.rabl") %>" >
Start from here, and then figure out what's wrong. But it's clear that render template: path is the syntax you want.
did you try render :template => "file_name" ?
Ok try:
<%= render :file => 'views_directory/index' %>
Where views_directory is the name of your directory in the views 8)
OLD:
If the content is the same use:
render :partial => "index"
in index.json.rabl and the content in _index.json.rabl

Rails: render a partial from a plugin

I'm getting a missing template error after I try rendering a partial from a plugin. I have included the files with the following:
%w{ models controllers helpers views }.each do |dir|
path = File.join(File.dirname(__FILE__), 'app', dir)
$LOAD_PATH << path
ActiveSupport::Dependencies.load_paths << path
ActiveSupport::Dependencies.load_once_paths.delete(path)
end
The Models are getting loaded, but as for other things I'm not sure what's going on. The helpers are not getting loaded too because I just copied the contents of the partial from the plugin instead of the render :partial => and then it came up with a helper error.
Question is how to be able to :render :partial => from the views folder in my plugin
For plugin views you usually just copy them to your app/views directory, or the plugin installer copies for you. Views don't work on the $LOAD_PATH the same way models and controllers.
In Rails 2.3.* your vendor/plugins/XXXX/app/views/ directories are automatically included in load paths. So when given the following plugin structure:
vendor/plugins/your_plugin/app/views/shared/_box.html.erb
Yuppie!
You are able to call this partial from, for example, app/views/site/index.html.rb like this:
<%= render 'shared/box' %>

Resources