this works
---------------
def self.is_readable_by(user, object = nil)
true if user.eql?(object.author) || user.admin
end
instead of (manual, wiki of RESTful_ACL)
--------------------------------------------------------------
def self.is_readable_by(user, object = nil)
true if user.eql?(author) || user.admin
end
...is that a bug, or am I doing something wrong here?
can it be done easier?
hi,
first of all, from your code i understand that you have a class called
"object". This should really be avoided since there already is a class
called object (the ruby core class, that is), so you will actually
reopen the ruby object-class.
to your question: you have to specifiy the object either with
self.author or object.author. that's the only way as far as i know...
I don't see an indication of there being a class named "Object." Yes
there is a local variable named "object."
What I can't see from the code in the OP is what kind of object is
being passed into the method referred to by "object." If this is an
ActiveRecord object containing an association to an "Author" object
then you would need object.author. user.eql?(author) would be
attempting to refer to a local variable named "author" which doesn't
exist.
I'm also guessing that this method might be defined in an ActiveRecord
subclass and you are expecting to be able to access the "author"
method directly. If that's the case then you should realize that
"self.is_readable_by(...)" is a class method so you wouldn't want to
try to access an instance method such as the "author" association.
This is why an object instance is being passed into the class method.
I am also making the assumption that the object passed into "object"
has an association to an Author object, which appears to be the case
since your solution works.
I have to admit that Ruby's use of the "self" keyword to define class
methods feels a bit awkward to me. However, that's probably because I
learned Objective C before diving into Ruby. Objective C uses the
"self" keyword to mean "this instance" in a similar way as Java uses
the "this" keyword. It was just a matter of getting used to it.
I personally like the syntax of the Objective C language where you
would have something like this:
+ myClassMethod
{
// implementation
}
- myInstanceMethod
{
// implementation
}
Methods with plus signs are class methods, where methods with minus
signs are instance methods. This way to intent is explicit and clear.
Class and instance methods are treated with the same "respect" in a
way.
But, at the end of the day it's all just all semantics.
I personally like the syntax of the Objective C language where you
would have something like this:
+ myClassMethod
{
// implementation
}
- myInstanceMethod
{
// implementation
}
The Ruby use of self is a bit more complicated. It's closer to java
that it appears that you understand. It refer to the current object
in a similar way to java, it's just that when you are in the context
of a class definition, self happens to refer to the class that is
being defined. You could just as easily declare it this way if it's
easier to understand:
class MyClass
def MyClass.my_class_method
...
end
def self.my_other_class_method
...
end
end
The flexibility of self in Ruby permits some other useful things. For
example, look at how ActiveRecord spins up getters and setters for db-
backed attributes. It hooks method_missing and then uses
'self' (which in this context refers to the current instance) to as
the receiver for setter/getter definitions.
I think the confusion arises because the 'def self.bar' use of self
for declaring class methods is one of the most common uses.
The issue is that you're defining your method as a class method, not
an instance method; i.e, you should do
def is_readable_by(user)
not
def self.is_readable_by(user)
Just to clarify why RESTful_ACL defines the is_readable_by method as a
Class-level method...
This method is responsible for securing both object#index and
object#show. Since object#index operates on a set of objects, it needs
to be class level. On the other hand, since it also secures object#show
(one object), it needs to have access to a potential object, hence
(object = nil)
If you really want to grok this, read the chapter on 'self' in Ruby for Rails. The trippy things (for me) were realizing that 1) in addition to being blueprints for creating objects (instances), ruby classes are objects in their own right, and 2) class definitions are *executed*.
You can also play with this:
# =========================
puts("In open code: self is now #{self}")
def top_level_method
puts("In top_level_method: self is now #{self}")
end
top_level_method
class MyClass
puts("In MyClass: self is now #{self}")
def MyClass.my_class_method
puts("In MyClass.my_class_method: self is now #{self}")
end
def my_instance_method
puts("In my_instance_method: self is now #{self}")
end
end