Rails render template with status - ruby-on-rails

What is the simplest/shortest way to respond in an API controller. Currently the following works:
respond_to do |format|
format.json { render 'client', status: :ok }
end
however this controller will only ever respond to json (respond_to :json) so the whole respond_to do |format| thing seems like unnecessary code.
Ideally I would just like to do something simple like:
render 'client', status: :ok
Update:
I neglected to mention that: 'client' is a jbuilder template that does not match my action name.

You can use render directly
render json: 'client', status: :ok

According to #hassasin, you can indicate your controller to render json: format on each action of your controller.
Other option is to take advantage of your config.routes.rb to set the entire response format of your controller, e.g. contacts_controller:
resources :contacts, defaults: {format: :json}
If you want to indicate the status, add this to your actions:
def index
render status: :ok # 200, 400, 500, what ever you want
end
I tested the code above with Rails 3.2.16
I hope it helps you.

Since you are using json views (assume you are using jbuilder), you dont need that render statement if your action name matches the view name.

Related

Rails routes: json endpoint naming convention

I have an endpoint that renders json:
def controller_method
render json: json_response
end
However, I am curious about the naming convention of the route. The following naming leads to ActionController::UnknownFormat Controller#controller_method is missing a template for this request format and variant.:
get '/controller/controller_method.json', to: 'controller#controller_method'
However, I successfully get the json when the route is named:
get '/controller/controller_method_data', to: 'controller#controller_method'
Am I not allowed to put .json in the url routes? Any way that I can allow .json be the name of the route?
There is a much easier way to respond to different formats - just use ActionController::MimeResponds
get '/controller/controller_method', to: 'controller#controller_method'
class Controller < ApplicationController
def controller_method
respond_to do |format|
format.json { render json: { hello: 'world' } }
format.html # renders the view implicitly
format.txt { render plain: 'Hello world'}
end
end
end

Render in action is shown on the screen - Ruby on rails

I am new programming in ruby ​​on rails and I need help with a problem of a render in an action of my controller
This is my action:
def events_calendar
render json: {events: all_events}, status: :ok
end
This is what it shows me:
I want you to show me my web page and not the data of my render, how could I solve this?
Take a look at respond_to.
def events_calendar
respond.to do |f|
f.html
f.js { render json: {events: all_events}, status: :ok }
end
end
That way, you get the JSON when you call events_calendar using AJAX, and still render events_calendar.html.erb when you use a plain HTTP resquest.

Redirect to another page in Ruby on Rails

I want to redirect to another page admin_antenna_reader_rfids_path at the end of the create method. I did:
def create
#antenna_reader_rfid = AntennaReaderRfid.new(antenna_reader_rfid_params)
if #antenna_reader_rfid.save
render json: {status: true}
redirect_to admin_antenna_reader_rfid_path(q#antenna_reader_rfid)
else
render json: {errors: #antenna_reader_rfid.errors.full_messages, status: false}
end
end
I get an error AbstractController :: DoubleRenderError:
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
How can I solve this?
You have to remove the line render json: {status: true} as currently you're trying to make your controller render a json and redirect to an HTML page at the same time. You have to pick one.
To handle multiple request format, you can use respond_to
if #antenna_reader_rfid.save
respond_to do |format|
format.json { render json: { status: true } }
format.html { redirect_to where_you_want_path }
end
else
# same way as above
end
Within the respond_to block, you can render all the request formats as you want, then based on the request header, the controller will choose the corresponding logic to respond to you.
You can't render nor return more than once in a method.

How to render erb template to string inside action?

I need a string of html (something like "<html><body>Hello World</body></html>") for faxing purpose.
I wrote it into a seprate erb file: views/orders/_fax.html.erb ,
and try to render the erb in action: html_data = render(:partial => 'fax').
Here is part of the controller that raises the issue:
respond_to do |format|
if #order.save
html_data = render(:partial => 'fax')
response = fax_machine.send_fax(html_data)
......
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render json: #order, status: :created, location: #order }
else
format.html { render action: "new" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
It gave me an AbstractController::DoubleRenderError as below:
AbstractController::DoubleRenderError in OrdersController#create
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
How to solve this problem?
If you only need the rendered HTML, and don't need any functionality from the controller, you might try using ERB directly within a helper class, eg.:
module FaxHelper
def to_fax
html = File.open(path_to_template).read
template = ERB.new(html)
template.result
end
end
The ERB docs explain this in more detail.
EDIT
To get the instance variables from the controller, pass the binding into the result call, eg:
# controller
to_fax(binding)
# helper class
def to_fax(controller_binding)
html = File.open(path_to_template).read
template = ERB.new(html)
template.result(controller_binding)
end
Note: I've never done this, but it seems workable :)
Use the #render_to_string method
it works the same way as the typical render method but useful when you need to add some templated HTML to a json response
http://apidock.com/rails/ActionController/Base/render_to_string
If you don't want to escape html, just call .html_safe on it:
"<html><body>Hello World</body></html>".html_safe
Re your error, please post your OrdersController - looks like you are calling render or redirect more than once in the create action.
(Btw, just in case you are trying it - you can't render a partial in a controller - you can only render partials in views)
Edit: yeah your problem is you trying to render a partial in the controller action. You could use an after_create callback to set up and send the fax - though again you won't want to use a partial (as they are for views). http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
Edit: for your fax problem,you could create a normal Ruby Class, see this excellent bit of advice from Yehuda: https://stackoverflow.com/a/1071510/468009
The reason is you cannot render or redirect inside the same action more than once at a given time.
But in your code, you have both render and redirect. I think in your controller you can use simply only the render, assuming you don't need any json output.
Try this
def create
#order.save
render(:partial => 'fax')
end
I haven't tested this, but I guess you get the idea :), and think about a way to handle errors as well (in case order didn't save).

Respond_with templates and status codes

There are some instances where I need to both have a template and return error codes when using respond_with in Rails 3.
I have a before filter that is as follows:
def ensure_premium
respond_with("Must be a premium user!", status: 401, location: nil) unless current_user.is_premium?
end
and a create action that does the following:
def create
#wait_list = #hangout.wait_lists.find_or_create_by(user_id: current_user.id)
respond_with(#wait_list) do |format|
format.json {render 'create', status: 201}
end
end
Even though the before filter trips, it still tries to render the template which results in an error. What am I missing to get it to return the right error and status code and not render the template?
You have multiple respond_with's for the create action. But I think more critically, you might need:
def ensure_premium
respond_with :json => {:error => "Must be a premium user!", :status => :unauthorized } unless....
I don't think this is the problem, but make sure in your controller you have
class SomeController < ApplicationController
respond_to :json
I ended up going a different route completely so this question is no longer valid.

Resources