missing partials with rails - ruby-on-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.

Related

missing template rails problem with JSON rendering?

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.

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

Rails looking for template for JSON requests

In my routes.rb I have:
resources :workouts
In my workouts controller I have:
def show
respond_to do |format|
format.html
format.json { render :json => "Success" }
end
end
But when I go to /workouts/1.json, I receive the following:
Template is missing
Missing template workouts/show, application/show with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder, :coffee]}. Searched in: * "/home/rails/app/views"
Which appears to show that the format is what it should be but it's still searching for a view. This same code functions in other controllers with identical setups just fine. Also, going to /workouts/1 for the html view seems to work just fine, though it also renders the html view properly when the format.html is removed.
Looks at the source code of render
elsif options.include?(:json)
json = options[:json]
json = ActiveSupport::JSON.encode(json) unless json.is_a?(String)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
response.content_type ||= Mime::JSON
render_for_text(json, options[:status])
Pay attention to the third line. If the value of :json is a string, render won't call to_json automatically for this value.
So the value remains as string and render will go on to search template.
To fix, supply a valid hash even for trying purpose.
format.json { render :json => {:message => "Success"} }
You would try with /workouts.json

How can I render an HTML view while constructing a JSON response in Rails?

I have a controller method that returns JSON. But sometimes part of that JSON object should include a rendered, serialized HTML view. So my controller method has a line like this:
html = render_to_string :partial => 'foo/bar'
# ...
render json: {x: 'y', html: html}
But that fails because Rails is only looking for JSON views!
ActionView::MissingTemplate (Missing partial foo/bar with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder, :coffee, :slim, :haml]}. […]
How can I solve this?
Update: I have gotten one "level" of layout to render_to_string as html using the below syntax, but the same error persists when that layout renders its own partials!
html = render_to_string :partial => "foo/bar.html.haml"
Surely there’s a solution here, right?
Update 2: render_to_string :action => 'method_in_this_controller' seems to be doing the trick.
Repeating Yanhao's answer because I ran into this exact problem and its what worked for me.
try:
html = render_to_string :partial => 'foo/bar', :formats=>[:html]
I am writing something like that in my action:
def show
...
respond_to do |format|
format.js { render :json => data }
end
end
May be it will help you.
Are you sure you have a file 'apps/views/foo/_bar.*'? I was able to render HTML as a JSON parameter with How do I render a partial to a string?
respond_to do |format|
format.html { redirect_to post_path(post) }
format.js {
render json: {
error: flash[:error],
content: (render_to_string partial: '/comments/comment', locals: {comment: comment}, layout: false )
}
}
end

"Template is missing" when rendering Liquid template

I'm trying to render a liquid template that is stored in the database.
Here is my 'show' action in the controller:
def show
#organization = Organization.find_by_subdomain(request.subdomain)
#template = Liquid::Template.parse(Template.find(#organization.current_template).body)
#page = #organization.pages.find(params[:id])
respond_to do |format|
format.html { render #template.render('page' => #page), :template => false}
format.json { render json: #page }
end
end
However, when I visit the page, I get a "Template is Missing" exception with the following error (note that "testing testing" is the body attribute of the page object, which is currently the only thing being rendered in the template):
Missing template /testing testing with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee, :haml]}.
Searched in: * "/Users/ashercohen/Documents/Rails/Vocalem-Rails/app/views"
* "/Users/ashercohen/.rvm/gems/ruby-1.9.3-p194/gems/twitter-bootstrap-rails-2.1.1/app/views"
* "/Users/ashercohen/.rvm/gems/ruby-1.9.3-p194/gems/devise-2.1.2/app/views"
Why is it trying to find another template, when I've specifically pass the :template => false argument? Is there something I'm missing here? I'm trying to bypass using any template files, as it seems like they shouldn't be needed here (though am not strongly opposed if I am wrong).
Because render almost always takes a filename, while #template.render('page' => #page) contains the plain html. You should invoke render like this:
render :text => #template.render('page' => #page), :content_type => :html

Resources