ActionView::MissingTemplate, Rails 5 API with JSON - ruby-on-rails

I am consistently getting an ActionView::MissingTemplate error when trying to render JSON in my Rails 5 Api. I just want to render the pure JSON, without a jbuilder or other view. Can anyone help?
thing_controller.rb:
class Api::ThingController < ApplicationController
def thing
render json: {error: 'This is my error message.'}, status: 422
end
end
thing_controller_test.rb:
require 'test_helper'
class Api::ThingControllerTest < ActionDispatch::IntegrationTest
test "the truth" do
get '/api/thing'
assert_response 422
end
end
full error message:
Error: Api::ThingControllerTest#test_the_truth:
ActionView::MissingTemplate: Missing template api/thing/thing,
application/thing with {:locale=>[:en], :formats=>[:json],
:variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby,
:jbuilder]}.
application_controller.rb:
class ApplicationController < ActionController::API
include ActionController::Caching
include ActionController::ImplicitRender # want implicit view rendering for JBuilder
before_action :add_cors_headers
def options
head(:ok) if request.request_method == "OPTIONS"
end

This is related to an issue in Rails 5 beta ActionController::API and Jbuilder. It looks like it has been fixed by this pull request.
Meantime you can return plain text and set the content type, like so:
render plain: {error: 'This is my error message.'}.to_json, status: 422, content_type: 'application/json'

Related

rails 5.1 API and Jbuilder render problem

After setup a simple API and try to login with a simple session controller
Session Controller
def create
user = User.find_by(email: [:email])
if user && user.authenticate([:password])
render json: {token: user.access_token}, status: 200
else
render text: "Email and password combination are invalid", status: 422
end
end
in the logs show
ActionView::MissingTemplate (Missing template sessions/create,
application/create with {:locale=>[:en], :formats=>[:json],
:variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby,
:jbuilder]}. Searched in: * "/home/daniel/ranks/app/views" ):
after googling around seems a issue with jbuilder and the workaround that some proposed was to: in the application controller
include ActionView::Rendering
def render_to_body(options)
_render_to_body_with_renderer(options) || super
end
but the problem persist so someone has any idea how to solve this issue with rails 5.1 and jbuilder 2.7.0?

Specifying layout in namespaced controller

