Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails: url_for :back leads to NoMethodError for back_url

I'm trying to use url_for(:back) to create a redirect leading back to a previous page upon a user's logging in.

I've had it working successfully for when the user just goes to the login page on his or her own. However, when the user is redirected to the login page due to accessing a page requiring that the user be authenticated, the redirect sends the user back to the page before the one s/he had tried to access with insufficient permissions.

I'm trying to modify my login controller action to deal with the redirect properly. My plan is to have a query string parameter "redirect" that is used when a forced redirect occurs. In the controller, if that parameter exists that URL is used; otherwise, url_for(:back) is used, or if that doesn't work (due to lack of HTTP_REFERER), then the user is redirected to the site's home page.

Here is the code snippet which is supposed to implement this logic:

if params[:redirect]
  @url = params[:redirect]
else
  @url = url_for :back
  @url ||= url_for :controller => "home", :action => "index"
end

The error I get is:

NoMethodError in UsersController#login

undefined method `back_url' for #

RAILS_ROOT: [obscured]
Application Trace | Framework Trace | Full Trace

vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb:112:in `__send__'
vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb:112:in `polymorphic_url'
vendor/rails/actionpack/lib/action_controller/base.rb:628:in `url_for'
app/controllers/users_controller.rb:16:in `login'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:76:in `process'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:74:in `synchronize'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:74:in `process'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:in `process_client'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `each'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `process_client'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `initialize'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `new'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `initialize'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `new'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:282:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `each'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:128:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/command.rb:212:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:281

vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb:112:in `__send__'
vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb:112:in `polymorphic_url'
vendor/rails/actionpack/lib/action_controller/base.rb:628:in `url_for'
vendor/rails/actionpack/lib/action_controller/base.rb:1256:in `send'
vendor/rails/actionpack/lib/action_controller/base.rb:1256:in `perform_action_without_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:617:in `call_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:610:in `perform_action_without_benchmark'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
/usr/lib/ruby/1.8/benchmark.rb:293:in `measure'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
vendor/rails/actionpack/lib/action_controller/rescue.rb:136:in `perform_action_without_caching'
vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:13:in `perform_action'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
vendor/rails/activerecord/lib/active_record/query_cache.rb:8:in `cache'
vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:12:in `perform_action'
vendor/rails/actionpack/lib/action_controller/base.rb:524:in `send'
vendor/rails/actionpack/lib/action_controller/base.rb:524:in `process_without_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:606:in `process_without_session_management_support'
vendor/rails/actionpack/lib/action_controller/session_management.rb:134:in `process'
vendor/rails/actionpack/lib/action_controller/base.rb:392:in `process'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:184:in `handle_request'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:112:in `dispatch_unlocked'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:125:in `dispatch'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:124:in `synchronize'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:124:in `dispatch'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:134:in `dispatch_cgi'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:41:in `dispatch'
vendor/rails/activesupport/lib/active_support/dependencies.rb:142:in `load_without_new_constant_marking'
vendor/rails/activesupport/lib/active_support/dependencies.rb:142:in `load'
vendor/rails/activesupport/lib/active_support/dependencies.rb:521:in `new_constants_in'
vendor/rails/activesupport/lib/active_support/dependencies.rb:142:in `load'
vendor/rails/railties/lib/commands/servers/mongrel.rb:64
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
vendor/rails/activesupport/lib/active_support/dependencies.rb:153:in `require'
vendor/rails/activesupport/lib/active_support/dependencies.rb:521:in `new_constants_in'
vendor/rails/activesupport/lib/active_support/dependencies.rb:153:in `require'
vendor/rails/railties/lib/commands/server.rb:49
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
script/server:3

vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb:112:in `__send__'
vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb:112:in `polymorphic_url'
vendor/rails/actionpack/lib/action_controller/base.rb:628:in `url_for'
app/controllers/users_controller.rb:16:in `login'
vendor/rails/actionpack/lib/action_controller/base.rb:1256:in `send'
vendor/rails/actionpack/lib/action_controller/base.rb:1256:in `perform_action_without_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:617:in `call_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:610:in `perform_action_without_benchmark'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
/usr/lib/ruby/1.8/benchmark.rb:293:in `measure'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
vendor/rails/actionpack/lib/action_controller/rescue.rb:136:in `perform_action_without_caching'
vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:13:in `perform_action'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
vendor/rails/activerecord/lib/active_record/query_cache.rb:8:in `cache'
vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:12:in `perform_action'
vendor/rails/actionpack/lib/action_controller/base.rb:524:in `send'
vendor/rails/actionpack/lib/action_controller/base.rb:524:in `process_without_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:606:in `process_without_session_management_support'
vendor/rails/actionpack/lib/action_controller/session_management.rb:134:in `process'
vendor/rails/actionpack/lib/action_controller/base.rb:392:in `process'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:184:in `handle_request'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:112:in `dispatch_unlocked'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:125:in `dispatch'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:124:in `synchronize'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:124:in `dispatch'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:134:in `dispatch_cgi'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:41:in `dispatch'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:76:in `process'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:74:in `synchronize'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/rails.rb:74:in `process'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:in `process_client'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `each'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `process_client'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `initialize'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `new'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `initialize'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `new'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:282:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `each'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/configurator.rb:281:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:128:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/command.rb:212:in `run'
/var/lib/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:281
vendor/rails/activesupport/lib/active_support/dependencies.rb:142:in `load_without_new_constant_marking'
vendor/rails/activesupport/lib/active_support/dependencies.rb:142:in `load'
vendor/rails/activesupport/lib/active_support/dependencies.rb:521:in `new_constants_in'
vendor/rails/activesupport/lib/active_support/dependencies.rb:142:in `load'
vendor/rails/railties/lib/commands/servers/mongrel.rb:64
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
vendor/rails/activesupport/lib/active_support/dependencies.rb:153:in `require'
vendor/rails/activesupport/lib/active_support/dependencies.rb:521:in `new_constants_in'
vendor/rails/activesupport/lib/active_support/dependencies.rb:153:in `require'
vendor/rails/railties/lib/commands/server.rb:49
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
script/server:3

Request

Parameters:

None

Show session dump

--- 
:user: 
:csrf_id: 2927cca61bbbe97218362b5bcdb74c0f
flash: !map:ActionController::Flash::FlashHash {}


Response

Headers:

{"Content-Type"=>"",
 "cookie"=>[],
 "Cache-Control"=>"no-cache"}

Bear in mind that I had it working earlier-- url_for(:back) knew how to operate properly before I added this logic.

Thanks in advance for any ideas!

like image 206
Platinum Azure Avatar asked May 26 '10 01:05

Platinum Azure


2 Answers

You are trying to use a view helper method in your controller. The behavour you expect resides in ActionView::Helpers::UrlHelper, but the method you are calling is in ActionController::Base. Unfortunately, both methods are named the same and have very similar functions, but not exactly the same.

For a quick fix, ActionController::Base sets a @template variable which has access to all the ActionView helpers. Try calling url_for from that object, like this:

if params[:redirect]
  @url = params[:redirect]
else
  @url = @template.url_for :back
  @url ||= url_for :controller => "home", :action => "index"
end

I'm not sure that's the "right" way to do it, however. If the rails developers wanted us to use the @template variable all willy-nilly, they'd advertise it more.

Another way to get the URL to the original referrer (the :back you're looking for) is by using the request method:

if params[:redirect]
  @url = params[:redirect]
else
  @url = request.env["HTTP_REFERER"]
  @url ||= url_for :controller => "home", :action => "index"
end
like image 71
irkenInvader Avatar answered Nov 15 '22 05:11

irkenInvader


In my case, sometimes :back points to same place I want to leave so a loop occurs. My solution was: Method in application_controller

def new_loc
  url = request.referer.to_s
  url == "" || url == request.url ? root_path : url
end

and in your controller

@url = params[:redirect] ? params[:redirect] : new_loc

Or in my case

redirect_to new_loc

That's it. I am on Rails 5

like image 23
Fer Padron Avatar answered Nov 15 '22 05:11

Fer Padron