Trying to Understand Use of Self.Method_Name VS. Classname.Method_Name in Ruby

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 (as foo = "bar" would):

    class Test
    attr_writer :foo
    def initialize
    self.foo = 1 # calls the setter method
    foo = 2 # creates a local variable
    end
    end
  • When 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
    end
  • When 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 # works
  • When 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



Leave a reply



Submit