Render in action is shown on the screen - Ruby on rails - 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.

Related

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.

JS format in the controller

Let's assume I have a controller action that whenever you try to access it via a js format, I want to render nothing.
def no_js_please
# there isn't a no_js_please partial or view
respond_to do |format|
format.html { # render a template }
format.json { render json: {valid: true} }
format.js { render nothing: true, status: :not_found }
end
end
When you access the endpoint via html or JSON, it works just fine. When you try to access it via JS it doesn't work. However, it does actually execute the block, because if I add a binding.pry within the js block, it gets picked up.
However, this does work:
def no_js_please
if request.format.js?
render nothing: true, status: :not_found
end
end
So what's the difference between the two?
EDIT
As a human mentioned below, what's the actual error? So, in this particular case, it raises a ActionController::InvalidCrossOriginRequest.
Use "head" instead of "render nothing: true". The latter is actually deprecated in Rails 5+ anyway.
def no_js_please
respond_to do |format|
format.html { # render a template }
format.json { render json: {valid: true} }
format.js { head :not_found }
end
end
This will get you the result you're looking for and it will be one less line to change when you upgrade.

Rails render template with status

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.

Parsing JSON errors using simple_form and AJAX in rails

I have a form that is using Simple Forms and remote => true on the users dashboard (which is handled by a dashboard view and dashboard controller). The form allows a user to add a custom game rule; however, it's loading the form via a Jquery's .load() function. The form is loading from the "rules" view (handled by a rules controller).
When the user clicks the submit button, I'm not getting any error validation.
Her is the create action on the rule controller:
def create
#rule = Rule.new(params[:rule])
respond_to do |format|
if #rule.save
format.html { redirect_to dashboard_path, notice: 'Rule was successfully created.' }
format.json { render json: #rule, status: :created, location: #rule }
format.js
else
format.html { render template: 'dashboard/index'}
format.json { render json: #rule.errors, status: :unprocessable_entity }
format.js
end
end
end
I've got a js file called create.js.erb in my views folder that is currently empty. I think that I have to somehow parse the JSON error data in this create.js.erb file, but I have no idea how to do it.
Also, does it matter that this form is being called by the Dashboard view/controller but the form is being handled by the Rule controller?
Try the following inside create.js.erb
$('.error-messages').remove();
<% if #rule.errors.any? %>
$('body').append('<ul class="error-messages"></ul>');
<% #rule.errors.full_messages.each do |msg| %>
$('.error-messages').append('<%= escape_javascript msg %>');
<% end %>
<% end %>
This will append the errors in your body tag.

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).

Resources