Skip to content

Instantly share code, notes, and snippets.

@jits
Forked from docklandsstudios/Re-direct
Created May 31, 2011 17:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jits/1000971 to your computer and use it in GitHub Desktop.
Save jits/1000971 to your computer and use it in GitHub Desktop.
Redirect Issue
class ApplicationController < ActionController::Base
protect_from_forgery
rescue_from CanCan::AccessDenied do |exception|
flash[:alert] = exception.message
redirect_to root_url
end
protected
def stored_location_for(resource)
if current_user && (current_user.role?("admin") || current_user.role?("moderator"))
return admin_index_path # Make sure this route exists in your app!
end
super(resource)
end
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable, :lockable and :timeoutable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# New Sign Ups
attr_accessible :email, :password, :password_confirmation, :remember_me, :username
has_and_belongs_to_many :roles
has_many :articles
# ensures usernames are unique and included in sign-up
validates :username, :presence => true, :uniqueness => true
def role?(role)
return !!self.roles.find_by_name(role.to_s)
end
before_create :setup_role
private
def setup_role
if self.role_ids.empty?
self.role_ids = [3]
end
end
end
@docklandsstudios
Copy link

OK will do. This is my rake routes file where I got admin_index from:

admin_index GET /admin/index(.:format) {:controller=>"admin", :action=>"index"}

@jits
Copy link
Author

jits commented May 31, 2011

Also, I recommend you upgrade Devise to the latest v1.1.x (I think it's v1.1.9 at the moment). I wouldn't recommend upgrading to v1.2+ until you have it working with v1.1.x

@docklandsstudios
Copy link

I inserted the new code block and it logs me in okay, but brings me back to the index page as before - no errors.

Hmmmm, the re-direct in the routes.rb file is root :to => "articles#index". Can't figure this one?!

@docklandsstudios
Copy link

Upgraded to Devise 1.1.9 and no side effects that I can see :-)

@docklandsstudios
Copy link

Can my models/ability_model for User roles shed any light on this?

class Ability
include CanCan::Ability

def initialize(user)
user ||= User.new # guest user

if user.role? :Admin
  can :manage, :all
  can :publish, Article
elsif user.role? :Moderator
  can :read, [Article, Comment]
  can [:edit, :update], Comment
elsif user.role? :Member
   can :read, :all
   can :create, [Article, Comment]
   can [:edit, :update], Comment
end

end
end

@jits
Copy link
Author

jits commented May 31, 2011

The routes.rb file doesn't do any redirects. It just defines the routes available in your app.

The fact that it is logging you in tells me that it may be working.

Let's try this: add some debugging prints in the stored_location_for method:

def stored_location_for(resource)
  puts "*** Called stored_location_for ***"
  puts "*** current_user.role_id = #{current_user.role_id} ***"
  puts "*** current_user.role.name = #{current_user.role.name} ***"
  if current_user && (current_user.role?("admin") || current_user.role?("moderator"))
    admin_index_path    # Make sure this route exists in your app!
  end
  super(resource) 
end

Then log in again as an admin and send me the output you get in the console (where you ran rails server).

@jits
Copy link
Author

jits commented May 31, 2011

Great about the upgrade to 1.1.9 :)

The Ability model looks fine to me. It shouldn't affect the sign in procedure.

@jits
Copy link
Author

jits commented May 31, 2011

Ahhh, I think I missed out something!

The stored_location_for method should say return admin_index_path not just admin_index_path. Please try this.

I'll update the Gist and the StackOverflow answer.

@docklandsstudios
Copy link

This is the output:

