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.
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/
What is the 'self' keyword doing exactly in this Class method?
self
is the class Restaurant
. def self.method
is how you implement a method on the class itself rather than an instance of the class. Restaurant.filter_by_city(...)
rather than Restaurant.new.filter_by_city(...)
.
self
changes in Ruby depending on context. Within a method, self
is the object the method was called on.
Within the class Restaurant
block, and outside of any method, self
is the Restaurant
object which is a Class object. Everything is an object in Ruby. Everything.
You can also do this by declaring a block where the class is the instance.
class << self
def filter_by_city(restaurants, city)
restaurants.select { |restaurant| restaurant.city == city }
end
end
Normally you'd use this syntax if you have a lot of class methods.
See Self in Ruby: A Comprehensive Overview for more.
Getting class name and method name in Ruby
Something like this should work:
class Foo
def self.bar
puts "I want to print #{self} and #{__method__}."
end
end
If it was not a class method you'd need to use self.class
instead.
Why can I change the method name when I call a setter method from a class?
Here's the StackOverflow link where 'mu is too short' answers this:
Ruby setter method syntax method=(value) - Comparison to Java
When you add two numbers, for example
4 + 4
This is what's going on
4.send(:+, 4)
The send method just invokes a method. The first argument is the method you want to call passed in as a symbol :+
and the second argument is the argument you want to pass into the method 4
In your case
mike.age = 20
is actually this
mike.send(:age=, 20)
Here, we are calling the age=
method and passing in 20
as the argument to age=
Heres the link to the Ruby docs about the send method https://ruby-doc.org/core-2.6.4/Object.html#method-i-send
ELI5: Why can you call class methods within class methods without explicitly stating the class itself? (Ruby/Rails)
Whenever you call a method, Ruby first checks to see if it's defined on self
. There is only one exception to this that I know of - if you have a local variable with the same name as the method, it will reference the local variable instead:
def num; 1; end
num = 2
num # => 2
Class methods are the same as instance methods in this regard.
It's easier to think of the cases where you can't omit the self:
When using a setter method e.g.
self.foo = "bar"
it's required because Ruby needs to know you're not trying to just set a local variable (asfoo = "bar"
would):class Test
attr_writer :foo
def initialize
self.foo = 1 # calls the setter method
foo = 2 # creates a local variable
end
endWhen there's ambiguity between a local variable and a method (both have the same name) and you want to call the method:
class Foo
def self.a; 1; end
def self.b
a = 2
a # references local variable
self.a # calls method
a() # can also call the method by writing out parens (removes ambiguity)
end
endWhen
self
is not what you want it to be in that scope.class Foo
def self; a; 1
end
a # obviously doesn't work, it isn't defined here
Foo.a # worksWhen the method name is the same as a reserved word (e.g.
class
)def class_name
class.name # syntax error, it thinks you want to define a class
self.class.name # works
end
Class Method to 'Know' Class Name in Ruby?
A Class Method is a method where the CLASS is the receiver, so to find the object upon which the method is invoked (what you appear to be trying to do here) simply inspect the value of self
.
class Parent
def self.whoami
self
end
end
class Child < Parent
end
puts Parent.whoami #=> Parent
puts Child.whoami #=> Child
How to define class name method like Integer() and when should I use it?
Integer
is a Kernel
method. In fact, it is defined as Kernel.Integer
.
You can simply create a new method that acts as initializer for your custom class:
class Foo
def initialize(arg)
@arg = arg
end
end
def Foo(arg)
Foo.new(arg)
end
Foo("hello")
# => #<Foo:0x007fa7140a0e20 @arg="hello">
However, you should avoid to pollute the main namespace with such methods. Integer
(and a few others) exists because the Integer
class has no initializer.
Integer.new(1)
# => NoMethodError: undefined method `new' for Integer:Class
Integer
can be considered a factory method: it attempts to convert the input into an Integer, and returns the most appropriate concrete class:
Integer(1).class
# => Fixnum
Integer(1000 ** 1000).class
# => Bignum
Unless you have a real reason to create a similar initializer, I'd just avoid it. You can easily create static methods attached to your class that converts the input into an instance.
Related Topics
Rspec Any_Instance Deprecation: How to Fix It
Installing Nokogiri MAC Os X 10.8.2 Xcode Installed
Are There Any Good Mutation Testing Tools for Ruby 1.9 and Rspec2
Get Jekyll Configuration Inside Plugin
Wicked-Pdf Not Showing Images, 'Wicked_Pdf_Image_Tag' Undefined
How to Sort Not Simple Hash (Hash of Hashes)
How to Make the Url's in Ruby on Rails Seo Friendly Knowing a @Vendor.Name
Running Phantomjs from a Ruby on Rails Application
Does Begin . . . End While Denote a 'Block'
Omniauth Facebook Expired Token Error
C1 or C2 Coverage Tool for Ruby
Why Doesn't Module.Method_Defined(:Method) Work Correctly
Ruby on Rails: Conditionally Display a Partial
Sunspot_Rails Gem - " Errno:: Econnrefused (Connection Refused - Connect (2)) "