What does self mean in Ruby? [duplicate] - ruby

This question already has answers here:
Ruby Definition of Self
(3 answers)
Closed 7 years ago.
What does ruby self represent? what is it? what does it mean? Could some please explain it to me? in simple terms please
And what is its function in a class?
class MyClass
def method.self
end
end

self refers to the object that is currently in context.
In your example, self is the class itself and def self.method is defining a class method. For example:
class MyClass
def self.method
puts "Hello!"
end
end
> MyClass.method
#=> "Hello"
You can also use self on instances of a class.
class MyClass
def method_a
puts "Hello!"
end
def method_b
self.method_a
end
end
> m = MyClass.new
> m.method_b
#=> "Hello!"
In this case, self refers to the instance of MyClass.
There is a good blog post on self in Ruby here, or, as it was pointed out in the comments, there is some more on this in the Ruby documentation.

Related

Ruby: DRY class methods calling Singleton instance methods [duplicate]

This question already has answers here:
Calling a method of a Ruby Singleton without the reference of 'instance'
(5 answers)
Closed 7 years ago.
I have the a Singleton class ExchangeRegistry which keeps all the Exchange objects.
Instead of needing to call:
ExchangeRegistry.instance.exchanges
I want to be able to use:
ExchangeRegistry.exchanges
This works, but I'm not happy with the repetition:
require 'singleton'
# Ensure an Exchange is only created once
class ExchangeRegistry
include Singleton
# Class Methods ###### Here be duplication and dragons
def self.exchanges
instance.exchanges
end
def self.get(exchange)
instance.get(exchange)
end
# Instance Methods
attr_reader :exchanges
def initialize
#exchanges = {} # Stores every Exchange created
end
def get(exchange)
#exchanges[Exchange.to_sym exchange] ||= Exchange.create(exchange)
end
end
I'm not happy with the duplication in the class methods.
I've tried using Forwardable and SimpleDelegator but can't seem to get this to DRY out. (Most examples out there are not for class methods but for instance methods)
The forwardable module will do this. Since you are forwarding class methods, you have to open up the eigenclass and define the forwarding there:
require 'forwardable'
require 'singleton'
class Foo
include Singleton
class << self
extend Forwardable
def_delegators :instance, :foo, :bar
end
def foo
'foo'
end
def bar
'bar'
end
end
p Foo.foo # => "foo"
p Foo.bar # => "bar"
The accepted answer is clever, but seems needlessly complex (not to mention to performance penalty of method_missing.
The usual way to solve this is to just assign the instance to a constant.
class ExchangeRegistrySingleton
include Singleton
# ...
end
ExchangeRegistry = ExchangeRegistrySingleton.instance
You can take advantage of method_missing hook and delegate the method calls to instance.
require 'singleton'
class ExchangeRegistry
include Singleton
# Missing methods will be delegated to `instance` if an implementation is available.
# Else `NoMethodError` will be raised via call to `super`
def self.method_missing method_name, *args
if instance.respond_to? method_name
puts "** Defining new method: '#{method_name}'"
(class << self; self; end).instance_eval do
define_method(method_name) do |*args|
instance.send(method_name, *args)
end
end
instance.send(method_name, *args)
else
super
end
end
attr_reader :exchanges
def initialize
#exchanges = {} # Stores every Exchange created
end
def get(exchange)
#exchanges[Exchange.to_sym exchange] ||= Exchange.create(exchange)
end
end
# By default, there is no class method - `exchanges`
p ExchangeRegistry.singleton_methods.grep(/exchanges/)
#=> []
p ExchangeRegistry.exchanges
#=> ** Defining new method: 'exchanges'
#=> {}
# After first call to `exchanges`, a new class method is now available
# Future calls will not hit `method_missing` again.
p ExchangeRegistry.singleton_methods.grep(/exchanges/)
#=> [:exchanges]
p ExchangeRegistry.exchanges
#=> {}
Another answer of this question indicates that there is performance penalty for handling method_missing. Hence, I have updated the answer to define the class method when first time a method_missing is reported. The update is based on article: Dynamically create class methods in Ruby

What does "self" mean in a module? [duplicate]

This question already has answers here:
Ruby self in layman terms?
(3 answers)
Closed 7 years ago.
What is the difference between:
module Math
def self.square(num)
num**2
end
end
puts Math.square(6)
and
module Math
def square(num)
num**2
end
end
puts Math.square(6)
What is "self" in the first example? I'm only used to using self inside of a class, where self refers to the instance of the class.
Well, let’s see:
module Foo
p self
end
# prints: Foo
So self is the module itself. This allows us to define methods directly on Foo, rather than instances of it:
module Foo
def self.bar
42
end
end
Foo.bar #=> 42
class A; include Foo; end
A.new.respond_to?(:bar) #=> false
Note that this is not unique to Modules, and is the same for Classes. And since self == Foo, nothing is stopping us from doing:
def Foo.baz
3.14
end
Foo.baz #=> 3.14

Ruby: class << self; def method VS. def self.method [duplicate]

This question already has answers here:
class << self vs self.method with Ruby: what's better?
(6 answers)
Closed 8 years ago.
My understanding is that:
class Example
class << self
def my_method; end
end
end
is equivalent to:
class Example
def self.my_method; end
end
but is that correct?
They are equivalent, but choose the latter for clarity reasons. When you have a class that is many lines long you may miss the class method definition when using class << self.
Another good reason to use class << self is when you need accessors on the class level:
class Foo
class << self
attr_accessor :bar
end
end
Beware that this is often not what you want as it is not thread safe. But that's a design problem. If you need it, you need it.
In the case of class << self all methods defined below will be class methods up until the class << self is closed. For a class method at a singular level or multiple ones if you wish you can define the method as self.foo.
class Test
def self.foo
end
def bar
end
end
class Test
class << self
def foo
end
end
def bar
end
end
In both of these cases you will end up with a class method "foo" and an instance method "bar". Both ways accomplish the same thing.

invoke methods which are elements of an array [duplicate]

This question already has answers here:
How to call methods dynamically based on their name? [duplicate]
(5 answers)
Closed 8 years ago.
class Shop
def self.name
"kids-toy"
end
def self.postcode
1000
end
end
methods = ["name", "postcode"]
methods.each {|m|
mcall = "Shop.#{m}"
eval mcall
}
Is there any other way rather than calling eval to invoke methods which are elements of an array?
Using Object#send:
methods.each { |m| Shop.send(m) }
Yes, possible using Method#call method :
class Shop
def self.name
"kids-toy"
end
def self.postcode
1000
end
end
methods = ["name", "postcode"]
methods.each do |m|
p Shop.method(m).call
end
# >> "kids-toy"
# >> 1000
Shop.method(m) will give you an object of the class Method, now you can invoke the method #call on that method object.

instance_eval vs class_eval in module

class Foo
include Module.new { class_eval "def lab; puts 'm' end" }
def lab
super
puts 'c'
end
end
Foo.new.lab #=> m c
========================================================================
class Foo
include Module.new { instance_eval "def lab; puts 'm' end" }
def lab
super
puts 'c'
end
end
Notice here I changed class_eval to instance_eval
Foo.new.lab rescue nil#=> no super class method lab
Foo.lab #=> undefined method lab for Foo class
So it seems that including the module neither defined an instance method nor a class method.
Any explanation what's going on here?
This code was tested on ruby 1.8.7 on mac.
First, think of what include does. it makes the instance methods of the module being included into instance methods on the including class. i.e. apart from the fact that your working example uses an anonymous module it is equivalent to:
module M1
def lab
puts 'm'
end
end
class Foo
include M1
def lab
super
puts 'c'
end
end
Next, think of what class_eval does. It evaluates the given code in the context of the class or module. i.e. it's exactly like you reopened the module and typed the code passed to class_eval. So MyModule = Module.new { class_eval "def lab; puts 'm' end" } is equivalent to
module MyModule
def lab
puts 'm'
end
end
Hopefully this explains the case that works.
When you use instance_eval you are evaluating the code within the context of the receiving object (in this case the instance of module) so MyMod2 = Module.new { instance_eval "def lab; puts 'm' end" } is equivalent to
module MyMod2
def MyMod2.lab
puts 'm'
end
end
i.e. it creates a module method which you'd call via MyMod2.lab and such methods are not added as instance methods by include.
Please note: this answer borrows a bit of its explanation from an answer I wrote to a previous question asking about instance_eval vs. class_eval relating to an example from The Ruby Programming Language book. You might find that answer helpful too.
including a module just takes the instance methods - you are looking for extend. luckily to get the best of both worlds, you can simply do:
module Something
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def blah
puts "lol"
end
end
end
class Test
include Something
end
irb:
>> Test.blah
lol
=> nil

Resources