named_scopes

Hey all,

I'm learning rails and am trying to put together a generic ACL check for all models. I've been able to sucessfully implement it as a method for all models by decorating ActiveRecord::Base. But when I try to do the "rails way" of creating an association (and thereby taking advantage of the ORM), I don't get very far...

Here is the code:

class ActiveRecord::Base

  has_many(:permissions)   named_scope(:acl_check, lambda do |user_id, method|     {       :include => :permission,       :conditions => [         ["permissions.user_id=?", user_id],         ["permissions.method=?", method],         ["permissions.classname=?", self.class.name]       ]     }   end)

  # Conducts a permission check for the entire class.   def self.check_acl(user_id, method)

    # Perform the permission check by User.     permission_check = Permission.find_by_user_id_and_instance_id_and_classname_and_method (user_id, nil, self.class.name, method)     if(permission_check)       # If the row exists, we generate a hit.       return(true)     end

    # Perform the permission check by Role.

    # Otherwise, the permissions check was a miss.     return(false)

  end

  # Conducts a permission check for the current instance.   def check_acl?(user_id, method)

    # Perform the permission check by User.     permission_check = Permission.find_by_user_id_and_instance_id_and_classname_and_method (user_id, self.id, self.class.name, method)     if(permission_check)       # If the row exists, we generate a hit.       return(true)     end

    # Perform the permission check by Role.

    # Otherwise, the permissions check was a miss.     return(false)

  end

end

Currently, calling check_acl on either an instance of a model or the model class itself functions as expected. But attempting to call acl_check (my named_scope), just results in a method not found.

At the very least I'd like to know why this isn't working and if at all possible, I'd like to hear some ideas on how I can make this work. I've heard about using modules, but I'd like to not have to include a source file in each model. Ideally doing it the object- oriented way would make me happier :slight_smile:

But again, I'd love to hear details on why ActiveRecord isn't making this happen....

Currently, calling check_acl on either an instance of a model or the model class itself functions as expected. But attempting to call acl_check (my named_scope), just results in a method not found.

So you're trying to call a named scope on an instance of your model ? That won't work because named scopes aren't supposed to work that way. In a nutshell scopes are about narrowing down the results of a find (although they are also handy for adding other options to a find), eg Person.active scopes the find to those people with active=true. When you are just talking about a single object you have already loaded, scopes don't make a lot of sense.

A fairly standard way of doing this would be to add a class method to ActiveRecord::Base (eg acts_as_permissioned) and then calling that method would add required associations and so on, so a model which does use this stuff looks like

class Something < AR::Base   acts_as_permissioned end

(which at the end of the day is using modules and what not, but I find this a whole lot clearer than having stuff inserted into the base class. at least hear you have a clear statement at the top that this class is using the permissions stuff)

Fred

(ps you probably don't want self.class.name in your self.check_acl method, since this will always evaluate to 'Class' )