Alle sabato 24 marzo 2007, zig ha scritto:
class methods.
In the rails scaffolding, the code calls Modelname.columns. So it’s
calling the class method, and the class has not been instantiated.
Help de-confuse me! How does this class method get away with
referencing an instance variable and where exactly does this instance
variable get initialized? (I can’t find any occurrences of @columns
outside of other class methods, so it’s apparently not being
initialized anywhere in this class?)
Thanks in advance,
zig
I don’t know rails at all, so I may be completely wrong. Classes (in
this case
the class ActiveRecord::Base) are themselves instances of the class
Class
(try writing ActiveRecord::Base.is_a?(Class): it returns true), so they
can
have instance variables, too (here I’m not referring to instance
variables of
instances of the class, i.e of instances of ActiveRecord::Base, but to
instance variables of the class ActiveRecord::Base itself). Instance
variables of a class can be created whenever self is the class, usually
in
the definition of the class or in a class method. Instance variables of
the
class can used in class methods of that class, which actually are simply
singleton instance methods of the class.
To make this explaination a bit more clear, here’s a simple example
(comments
refer to the line of code above them:
class MyClass
Here, we’re creating an instance of class Class and storing it in a
constant
called MyClass
def method_1
Here, we’re defining an instance method, i.e a method which can be
called
on instances of class MyClass (for example, on the object returned by
MyClass.new
@var=1
Here, we create an instance variable. Since self is an instance of
MyClass, this is an instance variable of an instance of MyClass
puts “This is method_1”
end
@cls_var=2
Now, self is MyClass, so @cls_var is an instance variable of the
class
itself. It can’t be called by instances of MyClass
def MyClass.cls_method_1
Here, we’re defining a class variable, i.e a singleton method of
MyClass.
(Note that the syntax is the same used for defining a singleton
method in
other circumstances)
puts “This is cls_method_1”
puts “@cls_var is #{@cls_var}”
Here, self is MyClass, so we can access its instance variables
end
class << self
This idiom is used to access an object’s singleton class (in this
case,
MyClass’s singleton class. From now until the corresponding end,
MyClass will behave as an instance of the current class
def cls_method_2
Here we’re defining an instance method. Since the instance of the
current
class is MyClass, this is a class method for MyClass
puts “This is MyClass.cls_method_2”
puts “@cls_var is #{@cls_var}”
Here, we show again that we can access the instance variable of the
class
end
end
Here, we exit the singleton class
def method_2
We define a new instance method for MyClass (this will be called on
instances of MyClass
puts “This is method_2”
puts “@cls_var is #{@cls_var.inspect}”
Here we can’t access instance variables of MyClass, and we see it
(inspect is used to display nil instead of an empty string)
end
end
Some tests on the above:
MyClass.cls_method_1
=> This is MyClass.cls_method_1
@cls_var is 2
MyClass.cls_method_2
=> This is MyClass.cls_method_2
@cls_var is 2
MyClass.new.method_1
=> This is method_1
MyClass.new.method_2
=> This is method_2
@cls_var is nil
I hope this helps (and doesn’t create additional confusion). Sorry for
the
length of the post.
Stefano