missing template rails problem with JSON rendering? - ruby-on-rails

Has anyone come across this error before? I've looked online and couldn't find much information, perhaps I didn't render my JSON correctly?
Missing template answer/results, application/results with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}. Searched in: * "/Users/Minhaj/Desktop/my_survey/my_survey/app/views" * "/Users/Minhaj/.rvm/gems/ruby-2.4.1/gems/devise-4.5.0/app/views"
Here is the code. If there is an error, help will be appreciated in fixing it.
def create
#answer = current_survey.answers.create(question_id: question, choice_id: choice)
redirect_to question_survey_path(current_survey)
end
def results
#choices = choices_hash
#results = questions.map do |question|
{
question.question => CountChoicesService.call(question.id)
}
end
respond_to do |format|
format.html { render :nothing => true, :status => 204 }
format.json { render json: #results }
end
end
private
def question
#question ||= params[:question]
end
def choice
#choice ||= params[:choice]
end
def choices
#choices ||= Array.wrap(Choice.all)
end
def choices_hash
choices_hash = {}
choices.each { |choice| choices_hash[choice.id] = choice.choice }
choices_hash
end
def questions
#questions ||= Array.wrap(Question.all)
end
end
I appreciate the help in advance.

Here is how it should look like, controller name is plural
Under your controller directory, you should have this
# app/controller/answers_controller.rb
class AnswersController < ApplicationController
def results
end
end
Now in the views directory,the view namespace should be the same as the controller name.
# app/views/answers/results.html.erb
<h1>Check if this works</h1>
routes.rb
resources :answers do
collection/member do
get :results
end
end

Your problem is that you are not returning. Rails will render the associated template for the action unless you return. Try wrapping your render calls in return().
Side note, why are you using Array.wrap()? ActiveRecord’s all methods are array-like. They wait to execute the query until you actually try to iterate them, and then they act like an array. You shouldn’t need to make them an array. If you ever find that you do, you can call .to_a on them.
One thing to note about the active record record collection though, if you remove anything from its “array”, it will actually do a delete from the database, which may or may not be what you want.

Related

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

Accessing a method in rails controller via button/link

I was trying to follow the solution on this thread - Rails 3 link or button that executes action in controller
I defined :update_question in my routes.rb file:
resources :surveys do
put :update_question, :on => :member
end
and in my controller:
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :edit, :update, :destroy]
before_action :set_question
# GET /surveys
# GET /surveys.json
def index
#surveys = Survey.all
end
# GET /surveys/1
# GET /surveys/1.json
def show
end
def survey
#survey = Survey.find(params[:survey_id])
end
# GET /surveys/new
def new
#survey = Survey.new
end
# GET /surveys/1/edit
def edit
end
def update_question
flash[:alert] = "getting there man"
end
And listed the link here in the html:
<%= link_to "Next Question", update_question_survey_path(#survey), {:method => :put} %>
However when I click the link I get this error:
Template is missing
Missing template surveys/update_question, application/update_question with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}.
Which seems to elude that it's looking for a view - but really I just want it to run the method in my survey controller and update the question that's being displayed. Perhaps I'm going about this the wrong way, any help/suggestions is much appreciated!
That's because the action is correctly reached, but then Rails tries to render something. By default, it will look for a view file with the same name of the action.
You should do something like this:
def update_question
set_survey
# do stuff
flash[:alert] = "getting there man"
redirect_to survey_path(#survey)
end

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"},

Creating User with Rails API and JSON?

So I'm testing out a very simple API in Rails to see if I can create a user from it locally using the Chrome plugin Postman (REST Client extension).
In my rails app, I've set up a folder/namespace for my API, and whenever I try to create my user, I get the following error:
Missing template api/v1/users/create, application/create with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in: * "PATH/app/views"
I'm using Rails 4.0.1 and Ruby 2.0
I'm posting a screenshot below of what I'm posting:
module Api
module V1
class UsersController < ApplicationController
class User < ::User
# add any hacks
end
respond_to :json
def index
respond_with User.all
end
def show
respond_with User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.create(user_params)
# respond_with(#user)
if #user.save
# render json: #user, status: :created, location: #user
redirect_to #user
end
end
private
def user_params
params.require(:user).permit(:name, :age, :location) if params[:user]
end
end
end
end
So based on my user_params, I should be able to create a new user, correct?
Please let me know if you need any additional info and I'll do my best to respond ASAP!
Thanks!
You can create user using API.
1) First you need to put proper resources in your routes.rb:
YourApp::Application.routes.draw do
namespace :api do
namespace :v1 do
resources :users
end
namespace :v2 do
# ... if needed
end
end
root to: 'users#index'
end
2) You need to create a RESTfull-style controller to process requests. Here how your action 'create' may be implemented.
def create
respond_with User.create(fio: params[:fio], phone: params[:phone], region: params[:region], updated_at: Time.now)
end
Example of 'create' with respond_to:
def create
# ...
respond_to do |format|
format.html {render text: "Your data was sucessfully loaded. Thanks"}
format.json {
User.create(... params ...)
render text: User.last.to_json # !
}
end
end
See documents about respond_with and respond_to if you need something special to respond.
Also can be helpful railscasts episodes about API building: #350 and #352
P.S. folder/namespace/v1/users_controller shall be the same as class name in your module Api
P.S.2 You can observe my app, where you can probably find something helpful (same as your app - simple API for records creating) - myApp
Example of users_controller (controllers/api/v1/users_controller.rb):
#encoding: utf-8
module Api
module V1
class UsersController < ApplicationController # Api::BaseController
before_filter :authenticate_user!, except: [:create, :index]
respond_to :json
def index
#respond_with
respond_to do |format|
format.html {render text: "Your data was sucessfully loaded. Thanks"}
format.json { render text: User.last.to_json }
end
end
def show
respond_with User.find(params[:id])
end
def create
respond_with User.create(access_token: params[:access_token], city: params[:city], created_at: Time.now, phone: params[:phone], region: params[:region], updated_at: Time.now)
end
def update
respond_with User.update(params[:id], params[:users])
end
def destroy
respond_with User.destroy(params[:id])
end
end
end
end
redirect dose not return, so your create method will keep looking for template to render, and then find there is no matching template.
To fix, you need to explicitly return redirect
if #user.save
return redirect_to(#user)
end
You also need to pay attention to the default url of #user. It's better to assign a named path explicitly in this case, say redirect_to(user_path(#user))

missing partials with rails

def some_action
#posts = Post.all
render partial: 'layouts/things'
end
In my layouts directory I have things as partial (_things.html.erb)
My other partials work fine. But it doesn't render partial throwing exception as
Missing partial layouts/things with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in: * "/my/path/appname/app/views"
Edit-1
def some_action
#posts = Post.all
respond_to do |format|
format.json
end
end
Ok i changed my controller link this but then too same exception.
Edit-2
I have created in my views/controller_name/_some_action.json.erb
This is the controller
def some_action
#posts = Post.all
respond_to do |format|
format.json { render json: #posts }
end
end
My _some_action.json.erb file has
<%= render partial: 'shared/information', post: #posts.name %>
And created _information..js.erb in views shared directory
MY _information.js.erb has sample text as
test
I am getting json response from controller i checked with inspect element. But it is not render actual text i need (i.e., test)
well, IMHO you need to name your partial like
_things.js.erb
or no?
As Jacub Kuchar mentions, if you're trying to provide a JSON response, your partial should be named accordingly (i.e. _things.js.erb). You should also put it in the 'shared' directory rather than 'layouts' as it's a partial, not a layout.
However, I'd also keep the logic of which view to render of the controller and let the view itself handle it.
So your controller can simply say:
respond_to :json # (and whatever other response types you want to support: xml, etc)
def some_action
respond_with #posts = Post.all
end
And then having a matching view, under views/{controller name}/some_action.js.erb, which says:
<%= render partial: 'shared/things', posts: #posts %>
That way your controller isn't polluted with view logic.

Resources