On my project I have
respond_to :json
load_and_authorize_resource
def show
respond_with #job_pattern
end
as per tutorial here http://blog.plataformatec.com.br/2009/08/embracing-rest-with-mind-body-and-soul/
it works like this: when a request comes, for example with format xml, it will first search for a template at users/index.xml
so I checked for job_patterns/index.json but didnt find any file with this name
can anyone guide me where i can find the file or how the output is generated here if it is not with the file.
Because respond_to :json does not render a view, rather it calls render json: #job_pattern.
render json:#job_pattern calls #job_pattern.to_json and sets the JSON string as the response body. You can do the same with XML or YML.
This is an example of the rails convention over configuration philosophy - if there is a show.json.[erb|haml] it takes priority. Otherwise rails will look for an instance variable which corresponds with the name of the controller (#job or #jobs for index) and attempt to serialize it as JSON.
Further reading:
Justin Weiss: respond_to Without All the Pain
Rails Guides: Layouts and Rendering in Rails
In your case, your action is show so the template associated with is show.json in views/[namespace]/show.json.
You should create this template, or if this template is not found Rails will automatically invoke to_json on the object passed to respond_with.
Refer to documentation.
Recents version of Rails with generated scaffold use show.json.jbuilder as template file.
For more info about it:
jbuilder
Related
I have a rails app which uses angularjs. Here I'm trying to render a template from rails controller and pass a resource to the template. But the ruby code for displaying the variables are showing exactly as it is in the html.erb view.
def fail
#order = Order.find(1)
render 'payments/fail'
end
in view
<%= #order.as_json %>
My guess would be that the problem is in the name of your view file. I'd guess that you named it something like fail.html instead of fail.html.erb. Without the .erb suffix, Rails just interprets the file as html text and renders it without interpreting the ruby code.
However, changing the file name isn't quite the correct solution. Since you want to render json instead of HTML you don't need to create a view template, so you should just delete the template file altogether.
All Rails models have an .as_json method automatically, so you can simply modify your controller's fail method like so:
def fail
#order = Order.find(1)
render json: #order.as_json
end
Also if you want to do something fancy and modify the json that is returned, you can define your own as_json method inside the model.
When there is
def some_action
respond_to do |format|
format.html {}
format.js {}
format.json { respond_with #objects}
end
end
It seems like html line and the js line automatically serve up/call the file matching the action's name. And the html and the js are serve up one or the other, not both. Is this correct?
The json gets called if you have an ajax call in your js that got called, and it requests data, and these need data to respond with, right? Do I need it to respond to json and to js, or just one?
If you don't to respond_to, and omit all the types, does it by default respond to html and to js?
When I do respond_to in the controller, rather than a respond_to block within each action, does using respond_with #objects apply to any argument (:thml, :js, :xml, :json, etc)?
Alternate syntax:
class TheController < ApplicationController
respond_to :html, :js, :json, only: [:some_action, :other_action]
def some_action
respond_with #objects
end
end
How does the alternate syntax work?
If you use the alternate syntax, can you not respond differently to different types of requests? Do you have to do a respond_to block isntead of the alternate syntax if you want to respond differently? How do each of these cases address graceful degradation to html?
respond_with
For a given controller action, respond_with generates an appropriate response based on the mime-type requested by the client.
This basically means your controller will send the appropriate data on a request basis - for example, if you did the following:
#app/controllers/articles_controller.rb
Class ArticlesController < ApplicationController
def show
#article = Article.find params[:id]
respond_with #article
end
end
This would basically respond with the data from #article each time you send a request. If the request is in the json mime-type, it will come back as a JSON object; if it's an HTML request, it will come back with the HTML object on the show view
--
respond_to
Basically allows you to tailor the specific responses to different mime-types. If you send a JS request, you can manage the JS response etc
respond_to blocks inside the controller actions are very cumbersome, and only really meant for specific changes / edits to the response itself.
A much simpler way to handle the respond_to is to declare it at the top of the controller file, essentially telling Rails that every action will use the options defined in that method:
#app/controllers/your_controller.rb
Class YourController < ApplicationController
respond_to :js, :json, :html #-> the same as using respond_to block for each action
end
note that in Rails 4 respond_with feature has been extracted to the gem 'responders' (https://github.com/plataformatec/responders).
The cases of when you need/don't need each format.*whatever* line.
Normally, you don't need any of it. Rails by default looks for an html file (aka template) matching the action name under the view folder matching the controller's name.
I'm not sure when/why the json and html are sometimes paired together(like in the scaffold-generated code). Perhaps the json line is for turbolinks (please confirm/correct this). But I do know you use a respond_to block with various types of format lines when you want each type to behave differently (e.g. serve up 10 results at a time through js, but more results through html).
The js format is needed when you use remote: true in a form or link. This is because Using this remote: true disables the html template from being served up, and instead looks for a js file matching the action's name, and executes/renders that file. You don't actually need the respond to json line if you're doing things in js only.
Bonus hint: if your js files have js.erb, you can access the instance variables (how about local variables? please confirm/correct this) that you set in your action. This kind of makes sense because your *.js.erb file is technically a view. Views can access its corresponding actions' variables (hmm what about when vies get rendered from another controller?). So if you already have access to your action's variables in your js file, this can eliminate the need to make ajax calls or json calls in many situations.
I'm actually not sure when you need the json line when also using remote: true / javascript. explicit jQuery.ajax() method calls that want json data might warrant the use of the respond to json line.
I'm building an API on Rails using ActiveRecordSerializer for serialization. When I want to render a list of resources I use:
render json: #resources
This automatically detects that there is a serializer for the resource, and uses it.
Now I want to implement pagination, and my idea is having a class called PaginatedResponse, instantiate it and render it as a json like this:
render json: PaginatedResponse.new(#resources, <more meta information of the page>)
The problem is that when I use this, everything works well but the resources are not rendered using ActiveRecordSerializer, but a default serializer. I suspect that this is happening because PaginatedResponse does not extend ActiveRecord.
Any clue how can I solve this?
Rails 4 has introduced a new concept jbuilder by default. So just create index.json.jbuilder and put the json syntex based code. Just refer the default scaffold index json jbuilder below,
json.array!(#users) do |user|
json.extract! user, :name, :email, :phone, :native_place
json.url user_url(user, format: :json)
end
This is for rendering all users with his name, phone, native_place.
So remove the line
render json: #resources
from your code and implement the the new jbuilder concept.
The solution was including ActiveModel::SerializerSupport in PaginatedResponse to indicate ActiveRecordSerializer that a serializer should be used.
I have an action in my controller as below:
def show
#post = Post.find_by_setitle(params[:setitle])
if !#post
render 'error_pages/404'
return
end
respond_to do |format|
format.html
end
end
If the render error_pages/404 I get a template missing. Switching it to render error_pages/404.haml.html works fine.
Why is this?
N.B. There is no actual error_pages controller or model. Just a convenient place to keep them.
Edit: I'm using mongoid and hence don't have access to ActiveRecord. Controller base can't be looking for a particular ActiveRecord exception?
From the documentation
The render method can also use a view that’s entirely outside of your application (perhaps you’re sharing views between two Rails applications):
Rails determines that this is a file render because of the leading slash character. To be explicit, you can use the :file option (which was required on Rails 2.2 and earlier):
You need either to pass the :file option, or to start the location string with a slash. Alternatively, you could use the Rails functionality to rescue from errors, and recover from ActiveRecord::RecordNotFound with a 404. See this post for details.
You should probably use render :template => 'error_pages/404'.
I think Rails is looking for a partial called _404.
Try it out 1:
render 'error_pages/404' (and name the file _404.html.erb)
Try it out 2:
render :template => 'error_pages/404' (and name the file 404.html.erb i.e. no leading underscore)
I'm creating a website in Ruby on Rails, where users can login using RESTful Authentication. Someone can get a specific user using html, xml and json, just like scaffolding. But I want to add one more format: vCard (e.g. /users/1.vcard). This has a specific format, but how do I define my own formats? Using views, or must I use another way? Thanks
In your /config/initializers/mime_types.rb file, add a new registration for your format. It should look something like this:
Mime::Type.register "text/x-vcard", :vcard #The :vcard is the important part
After that (you'll have to restart your app to pick up the change), you can respond to the symbol like any other format:
# then in your controller action
def show
respond_to do |format|
format.html # render html
format.vcard { #render vcard }
end
end
Adding from comments (thanks nanda):
In your views folder, then, you would put the vCard template into a show.vcard.erb file (for example).