Rails 6. Render a js.erb file - ruby-on-rails

I need to render a js.erb view inside a Model's method:
ApplicationController.render(template: 'js/library.js.erb', assigns: {foo: 'bar'}, handlers: [:js], formats: [:js])
works perfect, but I'm also getting:
DEPRECATION WARNING: Rendering actions with '.' in the name is deprecated:
But then if I try:
ApplicationController.render(template: 'js/library', assigns: {foo: 'bar'}, handlers: [:js], formats: [:js])
I'm getting:
ActionView::MissingTemplate
Missing template js/library.js with {:locale=>[:en], :formats=>[:js, :html], :variants=>[], :handlers=>[:js]}.
so, what is the correct way to render a js.erb file on Rails 6?

Solution:
Call a specific Controller's action, id est, a controller that already exists:
JsController.render('js/library', assigns: assigns)

Related

Template missing in render :file in ajax call when the file exists in Rails 4.2

Ajax is used for Bootstrap modal call. The js.erb file is called successfully and this js.erb file then should load html.erb residing in the same subdir as the js.erb is under biz_workflowz/app/views/application/. Here is the js.erb file:
$("#newworkflow .modal-content").html('<%= j render(:file => "/biz_workflowx/application/event_action.html.erb") %>');
$("#newworkflow").modal();
However the event_action.html.erb is never found. The error is raised in action_view/path_sets.rb:
def find(*args)
find_all(*args).first || raise(MissingTemplate.new(self, *args)) #find_all(*args).first returns NIL
end
The error is:
ActionView::Template::Error (Missing template c:/d/code/rails_proj/engines/biz_workflowx/app/views/application/event_action.html.erb with {:locale=>[:en], :formats=>[:js, :html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee]}. Searched in:
.......
* "C:/D/code/rails_proj/engines/biz_workflowx/app/views" #<<== did search the subdir but did not find anything
* "C:/D/code/rails_proj/engines/searchx/app/views"
* "C:/D/code/rails_proj/engines/commonx/app/views"
* "C:/D/code/rails_proj/engines/authentify/app/views"
* "C:/D/code/rails_proj/webportal"
* "C:/"
):
1: $("#newworkflow .modal-content").html('<%= j render(:file => "biz_workflowx/application/event_action.html.erb") %>');
2: $("#newworkflow").modal();
actionview (4.2.0) lib/action_view/path_set.rb:46:in `find'
Even with hardcoded path to the file event_action.html.erb, it still returns template missing. The similar js.erb code has been used in a few places for ajax call and I does not see why here it does not work. What could cause this error?
Updated
Here is the debug windows showing the biz_workflowz/app/views has been searched by resolver which does not see the file under /application/. Strange!
add event_action.html.erb file under c:/d/code/rails_proj/engines/biz_workflowx/app/views/application

Rails 5 render a template located outside of the 'views' directory

The following code
def show
render File.join(Rails.root, 'app', 'themes', 'default_theme', 'template'), layout: File.join(Rails.root, 'app', 'themes', 'default_theme', 'layout')
end
Works in rails 4.2.x but outputs the following error when using Rails 5.0.0
ActionView::MissingTemplate:
Missing template vagrant/app/themes/default_theme/template with {:locale=>[:nl], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby]}. Searched in:
* "/vagrant/app/views/themes/default_theme"
* "/vagrant/app/views"
* "/home/vagrant/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/bundler/gems/devise-ebe65b516b38/app/views"
* "/home/vagrant/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/devise-i18n-1.1.0/app/views"
It looks like it is searching only inside the 'app/views/*' directory. Is there a way to render a template located outside of the 'views' directory using rails 5.0.0, so it works just like it used to in previous Rails versions?
Start by appending the view path:
class ApplicationController
prepend_view_path( Rails.root.join('app/templates') )
# ...
end
You can then render templates in app/templates by calling:
render template: 'default_theme/template',
layout: 'default_theme/layout'
Using the template option tells rails to not append the path with the name of the controller.
You have to add the new folder to your configuration:
config.paths["app/views"].unshift(Rails.root.join("/vendor/myapp/views/myctrl").to_s)
Or your controller:
before_filter {
prepend_view_path(Rails.root.join("vendor/myapp/views/myctrl").to_s)
}
source

Attaching AXLSX view to mail Rails Mailer

According to the GitHub Page for the axlsx gem I should use this syntax to render a xlsx view to a file and attach it:
xlsx = render_to_string handlers: [:axlsx], formats: [:xlsx], template: "users/export", locals: {users: users}
attachments["Users.xlsx"] = {mime_type: Mime::XLSX, content: xlsx}
Here is my mail method:
xlsx = render_to_string(handlers: [:axlsx], formats: [:xlsx], template: 'v1/reports/reportxyz', params: {start_date: '2016-09-12', period: 'weekly'})
attachments["report.xlsx"] = {content: xlsx, mime_type: Mime::XLSX}
mail(to: "my#email.address", subject: "Report", format: "text")
However I get this error when I try and call the mailer method:
ActionView::MissingTemplate: Missing template layouts/mailer with {:locale=>[:en], :formats=>[:xlsx], :variants=>[], :handlers=>[:axlsx]}. Searched in:
* "path/to/project/app/views"
Why is the render_to_string method affecting what the mailer view the mailer is trying to render? locgially I don't have a mailer.xlsx.axlsx file in my app/views/layouts folder but rather the mailer.text.erb I am trying to use as with other emails.
EDIT
I changed the render line to xlsx = render_to_string(template: 'v1/reports/azamara_social', params: {start_date: '2016-09-12', period: 'weekly'})
And now it seems to try and render the xlsx view but of course gets nil:NilClass errors when the xlsx view tries to reference instance variables defined in the reports controller.
Have you tried passing layout: false? What versions of axlsx, axlsx_rails, rails, and rubyzip are you using?
In the end it all came down to moving the controller code into a lib file. This way I call it in the controller to get the data if it needs to be rendered via web-requests as well as via the Mailer method where I recreate the #variables the view template is looking for.
Here is the finished salient parts of the report mailer method:
data = ReportUtils.get_data(args)
xlsx = render_to_string(template: 'path/to/report.xlsx', locals: {:#period => period, :#date_ranges => data[:date_ranges], :#data => data[:data]})
attachments["report.xlsx"] = {content: xlsx, mime_type: Mime::XLSX}

Rails 4 - MissingTemplate/Missing Partial Error, Only in Production

We just secured our application with an SSL certificate. Moving to HTTPS is proved more complex than we thought and we're currently sorting through a few of the resulting bugs.
We have an AJAX call in CoffeeScript, where rails responds by rendering the html of a partial. This is working perfectly in development.
CoffeeScript:
coffee_method: (pos, uid) =>
$.ajax '/contoller/test/',
type: 'POST'
data:
pos: pos
uid: uid
success: (data) ->
$('#result-div').html(data) #Populates side menu with _next_destination_menu content
error: ->
alert 'How embarassing! Something went wrong - please try your search again. '
Controller:
def test
... #do some stuff
puts "format requested: #{request.format}"
puts "format url_encodeded: #{request.format.url_encoded_form?}"
render partial: 'trips/_test' #app/views/trips/_test.html.erb
end
However, in production, we get the following error:
ActionView::MissingTemplate (Missing partial trips/_test with {:locale=>[:en], :formats=>[:url_encoded_form], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}.
After some digging, I figured out the request in production was a different format. Using those puts lines in the controller to debug, here are the results:
Production:
format requested: application/x-www-form-urlencoded
format url_encodeded: true
Development:
format requested: */*
format url_encodeded: false
What is the best way to handle this issue. Do I:
Change the content type of every AJAX call in the CoffeeScript?
Add a respond_to...format.url_encoded_form {render partial: trips/test} to the controller?
The latter seems like I would be duplicating code, because I want to render the same partial, regardless of the format the request comes in. I tried format.all {...} but encountered the same issue. Any best practices are appreciated!
Update:
Specifying the response type directly gives me the same missing template error:
respond_to do |format|
format.html {render partial: 'trips/test'}
format.json {render partial: 'trips/test' }
format.url_encoded_form {render partial: 'trips/test'}
end
Update 2:
The Request headers for both localhost and production are the same, the content type is application/x-www-form-urlencoded, even though format.url_encoded_form? returns false.
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4
Connection:keep-alive
Content-Length:37
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
You could try passing in the format, locale, and handlers exactly as requested:
render(
   partial: 'trips/test',
     formats: [:html, :js, :json, :url_encoded_form],
     locale: [:en],
     handlers: [:erb, :builder, :raw, :ruby, :coffee, :jbuilder])

ActionView::MissingTemplate: Rails not looking for JSON format

I'm using Backbone.js and thus bootstrapping data using a JSON (jbuilder) partial like so (using HAML):
App.users = new App.UserList(#{render('users/index', :formats => [:json], :handlers => [:jbuilder], locals: {users: #users})})}, {silent:true});
It gives me this error:
ActionView::Template::Error (Missing partial users/index with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :jbuilder, :arb, :coffee, :haml]}. Searched in:
Notice that it is only looking for the ':html' format, despite me passing in 'formats: [:json]'. Should I be doing something differently?
Thank you for any help.
What version of Rails are you using? This problem was fixed for 3.2.3, but exists in earlier versions.
For a quick fix, though it will cause deprecation warnings in Rails 3.2 and later, you can add the format to the name of the template, i.e. render('users/index.json' ...

Resources