authorization recipe help

Hello all, I am following the rails recipe book for authorization and it works as written. I have created a controller that will be administrate accounts and want to show each user with all their roles. I can't seem to get the roles to match up. This is my logic 1. query RolesUsers (passing in the userid)

    privs= RolesUsers.get_roles(userid)

2 get the name of the role from Roles passing in the role_id received from step one

my problem is that I see this when I puts the result of step one

#<RolesUsers role_id: 1, user_id: 1>

I am still new to ruby and a little confused as to what I am seeing. it appears to be a class object, but from what I am use to seeing, it is missing the @ in front of role_id and user_id.

I get an error if I do this, privs.role_id

any clue what is happening? Thanks -Juan

Hi,

Lets step from here :

privs= RolesUsers.get_roles(userid)

what your "get_roles(userid)" is going to RolesUsers Active Record or Model? if yes, can you paste here your def get_roles(any), so we can understand well your problem.

This is what I have, if there is a better way, I would be happy to see it. Thanks

class RolesUsers < ActiveRecord::Base   def self.get_roles(userid)     find(:all, :conditions => ["user_id = ?", userid])   end

end

Hello,

class RolesUsers < ActiveRecord::Base   def self.get_roles(userid)     find(:all, :conditions => ["user_id = ?", userid])   end

You use find :all, so that the result of your searching will be formed as array. you can not run privs.role_id. First let we count how many array is there using :

@size = privs.size

example you got 1

you execute like this privs[0].role_id or to see all list of role_id you can use like it:

for kungfu in privs    print kungfu.role_id end

remember the ways below looks like the same but having difference result :

[First] @fighter = WorldFigther.find(1)

and

[Second] @fighter = WorldFigther.find(:all, :conditions => ["id = ?", 1])

To get fighter name of the First is @fighter.name, but the second is @fighter[0].name

I hope you can understand clearly, your problem is.

it makes Perfect sense now!! thank you!

@Juan,

You're working your way into the infamous N+1 db problem... I believe that the recipe has a User model like this:

class User   has_and_belongs_to_may :roles   ... end

To collect all the roles, you should rely on the association that you have defined:

@current_user = ... (User.find(session[:userid] iirc) @roles = @current_user.roles

@roles.each do |role|   puts role.name end

this is fantastic, could you explain what you mean by the infamous N+1 db problem? I will be the first to admit I am not well versed in db lingo, is this a performance measure? I would like to learn as much as possible from this mistake, so that I don't repeat it in the future. thanks again for the help. -Juan

What is the meaning of infamous N+1 db problem? sorry i am not good in db analyst and design.

N+1...

Assume the user has N roles. If you grab the user it will take 1 db round trip followed by N more to retrieve each of the roles for a total of N+1 round trips. db access is likely to be one of the most costly aspects of your application so you want to eliminate that as much as possible.

Enter the has_many :through => xxx and has_and_belongs_to_many (the latter is out of favor since the former permits you a full model that may contain extra state information about the join -- like a subscription class that joins a customer to his periodical but also tells you whether the customer is paid up). If/when you have one of these specified you can access the associated models through the named association and Rails will automatically do a join for you. So....

class User   has_many :user_roles   has_many :roles, :through=>:user_roles   ... end

user = User.find(..., :include=>:roles)

The above find will trigger a left outer join so that you collect the user and ALL of his associated roles in ONE db roundtrip.