Started GET "/" for 127.0.0.1 at Tue May 31 21:19:38 +0100 2011
Processing by ArticlesController#index as HTML
Article Load (0.8ms) SELECT "articles".* FROM "articles" WHERE (published = 't') ORDER BY Created_a
t DESC LIMIT 6 OFFSET 0
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 19)
User Load (0.3ms) SELECT "users".
FROM "users" WHERE "users"."id" = 7 LIMIT 1
Role Load (0.2ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles".id = "roles_use
rs".role_id WHERE "roles"."name" = 'Admin' AND ("roles_users".user_id = NULL ) LIMIT 1
Role Load (0.1ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles".id = "roles_use
rs".role_id WHERE "roles"."name" = 'Moderator' AND ("roles_users".user_id = NULL ) LIMIT 1
Role Load (0.1ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles".id = "roles_use
rs".role_id WHERE "roles"."name" = 'Member' AND ("roles_users".user_id = NULL ) LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 18)
CACHE (0.0ms) SELECT "users".
FROM "users" WHERE "users"."id" = 7 LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 17)
User Load (0.3ms) SELECT "users".
FROM "users" WHERE "users"."id" = 2 LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 16)
User Load (0.2ms) SELECT "users".
FROM "users" WHERE "users"."id" = 3 LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 14)
CACHE (0.0ms) SELECT "users".
FROM "users" WHERE "users"."id" = 2 LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 13)
CACHE (0.0ms) SELECT "users".
FROM "users" WHERE "users"."id" = 3 LIMIT 1
Rendered articles/_article.html.erb (140.9ms)
Tag Load (0.6ms) SELECT "tags".* FROM "tags" ORDER BY name
Rendered shared/_side.html.erb (98.2ms)
SQL (0.2ms) SELECT COUNT(*) FROM "articles" WHERE (published = 't')
Rendered layouts/_footer.html.erb (1.8ms)
Rendered layouts/_usernav.html.erb (1.3ms)
Rendered articles/index.html.erb within layouts/application (284.7ms)
Completed 200 OK in 303ms (Views: 288.2ms | ActiveRecord: 3.9ms)

Started GET "/users/sign_in" for 127.0.0.1 at Tue May 31 21:19:50 +0100 2011
Processing by Devise::SessionsController#new as HTML
Rendered devise/shared/_links.erb (1.3ms)
Rendered layouts/_usernav.html.erb (1.4ms)
Rendered devise/sessions/new.html.erb within layouts/application (11.3ms)
Completed 200 OK in 137ms (Views: 19.3ms | ActiveRecord: 0.0ms)
*** Called stored_location_for ***