I am creating a new version of one of my controllers,
Original Controller:-
class ExampleController < ApplicationController
layout 'filename', only: [:method_name]
...
def method_name
#...some logic...
respond_to do |format|
format.html
format.json {
render json: {}, root: false
}
end
end
...
end
New Controller:-
class V1::ExampleController < ApplicationController
layout 'filename', only: [:method_name]
...
def method_name
#...some logic...
respond_to do |format|
format.html
format.json {
render json: {}, root: false
}
end
end
...
end
I keep getting error:-
Missing template v1/example/filename, application/filename with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :arb, :haml, :jbuilder]}
One of the solution is to create a folder structure v1/example and put my layout file there too. But I do not want to create duplicate copies of this file.
Another is to use a parent controller class of both new and old example_controller and specify layout there(and have a folder structure according to the name of the parent class). But this will be an overkill and also I plan on deleting old controller once all my clients migrate to new versions.
I also tried specifying like this:-
class V1::ExampleController < ApplicationController
layout 'example/filename', only: [:method_name]
...
end
but this also doesn't work.
How to tell my new controller to render layout from the old folder structure.
format.html {
render template: 'path/to/template'
}
Rendering a template
Template rendering works just like action rendering except that it
takes a path relative to the template root. The current layout is
automatically applied.
# Renders the template located in [TEMPLATE_ROOT]/weblog/show.r(html|xml) (in Rails, app/views/weblog/show.erb)
render :template => "weblog/show"`
See reference for #render

rspec controller test can't find partial

I'm using render_to_string as a json response. It works fine in my app, but rspec can't find the partial.
controller:
# controllers/admin_controller.rb
class AdminController < ApplicationController
def retrieve_edit_form
user = User.find(params[:id])
form = render_to_string('_user_form', layout: false)
respond_to do |format|
format.json { render json: { form: form } }
end
end
end
spec:
# spec/app/controllers/admin_controller_spec.rb
require 'rails_helper'
RSpec.describe AdminController, type: :controller do
render_views
describe 'GET retrieve_edit_form' do
it 'returns http success' do
get :retrieve_edit_form, id: 100, format: :json
expect(response).to be_success
end
end
end
I get the error:
Missing template admin/_user_form, application/_user_form with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee]}. Searched in:
* "/Users/.../app/views"
How can I get rspec to recognize the partial?
Ok, I figured it out. Turns out I needed to add the extension to the partial and it all works fine.
The controller needed to be
form = render_to_string('_user_form.html.erb', layout: false)

rails 4 template missing error in render in ajax

I have the following ajax function
$.ajax({
url: '/sub_categories/sub_cat',
data: 'sub_cat=45',
success: function() {
alert('success');
}
})
Here is my controller
require 'json'
class SubCategoriesController < ApplicationController
def show
end
def sub_cat
#sub_categories = SubCategory.where(category_id: params[:cat_id])
html = render_to_string 'sub_categories/sub_cat'
response_html true,html
end
end
My application controller
def response_html status,html
respond_to do |format|
format.json {render json: {
status: status,
html: html,
}
}
format.html
end
end
I have json file in sub_categories/sub_cat.json.erb
When I run getting error as
ActionView::MissingTemplate at /sub_categories/sub_cat.json
Missing template sub_categories/show, application/show with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
* "/home/editmehere/Documents/site/name/app/views"
My route.rb has
resources :sub_categories do
get 'sub_cat', on: :collection
end
Why I am getting error like this and how can I solve it. Can anyone help me to solve it.
I'm guessing you're trying to keep your application dry, but why don't you just use this in your SubCategoriesController:
class SubCategoriesController < ApplicationController
def sub_cat
#sub_categories = SubCategory.where(category_id: params[:cat_id])
respond_to do |format|
format.json
format.html
end
end
end
This will allow you to call sub_cat.json.erb without having to pass the status var, or pre-render the HTML. This is just convention, so apologies if it's not what you need. I see a lot of people on here overcomplicate things, when simplicity would work much better
Ajax
Also, I believe you've got a problem with your ajax data var:
data: 'sub_cat=45',
should be
data: {sub_cat: "45"},

action mailer gives error while passing layout

in my action mailer(rails 3.2.13) I have something like
class RepaymentMailer < ActionMailer::Base
default from: "repayments#milaap.org"
def repayment_mail user, user_repayment_info, month_date
#mail_layout = if condition_true
'layout1'
else
'layout2'
end
mail(to: "#{user.first_name} <#{user.email}>",
from: "xxx#xxx.org",
bcc: ["xxx <xxx#xxx.org>"],
reply_to: 'xxx#xxx.org',
subject: "this is a test" ) do |format|
format.html { render layout: #mail_layout }
format.text
end
end
end
when I do
puts RepaymentMailer.repayment_mail(param1, param2, param3).deliver
it gives me error that even if repayment_mail template exist
ActionView::MissingTemplate: Missing template repayment_mailer/repayment_mail with {:locale=>[:en], :formats=>[:text], :handlers=>[:erb, :builder, :coffee, :arb]}. Searched in:
If I remove
do |format|
format.html { render layout: #mail_layout }
format.text
end
then It works without error.
But Obviously I want the desired layout. What can be the cause of the error.
Because in your error, it is clearly showing that problem is with this line:
Missing template repayment_mailer/repayment_mail with {:locale=>[:en], :formats=>[:text]**, :handlers=>[:erb, :builder, :coffee, :arb]}.
I think you didn't read the lines below:
class UserMailer < ActionMailer::Base
def welcome_email(user)
mail(to: user.email) do |format|
format.html { render layout: 'my_layout' }
format.text
end
end
end
This will render the HTML part using the my_layout.html.erb file and the text part with the usual user_mailer.text.erb file if it exists.
Please read here.
Thanks

Resources