I am getting DoublerenderError - ruby-on-rails

I have this following code in my controller, the error trace to this piece of code for the error DoubleRenderError.
def build_list(query_string)
tasks = query_tasks(query_string)
#schema2tasklist = schema2tasklist(tasks)
respond_to do |format|
format.html { render :file => "#{Rails.root}/app/views/tasks/list.html.erb" }
end
end
I'm confused where to put the "and return" statement so that only one render is being called at a time.
my list.html.erb also have a render call. I have tried to return from there as well but it didn't help.

These kind of errors happens when you try to render or redirect multiple times inside a method, check the followings
1) if your build_list calling from another method and does it has a redirect too.
def another_method
#code
build_list(query_string)
redirect_to root_url
end
2) does your methods, query_tasks and schema2tasklist has define redirects/renders inside them

Related

<AbstractController::DoubleRenderError in controller

I'm getting this error, I tried adding a redirect_to() and return to my access_doc_or_redirect() method, but no luck. Any recommendations?
def access_doc_or_redirect(doc_id, msg)
doc = Document.find(params[:id])
if doc.user_access?(current_user)
#document = doc
else
flash[:alert] = msg
redirect_to root_url and return
end
end
def get
access_doc_or_redirect(params[:id], "Sorry, no document view access.")
redirect_to #document.file.url
end
Error
access_doc_or_redirect(params[:id], "Sorry, no document view access" 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".
AbstractController::DoubleRenderError: Render and/or redirect were called multiple times in this action.
Error is self descriptive you are calling render or redirect multiple times in your action. Lets look at your methods:
def access_doc_or_redirect(doc_id, msg)
doc = Document.find(params[:id])
if doc.user_access?(current_user)
#document = doc
#this block will run fine and return #document to get method
else
flash[:alert] = msg
redirect_to root_url and return
#this block is giving you trouble because you are redirecting to root url and then control goes back to your get method where you are using redirect again and hence double render error
end
end
FIX:
If you are using it as a filter then to fix error you can do:
def get
#i think this is your main method so you should use redirect or render inside this method only
#instance variables set inside access_doc_or_redirect will automatically be available inside this method
if #document
redirect_to #document.file.url
else
flash[:alert] = "Sorry, no document view access."
redirect_to root_url
end
end
def access_doc_or_redirect
#doc = Document.find(params[:id])
if #doc.user_access?(current_user)
#document = doc
end
end

how to call javascript functions from the controller in rails

I'm trying to call a javascript function (actually coffeescript) from a controller in a Rails 3.2 app.
I'm getting a Render and/or redirect were called multiple times in this action error.
My code looks like this:
#Model.controller
def index
#models = Model.all
my_action if current_user.name == "Bob" #or some other general conditional
...and some stuff
respond_to do |format|
format.html
format.js #this is needed to handle ajaxified pagination
end
end
def my_action
respond_to do |format|
format.js { render :js => "my_function();" } #this is the second time format.js has been called in this controller!
end
end
#functions.js.coffee.erb
window.my_function = ->
i = xy
return something_amazing
What is the correct way to call a js function from the controller?
Man, you missed argument for block. Primary mistake.
def my_action
#respond_to do # This line should be
respond_to do |format|
format.js { render :js => "my_function();" }
end
end
And MrYoshiji's point is right. But your error was on server side, had not reached client side yet.
For the style, I think that's okay if the js code is one function call only. If more JS code, it's better to render js template
# controller
format.js
# app/views/my_controller/my_action.js.erb
my_function();
// and some more functions.
Update: How to fix double rendering problem
You must have your #index return if condition met, or the method will continue to execute and cause rendering twice or more. Fix it like this:
def index
#models = Model.all
if current_user.name == "Bob"
return my_action
else
# ...and some stuff
respond_to do |format|
format.html
format.js #this is needed to handle ajaxified pagination
end
end

Redirect_to and render with return

def confirm_invite_new_tutor
redirect_with_msg = false
#game_school = GameSchool.find(params[:id])
existing_user_emails = params[:all_emails][:existing_user] || []
new_users = params[:param_game_school][:game_school_invites_attributes]
if existing_user_emails.present?
existing_user_emails.each do |existing_user|
// some code
end
redirect_with_msg = true
end
if new_users.present?
if #game_school.update_attributes(params[:param_game_school])
redirect_with_msg = true
else
render :invite_tutor_form
end
end
if redirect_with_msg
redirect_to #game_school, notice: "daw"
else
redirect_to #game_school
end
end
If I am executing this, I am getting error as
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".
If I use return Its taking me to some other page, and even the flash msg is not shown.
How to fix this?
everytime you use render or redirect in a controller, no part of the remaining code should have a render or redirect unless it's sure that it won't be passed. using your code
if new_users.present?
if #game_school.update_attributes(params[:param_game_school])
redirect_with_msg = true
else
render :invite_tutor_form
end
end
if validation fails when you update the attributes, you're running render :invite_tutor_form. But the code will keep on running the next part of the code which is
if redirect_with_msg
redirect_to #game_school, notice: "daw"
else
redirect_to #game_school
end
so you get that error. The simplest solution is to add a return after the call to render
if new_users.present?
if #game_school.update_attributes(params[:param_game_school])
redirect_with_msg = true
else
render :invite_tutor_form
return
end
end
Please do note that when you're doing more processing (like updating other attributes, or sending emails) after the if block that contains return, those part of the code will not be executed.
add justand return at the end of each redirect_to or render like below
`redirect_to #game_school and return`
This will work for you

AbstractController::DoubleRenderError that shouldn't be

I've been getting the following error when I hit this destroy method in a my User controller.
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".):
It's a strange one, because I honestly am only responding once to the call.
Here's my action:
def destroy
user = User.find(params[:id])
if user.has_role_for? current_client
# then we remove the role
user.has_no_roles_for! current_client
# was that the users only role?
if user.roles.count == 0
user.destroy
end
respond_with head :ok
else
respond_with({:error=>'unauthorised'}, :status => :forbidden)
end
end
Any ideas?
Try adding " and return" after the respond_with lines:
respond_with head :ok and return
respond_with({:error=>'unauthorised'}, :status => :forbidden) and return
head(:ok) doesn't return something you can respond_with. head :ok renders a 200 with no body. respond_with renders via the responder some representation of the object you passed into it. head calls render, respond_with calls render, hence the double render error.
You should change that line to just head :ok.

render (and redirect_to) should somehow terminate the processing of an action?

def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
render :action => show
end
render :template => "fix_user_errors"
end
The previous code will generate an error (because render is called twice) in the case where update_attributes succeeds.
The act of calling render (and redirect_to) should somehow terminate the processing of an action?But its not why?
render doesn't actually terminate the processing of the action.
You need to add an else to your if statement:
if #user.update_attributes(params[:user])
render :action => show
else
render :template => "fix_user_errors"
end
I think you can also use "return render ..." which will return immediately from the action method but this might have unintended consequences.
No, calling render does not end your action. render is a method to tell your controller which template is going to render if you do not want the default one, not to actually tell it you are done processing.
You might want to call return after you call render, if you are actually done.
Also, calling redirect (I am guessing this, I am not sure) actually sends a Location header to your browser, but does not end your action. You need to return or branch too after calling it, so you do not call it twice.
You can use the else, doesnt really has sense to render an action and render another. I would write like this:
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
redirect_to :action => show
else
render :template => "fix_user_errors" #probably you want to render the edit template here.
end
end

Resources