Started POST "/users/sign_in" for 127.0.0.1 at Tue May 31 21:19:55 +0100 2011
Processing by Devise::SessionsController#create as HTML
Parameters: {"commit"=>"Sign In", "authenticity_token"=>"wVUe9SL63fJmH+zumPa+1wXHhi3kOcvu9TVyBTvSR4I
=", "utf8"=>"✓", "user"=>{"remember_me"=>"0", "password"=>"[FILTERED]", "email"=>""}}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = '' LIMIT 1
AREL (26.2ms) UPDATE "users" SET "last_sign_in_at" = '2011-05-31 20:17:05.619025', "current_sign_in
_at" = '2011-05-31 20:19:55.562572', "sign_in_count" = 133, "updated_at" = '2011-05-31 20:19:55.563103
' WHERE "users"."id" = 1
Completed in 121ms

NoMethodError (undefined method role_id' for #<User:0x105c09a08>): app/controllers/application_controller.rb:13:instored_location_for'

Rendered /opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.5/lib/action_dispatch/middleware/templates/r
escues/_trace.erb (0.9ms)
Rendered /opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.5/lib/action_dispatch/middleware/templates/r
escues/_request_and_response.erb (12.4ms)
Rendered /opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.5/lib/action_dispatch/middleware/templates/r
escues/diagnostics.erb within rescues/layout (17.9ms)

@jits
Copy link
Author

jits commented May 31, 2011

OK, thanks. You can remove the 3 puts statements now

@docklandsstudios
Copy link

Just added the updated code which included the return admin_index_path and it directs to the index page with no errors.

@jits
Copy link
Author

jits commented May 31, 2011

So it works now?

@docklandsstudios
Copy link

Sorry - I meant it directs me to the home index page as a 'normal' user, so not working yet.

I tried 'return articles_new_path' as I know this exists and it has no effect either - so its something that is/is not happening before it gets to the redirect function?

@jits
Copy link
Author

jits commented May 31, 2011 via email

@docklandsstudios
Copy link

Have checked the user roles and their permission levels - normal users cannot delete articles and admins can, and they are correct

@jits
Copy link
Author

jits commented May 31, 2011

OK. And are you sure the user that you are logging in with is definitely an admin? You can check this in your rails console with the following:

u = User.find(admin_user_id)    # admin_user_id should be the ID of the user you are logging in as
u.role? "admin"

@docklandsstudios
Copy link

I changed my own user ID from [1] to [3] and logged in and lost all my 'delete' privileges.

Then I changed it back to [1] and my delete articles ability was back - so I'm confident they are set up correctly.

So its somewhere between the permissions and the re-direct that is the issue?

@jits
Copy link
Author

jits commented May 31, 2011

I would think so. Something is not going right in this line:

if current_user && (current_user.role?("admin") || current_user.role?("moderator"))

But to verify this, please could you add puts "\n*** current_user is an admin or moderator ****\n" inside the if block to see if it actually goes inside it.

@docklandsstudios
Copy link

Insert like this?

def stored_location_for(resource)
puts "\n*** current_user is an admin or moderator ****\n"
return articles_new_path # Make sure this route exists in your app!
end
super(resource)
end

It throws up this error:

Started GET "/" for 127.0.0.1 at Tue May 31 23:19:33 +0100 2011

ActionController::RoutingError (super called outside of method):
app/controllers/application_controller.rb:15
app/controllers/articles_controller.rb:1

Rendered /opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.5/lib/action_dispatch/middleware/t
emplates/rescues/routing_error.erb within rescues/layout (0.7ms)

@jits
Copy link
Author

jits commented Jun 1, 2011

No! Insert it into the if block, like this:

def stored_location_for(resource)
  if current_user && (current_user.role?("admin") || current_user.role?("moderator"))
    puts "\n*** current_user is an admin or moderator ****\n"
    return admin_index_path    # Make sure this route exists in your app!
  end
  super(resource) 
end

You should really know enough Ruby to realise that what you did above just wouldn't run! :)

@docklandsstudios
Copy link

You're right - am putting that one down to it being a long day !

I appreciate your help with this - the application is here www.worrybin.ie to give it some context

This is the log from that code block - could this be an issue with CanCan?

Started GET "/users/sign_in" for 127.0.0.1 at Wed Jun 01 09:42:20 +0100 2011
Processing by Devise::SessionsController#new as HTML
Rendered devise/shared/_links.erb (1.2ms)
Rendered layouts/_usernav.html.erb (1.3ms)
Rendered devise/sessions/new.html.erb within layouts/application (10.5ms)
Completed 200 OK in 35ms (Views: 18.0ms | ActiveRecord: 0.0ms)

Started POST "/users/sign_in" for 127.0.0.1 at Wed Jun 01 09:42:27 +0100 2011
Processing by Devise::SessionsController#create as HTML
Parameters: {"commit"=>"Sign In", "authenticity_token"=>"WM3a3u51jcl/CGAK/pXwW+W2qXsmyvdty
WSqBAAXXa8=", "utf8"=>"✓", "user"=>{"remember_me"=>"0", "password"=>"[FILTERED]", "email"=>"
"}}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'ubique18@yahoo.i
e' LIMIT 1
AREL (0.3ms) UPDATE "users" SET "updated_at" = '2011-06-01 08:42:28.065559', "sign_in_cou
nt" = 146, "last_sign_in_at" = '2011-06-01 08:41:49.931388', "current_sign_in_at" = '2011-06
-01 08:42:28.065027' WHERE "users"."id" = 1
Role Load (0.2ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles".id =
"roles_users".role_id WHERE "roles"."name" = 'admin' AND ("roles_users".user_id = 1 ) LIMIT
1
Role Load (0.2ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles".id =
"roles_users".role_id WHERE "roles"."name" = 'moderator' AND ("roles_users".user_id = 1 ) LI
MIT 1
Redirected to http://localhost:3000/
Completed 302 Found in 102ms

Started GET "/" for 127.0.0.1 at Wed Jun 01 09:42:28 +0100 2011
Processing by ArticlesController#index as HTML
Article Load (0.8ms) SELECT "articles".* FROM "articles" WHERE (published = 't') ORDER BY
Created_at DESC LIMIT 6 OFFSET 0
SQL (0.3ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 19)
User Load (0.2ms) SELECT "users".
FROM "users" WHERE "users"."id" = 7 LIMIT 1
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Role Load (0.2ms) SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles".id =
"roles_users".role_id WHERE "roles"."name" = 'Admin' AND ("roles_users".user_id = 1 ) LIMIT
1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 18)
CACHE (0.0ms) SELECT "users".
FROM "users" WHERE "users"."id" = 7 LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 17)
User Load (0.2ms) SELECT "users".
FROM "users" WHERE "users"."id" = 2 LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 16)
User Load (0.2ms) SELECT "users".
FROM "users" WHERE "users"."id" = 3 LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 14)
CACHE (0.0ms) SELECT "users".
FROM "users" WHERE "users"."id" = 2 LIMIT 1
SQL (0.2ms) SELECT COUNT() FROM "comments" WHERE ("comments".article_id = 13)
CACHE (0.0ms) SELECT "users".
FROM "users" WHERE "users"."id" = 3 LIMIT 1
Rendered articles/_article.html.erb (146.5ms)
Tag Load (0.6ms) SELECT "tags".* FROM "tags" ORDER BY name
Rendered shared/_side.html.erb (98.1ms)
SQL (0.2ms) SELECT COUNT(*) FROM "articles" WHERE (published = 't')
Rendered layouts/_footer.html.erb (1.7ms)
Rendered layouts/_usernav.html.erb (1.6ms)
Rendered articles/index.html.erb within layouts/application (277.9ms)
Completed 200 OK in 297ms (Views: 281.6ms | ActiveRecord: 4.9ms)

@jits
Copy link
Author

jits commented Jun 1, 2011

Hmmm... puzzling. Looks like the if block is not being reached at all (ie: it's not recognising the user as an admin nor moderator). Please could you start a rails console (rails c) and type in the following and send me the output:

u = User.find(admin_user_id)    # admin_user_id should be the ID of the user you are logging in as
u.role? "admin"
u.role? "moderator"

@docklandsstudios
Copy link

Okay, now this really is puzzling...

I am neither an Admin, Moderator or Member but I have sign In and full editing/delete permissions.

Other users who are members don't have these permissions on the website.

irb(main):007:0> u=User.find(1)
=> #<User id: 1, email: "ubique18@yahoo.ie", encrypted_password: "$2a$10$baHUTj.NoPuNRAhGQwH
LeOJBEUQOZsQ8mkyMWKJkuwvh...", password_salt: "$2a$10$baHUTj.NoPuNRAhGQwHLeO", reset_passwor
d_token: "i-CKyGNKXcbJnopYTVbi", remember_token: nil, remember_created_at: nil, sign_in_coun
t: 151, current_sign_in_at: "2011-06-01 09:30:57", last_sign_in_at: "2011-06-01 09:30:13", c
urrent_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2011-05-03 11:38:
06", updated_at: "2011-06-01 09:30:57", username: "Fenster">
irb(main):008:0> u.role? "admin"
=> false
irb(main):009:0> u.role? "moderator"
=> false
irb(main):010:0> u.role? "author"
=> false
irb(main):011:0> u.role? "member"
=> false

models/ability.rb

class Ability
include CanCan::Ability

def initialize(user)
user ||= User.new # guest user

if user.role? :Admin
  can :manage, :all
  can :publish, Article
elsif user.role? :Moderator
  can :read, [Article, Comment]
  can [:edit, :update], Comment
elsif user.role? :Member
   can :read, :all
   can :create, [Article, Comment]
   can [:edit, :update], Comment
end

end
end

/models/user.rb

def role?(role)
return !!self.roles.find_by_name(role.to_s)
end

default role for new users as authors

before_create :setup_role
private
def setup_role
if self.role_ids.empty?
self.role_ids = [3]
end
end

@jits
Copy link
Author

jits commented Jun 1, 2011

In Rails Console, try:

u = User.find(admin_user_id)    # admin_user_id should be the ID of the user you are logging in as
u.role? :Admin
u.role? :Moderator

Also, what database are you using? MySQL? Postgres?

@docklandsstudios
Copy link

Good spot!

I'm using SQLite3 in Aptana Studio 3 dev.env

irb(main):002:0> u.role? :Admin
=> true
irb(main):003:0> u.role? :Moderator
=> false
irb(main):004:0>

@jits
Copy link
Author

jits commented Jun 1, 2011

Ah ha! Then it's to do with the case sensitivity... d'oh!

Does it all work as you'd like now?

If so, please do mark up my answer on StackOverflow and also mark it as the correct answer :)

@docklandsstudios
Copy link

Legend... well done, it works perfectly and I tested it with both the Admin and Member!

If you were up for a challenge, I just need to get this Atom feed working and the project is finished!?

http://stackoverflow.com/questions/6179512/rails-3-help-with-atom-feed

@jits
Copy link
Author

jits commented Jun 1, 2011

Ace!

Did my answer here - http://stackoverflow.com/questions/6175928/rails-3-atom-feed-problem/6176888#6176888 - not help with this problem?

@jits
Copy link
Author

jits commented Jun 1, 2011

@docklandsstudios
Copy link

Thanks - I added your other suggestion alright, but still having an issue with it!

You know, I've followed 4 different tutorials from this ATOM feed and none of them have worked for me... might start blogging when this is finished lol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment