<AbstractController::DoubleRenderError in controller - ruby-on-rails

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

Related

DoubleRenderError in Controller

before_action :set_blacklisted_nfts, only: %i[blacklisted_nfts]
def blacklisted_nfts
if #blacklisted_nft.present?
redirect_to destroy and return
end
end
def destroy
success = false
message = 'Unable to delete NFT!'
if !current_user.admin?
message = 'This action require admin privileges!'
elsif #nft.destroy
success = true
message = 'NFT deleted successfully!'
end
render layout: false, locals: {
type: success ? 'success' : 'error',
message: message,
nft_id: #nft.id
}
end
private
def set_blacklisted_nfts
#blacklisted_nft = BlacklistedNft.create(contract_address: #nft.contract_address, contract_type: #nft.contract_type, token_id: #nft.token_id, chain: #nft.chain)
end
can anyone guide me where is an issue am having this error:
Error: 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".
Where you have redirect_to destroy that's actually calling the destroy method. You might be trying to redirect to the destroy method, but it's calling it directly.
You can't actually redirect to anything other than another "GET" action, the redirect just responds back to the browser with a URI and the browser just calls a GET on it, you can't have a POST or DELETE or any other http method (aka: http verb).
Probably instead in that condition, you just want to do a #blacklisted_nft.destroy and then redirect_to :back, notice: "Deleted #blacklisted_nft.name" or something.

Can't overwrite the active admin default redirect path

I am using active admin in my application. In my controller, I have an action update with redirect_to function. But while updating, it threw me an error.
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 terminates execution of the action, so if you want to exit an action after redirecting, you need to do something like redirect_to(...) and return.
def update
#user = User.find(params[:id])
#user.update
mailers.notify(#user).deliver
redirect_to user_path(#user)
end
I tried
only redirect_to
redirect_to() and return
but nothing works.
before_filter :only =>[:create,:update] do
if self.action_name.to_sym == :create
#user = User.new(params[:user])
else
#user = User.find(params[:id])
end
I fix it by adding this to my update action .This works for me fine.
def update
update!do |format|
format.html { redirect_to_user_path(#user)}
end
What is your purpose? Why you use mailers.notify(#user).deliver inside the update action?
Move the notification to after_update filter in your User model, smth like this:
after_update :send_notifications
def send_notifications
Mailer.notify(self).deliver
end
Change the update method to smth like this:
def update
super do |format|
redirect_to user_path(#user), notice: "Your notice message" and return if resource.valid?
end
end

Print to console when method is called?

I want to print a message to the browser console or to the page so I can see exactly when each method is called. Nothing is being printed and I haven't found a working solution. I tried using flash messages but it didn't work as well. I'm learning Rails so I want to see exactly what is being called and when. For example if create was called I want to see a message "Create was called!". I have tried this:
class PostsController < ApplicationController
# only index, show, new, and edit pages will have views
# create, update, and destroy will do some kind of work and then redirect
# instance variables are visible in our view files
def index
#posts = Post.all
end
def show
# find the post and find the id that was passed into the url
#post = Post.find(params[:id])
flash[:success] = "SHOW WAS CALLED IN FLASH"
puts "SHOW METHOD WAS CALLED!"
end
def new
#post = Post.new
end
def create
#post = Post.new(params[:post])
if #post.save
redirect_to(posts_path, :notice => "Your post was saved!")
else
render "new"
end
end
def edit
puts "<p>EDIT METHOD WAS CALLED!</p>"
#post = Post.find(params[:id])
end
def update
puts "UPDATE METHOD WAS CALLED!"
#post = Post.find(params[:id])
if #post.update_attributes(params[:post])
redirect_to posts_path, :notice => "Your post has been saved."
else
render "edit"
end
end
def destroy
puts "DESTROY METHOD WAS CALLED!"
#post = Post.find(params[:id])
#post.destroy
redirect_to(posts_path, :notice => "Post deleted")
end
end
Use logger for this and tail log/development.log
logger.debug "Method was called"
debug level logging will only be logged in development environment. use info if you want to log in production
Using puts in the controller action won't print it on the web page in the browser. It will be printed in the terminal where your server is running in case you are using Webrick.
If you want to print it on the webpage, you need to do so in the view corresponding to the action like this:
In show.html.erb write:
SHOW METHOD WAS CALLED!
You can log the statements in the log files using Rails.logger in the action.
Rails.logger.info "SHOW METHOD WAS CALLED!"
This will be written to the development.log/production.log file depending on which environment your application is running.

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

I am getting DoublerenderError

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

Resources