i get a AbstractController::DoubleRenderError in TicketsController#update.
If i select a particular user, the update is not happening.
def update
#selected_group = Group.find_by_id(params[:Department]) unless params[:Department].nil?
#selected_company = Company.find_by_id(params[:Company]) unless params[:Company].nil?
#ticketnote_content = params[:Ticketnote]
if ((#selected_group != nil) && (#selected_company != nil))
map_group_to_department
map_user_to_staff
update_ticket
if (#response['response'] == "Failed")
flash[:error] = response['err_desc']
redirect_to "/ticket/#{params[:id]}/edit"
return
elsif (#response['response'] == "Success")
#ticketnote_content
if #ticketnote_content != ""
add_note_to_ticket
end
map_assets_findings_tickets
flash[:notice] = "Succesfully updated the ticket"
TicketHistory.create_ticket_history(#assigned_user,#selected_asset,#ticket_params,current_user,#updated_ticket_response,"Updated")
end
else
flash[:error] = "Company or department can't be blank."
redirect_to "/ticket/#{params[:id]}/edit"
return
end
redirect_to :controller => 'tickets' , :action => 'show', :id => params[:id],:test_id => #test,:ticket_id=> params[:ticket_id]
end
As you have already used redirect_to within your if else statement and after execution of if else you are redirecting again, which lead this error(you can use only once within each action). In order to resolve this, I would suggest following solutions(the question was not clear, so I may not be right):
Solution 1: If your last redirect_to is not required then delete it, i.e.
redirect_to :controller => 'tickets' , :action => 'show', :id => params[:id],:test_id => #test,:ticket_id=> params[:ticket_id]
Solution 2: Update with and return in every redirect_to and moving you last redirect_to in your successful response condition(I'm not sure where you want your Ticket#show) , i.e.
def update
#selected_group = Group.find_by_id(params[:Department]) unless params[:Department].nil?
#selected_company = Company.find_by_id(params[:Company]) unless params[:Company].nil?
#ticketnote_content = params[:Ticketnote]
if #selected_group && #selected_company
map_group_to_department
map_user_to_staff
update_ticket
if (#response['response'] == "Failed")
flash[:error] = response['err_desc']
redirect_to "/ticket/#{params[:id]}/edit"
elsif (#response['response'] == "Success")
add_note_to_ticket if #ticketnote_content != ""
map_assets_findings_tickets
flash[:notice] = "Succesfully updated the ticket"
TicketHistory.create_ticket_history(#assigned_user,#selected_asset,#ticket_params,current_user,#updated_ticket_response,"Updated")
redirect_to :controller => 'tickets' , :action => 'show', :id => params[:id],:test_id => #test,:ticket_id=> params[:ticket_id]
end
else
flash[:error] = "Company or department can't be blank."
redirect_to "/ticket/#{params[:id]}/edit" and return
end
end
P.S.: You can use redirect_to and flash[:message] in one line:
redirect_to your_path(params), :notice => "your message"
Related
i have login page with 2 sessions client and admin so when client logged in i do redirect to complete the form and when admin logged in i redirect him to dashboard, the problem is :
ActionController::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".)
def login
#institute = Configuration.find_by_config_key("LogoName")
available_login_authes = FedenaPlugin::AVAILABLE_MODULES.select{|m| m[:name].classify.constantize.respond_to?("login_hook")}
selected_login_hook = available_login_authes.first if available_login_authes.count>=1
if selected_login_hook
authenticated_user = selected_login_hook[:name].classify.constantize.send("login_hook",self)
else
if request.post? and params[:user]
#user = User.new(params[:user])
user = User.find_by_username #user.username
if user.present? and User.authenticate?(#user.username, #user.password)
authenticated_user = user
end
end
end
if authenticated_user.present?
successful_user_login(authenticated_user) and return
elsif authenticated_user.blank? and request.post?
flash[:notice] = "#{t('login_error_message')}"
end
end
private
def successful_user_login(user)
session[:user_id] = user.id
flash[:notice] = "#{t('welcome')}, #{user.first_name} #{user.last_name}!"
redirect_to session[:back_url] || {:controller => 'user', :action => 'dashboard'}
if user.client
redirect_to session[:back_url] || {:controller => 'client', :action => 'complete_registration'}
end
end
end
You said right redirect_to is not a return method, the codes above is executed too. In you successful_user_login if user is client, you are calling redirect_to twice, so you can refactor this method to:
if user.client
redirect_to session[:back_url] || {:controller => 'client', :action => 'complete_registration'}
else
redirect_to session[:back_url] || {:controller => 'user', :action => 'dashboard'}
end
ActionController::DoubleRenderError is a error thrown by Ruby on Rails when a controller action tries to render or redirect a response twice. In your code, the action attempts to redirect the user to both 'user/dashboard' and 'client/complete_registration' depending on the user's status as a client. This will result in a DoubleRenderError. Notice that rendering or redirecting do not returns from the method.
Here are some untested code examples with different approaches:
You can calculate the controller and the action before calling redirect_to:
def successful_user_login(user)
session[:user_id] = user.id
flash[:notice] = "#{t('welcome')}, #{user.first_name} #{user.last_name}!"
controller, action = if user.client
["client", "complete_registration"]
else
["user", "dashboard"]
end
redirect_to session[:back_url] || {controller: controller, action: action}
end
You can also do an if and return after first redirect_to:
def successful_user_login(user)
session[:user_id] = user.id
flash[:notice] = "#{t('welcome')}, #{user.first_name} #{user.last_name}!"
if user.client
redirect_to session[:back_url] || {:controller => 'client', :action => 'complete_registration'}
return
end
redirect_to session[:back_url] || {:controller => 'user', :action => 'dashboard'}
end
Or do an if else:
def successful_user_login(user)
session[:user_id] = user.id
flash[:notice] = "#{t('welcome')}, #{user.first_name} #{user.last_name}!"
if user.client
redirect_to session[:back_url] || {:controller => 'client', :action => 'complete_registration'}
else
redirect_to session[:back_url] || {:controller => 'user', :action => 'dashboard'}
end
end
Here, I'm defining a recipient by the params.
What if I want to send the message to all the users who has confirmed already at once?
How can I write?
Anyone has any idea?
controller
recipient = User.find_by_username(params[:messages][:recipient])
if recipient.confirmed_at.nil?
redirect_to messages_sent_path
flash[:notice] = "This user hasn't confirmed yet!"
return
end
params[:messages][:subject] = 'no subject' if params[:messages][:subject].blank?
subject = params[:messages][:subject]
body = params[:messages][:body]
if current_user != recipient
current_user.send_message(recipient, body, subject)
redirect_to :controller => 'messages', :action => 'sent'
flash[:notice] = "Sent!"
else
redirect_to :controller => 'messages', :action => 'received'
flash[:notice] = "Cannot send to yourself!"
end
If you're using mysql / sqlite3
users = User.where('confirmed_at IS NOT NULL')
users.each do |user|
current_user.send_message(user, body, subject)
end
I have such code in controller:
if verify_recaptcha #verify_recaptcha(:model => #order, :message => "Oh! It's error with reCAPTCHA!") &&
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
OrderMailer.order_confirmation(#order, #user).deliver
UserOrderMailer.user_order_mailer(#order, #user).deliver
#OrderNotifier.received(#order).deliver
pdf_link = generate_pdf(#order)
link = " #{I18n.t(:get_pdf)}"
format.html { redirect_to root_url, :notice => (I18n.t(:successful_order_send)+link.to_s).html_safe}
else
format.html { render :action => "new", :notice => I18n.t(:error) }
format.xml { render :xml => #order.errors, :status => :unprocessable_entity }
end
end
else
flash[:warning] = I18n.t(:wrong_captcha)
redirect_to :back
end
And in form view:
- if #user_vehicle.errors.messages.values.present?
.warning
- #user_vehicle.errors.messages.values.each do |msg|
- msg.each do |m|
%li= m
But also in layout i have:
- if flash[:warning]
.warning
= flash[:warning]
- if flash[:notice]
.notice
= flash[:notice]
I want to know, how can i append recaptcha fail error to errors.messages.values list of error's and display in same div and with li as i do for model validation messages?
How can i see as one more li item recaptcha message?
if verify_recaptcha
...
else
#user_vehicle.errors.add(:base, I18n.t(:wrong_captcha))
end
def restore_download_delete_file
begin
case params[:submit]
when "restore"
restore_status = restore_file(params[:file_names])
raise if restore_status != 0
flash[:notice] = "File Successfully Restored."
redirect_to :action => "database_settings"
when "download"
download_status = download_file(params[:file_names])
raise if download_status != 0
when "delete"
delete_status = delete_file(params[:file_names])
raise if delete_status != 0
flash[:notice] = "File Successfully Deleted."
redirect_to :action => "database_settings"
end
rescue Exception => e
flash[:error] = "Error with #{params[:submit]}! Please retry."
redirect_to :action => "database_settings"
end
end
How could I improve this method?
You can clean it up by dividing it into four: one for restore, one for delete, one for download, and one for calling the appropiate one and handling the exceptions.
def restore_download_delete_file
begin
self.send "#{params[:submit]}"
rescue Exception => e
flash[:error] = "Error with #{params[:submit]}! Please retry."
redirect_to :action => "database_settings"
end
end
def restore
restore_status = restore_file(params[:file_names])
raise if restore_status != 0
flash[:notice] = "File Successfully Restored."
redirect_to :action => "database_settings"
end
def download
download_status = download_file(params[:file_names])
raise if download_status != 0
end
def delete
delete_status = delete_file(params[:file_names])
raise if delete_status != 0
flash[:notice] = "File Successfully Deleted."
redirect_to :action => "database_settings"
end
Also, a couple considerations:
Raise proper exceptions, not nil.
Don't rescue all exceptions. Rescue the ones you are raising instead.
Try like this
begin
status = send("#{params[:submit]}_file", params[:file_names])
raise unless status == 0
if params[:submit] == 'restore' || params[:submit] == 'delete'
flash[:notice] = "File Successfully #{params[:submit].capitalize}d"
end
rescue Exception => e
flash[:error] = "Error with #{params[:submit]}! Please retry."
ensure
redirect_to :action => "database_settings" unless params[:submit] == 'download'
end
def restore_download_delete_file
submit = params[:submit]
if not restore_file(params[:file_names]).zero?
flash[:error] = "Error with #{submit}! Please retry."
elsif submit != "download"
flash[:notice] = "File Successfully #{submit.capitalize}d."
else
return
end
redirect_to :action => "database_settings"
end
You can always turn your mega-method into a little interpreter:
private
FILE_CMDS = {
'delete' => {
:action => lambda { |names| delete_file(names) },
:notice => 'File Successfully Deleted.',
:redirect => 'database_settings',
},
'download' => {
:action => lambda { |names| download_file(names) },
},
'restore' => {
:action => lamba { |names| restore_file(names) },
:notice => 'File Successfully Restored.',
:redirect => 'database_settings',
},
}
public
def restore_download_delete_file
begin
cmd = FILE_CMDS[params[:submit]]
status = cmd[:action].call(params[:file_names])
raise if(status != 0)
flash[:notice] = cmd[:notice] if(cmd[:notice])
redirect_to :action => cmd[:redirect] if(cmd[:redirect])
rescue Exception => e
flash[:error] = "Error with #{params[:submit]}! Please retry."
redirect_to :action => "database_settings"
end
end
But I think egarcia's approach makes the most sense; there's really
no need to mash all this stuff into one method. The commonalities
really are quite minimal so four methods in one controller makes
more sense: one action, one method. DRY is just a guideline, it isn't
dogma to be followed at all costs.
I am working with the following piece;
def index
#user = User.find(params[:id])
rescue
flash[:notice] = "ERROR"
redirect_to(:action => 'index')
else
flash[:notice] = "OK"
redirect_to(:action => 'index')
end
Now I either case whether I have a correct ID or not, I am always getting "OK" in my view, what am I doing wrong?
I need that when I have no ID in the DB to show "ERROR". I have also tried to use rescue ActiveRecord::RecordNotFound but same happens.
All help is appreciated.
All code after the end of the rescue block is interpreted only if there are no returns in the rescue block. So you can call return at the end of your rescue block.
def index
begin
#user = User.find(params[:id])
rescue
flash[:notice] = "ERROR"
redirect_to(:action => 'index')
return
end
flash[:notice] = "OK"
redirect_to(:action => 'index')
end
or
def index
#user = User.find(params[:id])
# after is interpret only if no exception before
flash[:notice] = "OK"
redirect_to(:action => 'index')
rescue
flash[:notice] = "ERROR"
redirect_to(:action => 'index')
end
But in your case the better is to use rescue_from or rescue_in_public
like
class UserController < ApplicationController
def rescue_in_public(exception)
flash[:notice] = "ERROR"
redirect_to(:action => 'index')
end
def index
#user = User.find(params[:id])
flash[:notice] = "OK"
redirect_to(:action => 'index')
end
end
But the using of rescue_in_public is not really good advice
Just an overall Rails Rescue answer:
I found this to be very cool:
#user = User.find(params[:id]) rescue ""
If there is no user with that id, then User.find will return nil. Returning nil is not an error case and will not trigger a rescue.