Difference between 'self.method_name' and 'class self' in Ruby
The class << self
notation opens up the eigenclass of an object. An eigenclass is an anonymous class that stores instance-specific behaviour. In the case of a class an eigenclass is sometimes called a metaclass.
Ruby uses eigenclasses to implement so called 'class methods' (also called static methods).
A Class (as moritz stated) is also an Object in Ruby and in so far as it is an object it also has a class. The class of a class in Ruby is called Class
.
A 'class method' in any language is a method in which a class is the receiver - that is the method is directly invoked on the class itself.
However in order for a method to be invoked on a receiver that method must be defined on the class of that receiver. In the case of classes a 'class method' could be implemented as an instance method on the Class
class.
But defining an instance method on Class
would mean that ALL classes get access to that class method which is not ideal.
Enter the eigenclass, as stated before, the eigenclass for an object is a special class that stores the methods unique to that object. In the case of classes the eigenclass subclasses the Class
class and is the direct class of the class.
'class methods' in Ruby therefore are just 'instance methods' defined on the class's eigenclass.
The def MyClass.my_method
notation actually defines my_method
on the eigenclass of MyClass. If you use this notation you can get by (for a while) without actually understanding eigenclasses since you can trick yourself into thinking it is just Ruby's way of defining 'static methods' and continue thinking Ruby's class model is similar to Java's. However, the class << self
notation allows no such interpretation and you must come to terms with the reality of eigenclasses.
In summary, 'class methods' are actually 'instance methods' defined on the eigenclass and the class << self
gives you access to the eigenclass.
For more reading check out these links:
http://banisterfiend.wordpress.com/2008/11/25/a-complete-ruby-class-diagram/
http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/
http://www.klankboomklang.com/2007/09/21/the-singleton-class/
class self vs self.method with Ruby: what's better?
class << self
is good at keeping all of your class methods in the same block. If methods are being added in def self.method
form then there's no guarantee (other than convention and wishful thinking) that there won't be an extra class method tucked away later in the file.
def self.method
is good at explicitly stating that a method is a class method, whereas with class << self
you have to go and find the container yourself.
Which of these is more important to you is a subjective decision, and also depends on things like how many other people are working on the code and what their preferences are.
What does `def self.function` name mean?
Contrary to other languages, Ruby has no class methods, but it has singleton methods attached to a particular object.
cat = String.new("cat")
def cat.speak
'miaow'
end
cat.speak #=> "miaow"
cat.singleton_methods #=> ["speak"]
def cat.speak
creates a singleton method attached to the object cat.
When you write class A
, it is equivalent to A = Class.new
:
A = Class.new
def A.speak
"I'm class A"
end
A.speak #=> "I'm class A"
A.singleton_methods #=> ["speak"]
def A.speak
creates a singleton method attached to the object A. We call it a class method of class A.
When you write
class A
def self.c_method
'in A#c_method'
end
end
you create an instance of Class
(*). Inside the class definition, Ruby sets self to this new instance of Class, which has been assigned to the constant A. Thus def self.c_method
is equivalent to def cat.speak
, that is to say you define a singleton method attached to the object self, which is currently the class A.
Now the class A has two singleton methods, that we commonly call class methods.
A.singleton_methods
=> ["c_method", "speak"]
(*) technically, in this case where A
has already been created by A = Class.new
, class A
reopens the existing class. That's why we have two singleton methods at the end. But in the usual case where it is the first definition of a class, it means Class.new
.
what does class self mean in Rails?
That is the same as
class Post < ActiveRecord::Base
def self.search(q)
# Class Level Method
# search from DB
end
def search2(qq)
# Instance Level Method
# search from DB
end
end
Class methods work on the class (e.g. Post), instance methods works on instances of that class (e.g. Post.new)
Some people like the class << self; code; end;
way because it keeps all class level methods in a nice block and in one place.
Others like to prefix each method with self.
to explicitly know that is a class method not an instance method. It's a matter of style and how you code. If you put all class methods in a block like class << self
, and this block is long enough, the class << self
line might be out of your editor view making it difficult to know that you are in the class instance block.
On the other hand, prefixing each method with self.
and intermixing those with instance methods is also a bad idea, how do you know all the class methods while reading your code.
Pick an idiom which you prefer for your own code base but if you work on an open source project or you collaborate on someone else's code, use their code formatting rule.
Trying to understand use of self.method_name vs. Classname.method_name in Ruby
def before_create
self.hashed_password = User.hash_password(self.password)
end
In this example, User.hash_password
calls the hash_password
method on the class User
, whereas self.hashed_password=
calls the hashed_password=
method on this particular instance of User
.
If you replace User.hash_password
with self.hash_password
, Ruby would complain with a NoMethodError
, because no instance method by the name of hash_password
exists in the class User
. You could replace it with self.class.hash_password
, though.
If you replace self.hashed_password=
with simply hashed_password=
, Ruby would create a local variable named hashed_password
, rather than call the instance method hashed_password=
. You need to explicitly add self
if you want to call attribute writers.
The self
in the method definition (def self.hash_password
) makes hash_password
a class method instead of an instance method. In this context, self
refers to the class. In the context of an instance method, self
refers to an instance.
Using self in modules
The difference is that first example defines module method called preview
, and second example defines mixin method preview
.
So that if you include first module into a class, you'll be able to call this method on the class (whereas calling the method on the class instance would cause the error), while including the second module into the class will allow you to call the method on class' instances, but calling the method on the class itself will cause
NoMethodError: undefined method preview for Foo:Class
Regarding conflicts basing on the same method name in class and module included to it. Answer to this question lays in Ruby method lookup, which is following:
- Methods from the object's singleton/meta/eigen class
- Methods from prepended modules (Ruby 2.0+ feature)
- Methods from the object's class
- Methods from included modules
- Methods from the class hierarchy (superclass and its ancestors)
Method lookup stops, when the method is found.
With prepend
the mixin method will have precedence in method lookup;
With include
method defined in class has the precedence in method lookup.
So no conflicts are possible.
def self.methodName vs def methodName
Assuming User
model
Instance methods
def methodName
#do something
end
to call this method use
User.new.methodName
Class Methods
def self.methodName #OR User.methodName
#do something
end
to call this method use
User.methodName
Yield in class self in class method
It's a little bit weird, but OK if you are exploring Ruby.
class Person
puts "evaluating Person's body ..."
def self.mega_methods
puts 'in Person#self.mega_methods, about to yield ...'
yield
end
end
class Tom < Person
puts "evaluating Tom's body ..."
print 'Tom.singleton_methods : '; p Tom.singleton_methods
mega_methods do
puts 'in Tom, about to define self.hiya!'
def self.hiya!
puts 'hiYA!'
end
end
print 'Tom.singleton_methods : '; p Tom.singleton_methods
end
Tom.hiya!
Execution :
$ ruby -w t.rb
evaluating Person's body ...
evaluating Tom's body ...
Tom.singleton_methods : ["mega_methods"]
in Person#self.mega_methods, about to yield ...
in Tom, about to define self.hiya!
Tom.singleton_methods : ["mega_methods", "hiya!"]
hiYA!
Note that the exclamation point in the name of a method is, by convention, reserved for destroying methods, such as String#sub!
which modifies the receiver string.
See also What does def `self.function` name mean?
It's all about self !
class Person2
def self.mega_methods
print 'in Person2 self='; p self
class << self
print 'in class << self self='; p self
yield
end
end
end
class Tom2 < Person2
mega_methods do
puts "in Tom2, about to define self.hiya! for self=#{self}"
def self.hiya!
puts 'hiYA!'
end
def hi
puts 'hi'
end
end
end
print 'Tom2.singleton_methods : '; p Tom2.singleton_methods
print 'Tom2.instance_methods : '; p Tom2.instance_methods(false)
Tom2.hiya!
Tom2.new.hi
Execution :
$ ruby -w t2.rb
in Person2 self=Tom2
in class << self self=#<Class:Tom2>
in Tom2, about to define self.hiya! for self=Tom2
Tom2.singleton_methods : ["mega_methods", "hiya!"]
Tom2.instance_methods : ["hi"]
hiYA!
hi
How to create a private class method?
private
doesn't seem to work if you are defining a method on an explicit object (in your case self
). You can use private_class_method
to define class methods as private (or like you described).
class Person
def self.get_name
persons_name
end
def self.persons_name
"Sam"
end
private_class_method :persons_name
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
Alternatively (in ruby 2.1+), since a method definition returns a symbol of the method name, you can also use this as follows:
class Person
def self.get_name
persons_name
end
private_class_method def self.persons_name
"Sam"
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
Related Topics
Why Pg::Uniqueviolation: Error: Duplicate Key Value Violates Unique Constraint
How to Track Down a Memory Leak in My Ruby Code
Creating Routes with an Optional Path Prefix
Best Ruby Idiom for "Nil or Zero"
When to Use a Lambda in Ruby on Rails
Difference Between Plugins and Ruby Gems
Getting Only New Mail from an Imap Server
Count Number of Days Between Two Dates
How to Return Something Early from a Block
How to Check If a Class Is Defined
How to Sort a String's Characters Alphabetically
How to Add a New Action to the Existing Controller
What's the Best Way to Talk to a Database While Using Sinatra
Suppressing the Output of a Command Run Using 'System' Method While Running It in a Ruby Script