Rails respond_to in the controller - ruby-on-rails

This is the code from internet and I am having trouble understanding what does respond_to, format.html and format.js do in the controller.
def create
#review = Review.create!(params[:review])
flash[:notice] = "Thank you for reviewing this product"
respond_to do |format|
format.html { redirect_to #review.product }
format.js
end
end
Thank you for your time.
Ramya

respond_to(*types, &block) public
Without web-service support, an action which collects the data for displaying a list of people might look something like this:
def index
#people = Person.find(:all)
end
Here’s the same action, with web-service support baked in:
def index
#people = Person.find(:all)
respond_to do |format|
format.html
format.xml { render :xml => #people.to_xml }
end
end
What that says is, "if the client wants HTML in response to this action, just respond as we would have before, but if the client wants XML, return them the list of people in XML format." (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
Supposing you have an action that adds a new person, optionally creating their company (by name) if it does not already exist, without web-services, it might look like this:
def create
#company = Company.find_or_create_by_name(params[:company][:name])
#person = #company.people.create(params[:person])
redirect_to(person_list_url)
end
Here’s the same action, with web-service support baked in:
def create
company = params[:person].delete(:company)
#company = Company.find_or_create_by_name(company[:name])
#person = #company.people.create(params[:person])
respond_to do |format|
format.html { redirect_to(person_list_url) }
format.js
format.xml { render :xml => #person.to_xml(:include => #company) }
end
end
If the client wants HTML, we just redirect them back to the person list. If they want Javascript (format.js), then it is an RJS request and we render the RJS template associated with this action. Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also include the person’s company in the rendered XML, so you get something like this:
http://apidock.com/rails/ActionController/MimeResponds/InstanceMethods/respond_to

Related

Rails 5 best controller action to write a like query

I want to make an ajax search query by a client's name, so I'm using a like clause (see this question). I was thinking of using the index action to respond to json format from clients_controller but I'm already using it to repond to html format and at the same time paginates my listed rows with will_paginate and will_paginate-bootstrap.
What is the best way? making a new method to respond to json format or should I use the index one with format? and How to do that?
I'm new with ruby on rails
clients_controller.rb
def index
respond_to do |format|
format.html
{
#something like this I know that I would return me a syntax error
#client = Client.paginate(:page => params[:page])
}
format.json
{
#something like this I know that I would return me a syntax error
#client = Client.where("client_name LIKE ? ", "%#{params[:client_name]}%" )
}
end
end
def other_method
#client = Client.where("client_name LIKE ? ", "%#{params[:client_name]}%" )
respond_to do |format|
format.json {...}
end
end
In my opinion, you should keep only your index action and just accumulate the scopes on your #client variable.
Remember that your SQL query is only sent to the database when performing an Array method like each on your variable, not before.
So you can write something like:
def index
#client = Client.all
if params[:client_name].present?
#client = #client.where("client_name LIKE ? ", "%#{params[:client_name]}%")
else
#client = #client.paginate(page: params[:page])
end
respond_to do |format|
format.html
format.json
end
end
You should create a new action with some fruitful name like search or search_by_client_name . It will solve your issue also and you will stick with rails restful routing.
If you want index action to serve both request then you can do something like this:
def index
#client = Client.paginate(:page => params[:page])
respond_to do |format|
format.html
format.json do
client = Client.where("client_name LIKE ? ", "%#{params[:client_name]}%"
render json: { client: client }
end
end
end

What does respond_to do when called without a block?

I understand how respond_to works when it's called with something like this:
def index
#users = User.all
respond_to do |format|
format.html
format.json { render json: #users }
end
end
But I've seen some apps which pass respond_to a list of symbols, outside of the controller methods, e.g.:
class UsersController < ApplicationController
respond_to :html, :json
def index
# blah blah bah
end
end
What does this do? I've been playing around with it in one of my controllers and I can't figure out what difference it makes.
For a given controller action, #respond_with generates an appropriate response based on the mime-type requested by the client.
If the method is called with just a resource, as in this example -
class PeopleController < ApplicationController
respond_to :html, :xml, :json
def index
#people = Person.all
respond_with #people
end
end
then the mime-type of the response is typically selected based on the request's Accept header and the set of available formats declared by previous calls to the controller's class method respond_to. Alternatively the mime-type can be selected by explicitly setting request.format in the controller.
If an acceptable format is not identified, the application returns a '406 - not acceptable' status. Otherwise, the default response is to render a template named after the current action and the selected format, e.g. index.html.erb. If no template is available, the behavior depends on the selected format:
for an html response - if the request method is get, an exception is raised but for other requests such as post the response depends on whether the resource has any validation errors (i.e. assuming that an attempt has been made to save the resource, e.g. by a create action) -
If there are no errors, i.e. the resource was saved successfully, the response redirect's to the resource i.e. its show action.
If there are validation errors, the response renders a default action, which is :new for a post request or :edit for patch or put.
Thus an example like this -
respond_to :html, :xml
def create
#user = User.new(params[:user])
flash[:notice] = 'User was successfully created.' if #user.save
respond_with(#user)
end
is equivalent, in the absence of create.html.erb, to -
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = 'User was successfully created.'
format.html { redirect_to(#user) }
format.xml { render xml: #user }
else
format.html { render action: "new" }
format.xml { render xml: #user }
end
end
end
for a javascript request - if the template isn't found, an exception is raised.
for other requests - i.e. data formats such as xml, json, csv etc, if the resource passed to respond_with responds to to_, the method attempts to render the resource in the requested format directly, e.g. for an xml request, the response is equivalent to calling render xml: resource.

Rails: respond_to JSON and HTML

I have a controller "UserController" that should respond to normal and ajax requests to http://localhost:3000/user/3.
When it is a normal request, I want to render my view. When it is an AJAX request, I want to return JSON.
The correct approach seems to be a respond_to do |format| block. Writing the JSON is easy, but how can I get it to respond to the HTML and simply render the view as usual?
def show
#user = User.find(params[:id])
respond_to do |format|
format.html {
render :show ????this seems unnecessary. Can it be eliminated???
}
format.json {
render json: #user
}
end
end
As per my knowledge its not necessary to "render show" in format.html it will automatically look for a respective action view for ex : show.html.erb for html request and show,js,erb for JS request.
so this will work
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
also, you can check the request is ajax or not by checking request.xhr? it returns true if request is a ajax one.
Yes, you can change it to
respond_to do |format|
format.html
format.json { render json: #user }
end
The best way to do this is just like Amitkumar Jha said, but if you need a simple and quick way to render your objects, you can also use this "shortcut":
def index
#users = User.all
respond_to :html, :json, :xml
end
Or make respond_to work for all the actions in the controller using respond_with :
class UserController < ApplicationController
respond_to :html, :json, :xml
def index
#users = User.all
respond_with(#users)
end
end
Starting from Rails 4.2 version you will need to use gem responder to be able to use respond_with.
If you need more control and want to be able to have a few actions that act differently, always use a full respond_to block. You can read more here.

Respond_to and redirect in the same action in Rails

In the Update action of Rails controllers usually there is code that looks like this:
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
else
render :edit
end
end
In the else case, this will render the edit template. But what if I wanted to use a respond_to, exactly the same way that I have in the edit action, as:
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
else
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #team }
end
end
end
So, if the Update fails, be sure you are returning a json or html depending on the requested format. Does that makes sense? If so, how would you avoid the error: "Render and/or redirect were called multiple times in this action"
Makes sense to me. The answer should be simple, just return after redirect_to.
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to(#book)
return
else
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #team }
end
end
end
Not sure exactly how you're rendering multiple times, but assuming you are, a well-placed return should tell RAILS to stop processing any further renders after redirecting. If that's all true, it's likely that there's an after_filter interfering from somewhere.

Add JSON support to Rails app

I am experimenting with Rails and was wondering what's needed to allow/add support for JSON requests?
I have a vanilla installation of Rails 2.3.5 and the default scaffolding seem to provide support for HTML & XML requests but not JSON.
class EventsController < ApplicationController
# GET /events
# GET /events.xml
def index
#events = Event.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #events }
end
end
# GET /events/1
# GET /events/1.xml
def show
#event = Event.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #event }
end
end
...
I'm new to this but it would appear as though i would need to add a format line in each method along the lines of:
format.js { render :js => #event.json }
couldn't this be done automatically? perhaps there's a template somewhere i need to update...or a flag i can set? Or perhaps, and most likely, I've missed the boat entirely?!?
You do:
format.json {render :json=>#event}
That will render the default activerecord JSON for the model
The option of ease of use is that you can write a private method which takes the format object and an object to render and then, based on the format, renders different things. Example:
class MyController<ApplicationController
def show
#event=Event.find(params[:id])
respond_to do {|format| myRenderer(format,#event)}
end
...
private
def myRenderer(fmt,obj)
fmt.json {render :json=>obj}
fmt.html
fmt.xml {render :xml=>obj}
end

Resources