Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Devise current_user is undefined in a matches? advanced route constraint

I get an error NameError (undefined local variable or method "current_user" for #<APIRouter:0x007ffd54a81f98>): when I try to use current_user in a matches? constraint. I want certain dummy user to be routed to one set of controllers and other users to be routed to another set of controllers. However, when I try to use current_user I get an error.

  • devise (2.0.4)
  • rails (3.2.2)

My matches constraint is defined in the APIRouter Class:

class APIRouter
  def matches? request
    @use_rm_app = ENV["USE_RM_APP"] == "true" || (current_user && current_user.is_test)
  end
end

Any ideas as to how I can use current user in the matches? constraint as defined in the Rails guide.

Section from the routes.rb file:

#  Route to the rm_app controller if APIRouter says we should, otherwise use the real backend controllers.
match '/api/v1/*path', :controller => 'api/v1', 
  :action => 'handle_create_request', 
  :via => :post, :constraints => APIRouter.new

UPDATE: Solved thanks to ksol. Attempt 3 works. Get user using request.env["warden"].user(:user)

Solution is to modify the APIRouter

  def matches? request
    user = request.env["warden"].user(:user)
    (user && user.is_test) || ENV["USE_RM_APP"] == "true"
  end
like image 506
Pankaj Tyagi Avatar asked Sep 25 '12 18:09

Pankaj Tyagi


2 Answers

current_user is only available in your controllers and views. There is more than one way to achieve what you want, the easier being supplying it as a parameter to your method.

EDIT

if current_user if accessible in the router, you can pass it to your constraints class by doing constraints: APIRouter.new(current_user). Then you need to define APIRouter#initialize and store the current_user in an instance var that you can use in matches?.

EDIT 2

I just remembered devise allows you to do this in your router :

authenticated :user do
  root :to => "main#dashboard"
end

I don't know how to ensure that user.is_test though.

EDIT 3

Last attempt. request.env["warden"].user(:user) should give you a user if one is authenticated.

like image 168
ksol Avatar answered Sep 22 '22 13:09

ksol


Building on ksol's post, you can ensure user.is_test by passing a block to authenticated:

authenticated :user, lambda {|u| u.is_test } do
    // route stuff here
end

This is assuming that u.is_test returns a Boolean value.

like image 41
user2205763 Avatar answered Sep 25 '22 13:09

user2205763