Ruby: DRY class methods calling Singleton 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"
Calling a singleton method within the singleton class in Ruby?
You can define the default value as:
module MyModule
class << self
def process_item(item)
item.capitalize
end
def foo=(item)
@foo_ref=process_item(item)
end
def foo
@foo_ref ||= "initial foo"
end
end
end
What you were trying to do was to set foo to the singleton class, instead of setting foo to the class.
Retrieve a Ruby object from its singleton class?
I'm not aware of any built-in method or keyword but you could write a method that adds a (singleton) method to an object's singleton class, returning the object itself:
class Object
def define_instance_accessor(method_name = :instance)
singleton_class.define_singleton_method(method_name, &method(:itself))
end
end
Usage:
obj = Object.new #=> #<Object:0x00007ff58e8742f0>
obj.define_instance_accessor
obj.singleton_class.instance #=> #<Object:0x00007ff58e8742f0>
In your code:
class Example
PARENTS = []
PARENTS.define_instance_accessor
class << PARENTS
FATHER = :father
MOTHER = :mother
instance.push(FATHER, MOTHER)
end
end
Internally, YARV stores the object in an instance variable called __attached__
. The instance variable doesn't have the usual @
prefix, so it isn't visible or accessible from within Ruby.
Here's a little C extension to expose it:
#include <ruby.h>
static VALUE
instance_accessor(VALUE klass)
{
return rb_ivar_get(klass, rb_intern("__attached__"));
}
void Init_instance_accessor()
{
rb_define_method(rb_cClass, "instance", instance_accessor, 0);
}
Usage:
irb -r ./instance_accessor
> obj = Object.new
#=> #<Object:0x00007f94a11e1260>
> obj.singleton_class.instance
#=> #<Object:0x00007f94a11e1260>
>
How to programmatically remove singleton information on an instance to make it marshal?
You can define custom marshal_dump
and marshal_load
methods:
class X
def break_marshalling!
meta_class = class << self
self
end
meta_class.send(:define_method, :method_y) do
return
end
end
# This should return an array of instance variables
# needed to correctly restore any X instance. Assuming none is needed
def marshal_dump
[]
end
# This should define instance variables
# needed to correctly restore any X instance. Assuming none is needed
def marshal_load(_)
[]
end
end
# Works fine
restored_instance_of_x =
Marshal.load Marshal.dump(X.new.tap { |x| x.break_marshalling! })
# Does not work
restored_instance_of_x.method_y
If you want you can manage dynamic methods definitions via method_missing
:
class X
def method_missing(name, *args)
if name == :method_y
break_marshalling!
public_send name, *args
else
super
end
end
end
# Works fine
Marshal.load(Marshal.dump(X.new)).method_y
Singleton method vs. class method
Most of what happens in Ruby involves classes and modules, containing
definitions of instance methods
class C
def talk
puts "Hi!"
end
end
c = C.new
c.talk
Output: Hi!
But as you saw earlier (even earlier than you saw instance methods inside classes), you can also define singleton methods directly on individual objects:
obj = Object.new
def obj.talk
puts "Hi!"
end
obj.talk
#Output: Hi!
When you define a singleton method on a given object, only that object can call that method. As you’ve seen, the most common type of singleton method is the class method—a method added to a Class object on an individual basis:
class Car
def self.makes
%w{ Honda Ford Toyota Chevrolet Volvo }
end
end
But any object can have singleton methods added to it. The ability to define method- driven behavior on a per-object basis is one of the hallmarks of Ruby’s design.
Singleton classes
Singleton classes are anonymous: although they’re class objects (instances of the class Class ), they spring up automatically without being given a name. Nonetheless, you can open the class-definition body of a singleton class and add instance methods, class methods, and constants to it, as you would with a regular class.
Note:
Every object has two classes:
■ The class of which it’s an instance
■ Its singleton class
----------------------------------------------------------------
At Last I would highly recommends you to watch.
1: The Ruby Object Model and Metaprogramming For detail info about singleton method vs. class method ruby
2: MetaProgramming - Extending Ruby for Fun and Profit - by Dave Thomas
Hope this help you!!!
I want to add a singleton method with a closure to a Ruby object
You can define a method with a block using define_method
.
Example:
class Object
def eigenclass
class <<self; self end
end
end
a = "Hello"
other_word = "World"
a.eigenclass.class_eval do
define_method(:cliche) {"#{self} #{other_word}"}
end
a.cliche # => "Hello World"
"Goodbye".cliche # => NoMethodError: undefined method `cliche' for "Goodbye":String
Here is an implementation of a define_singleton_method
method:
class Object
def define_singleton_method(name, &block)
eigenclass = class<<self; self end
eigenclass.class_eval {define_method name, block}
end
end
Why can some classes and/or methods be called without instances of their parent class?
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object
class and hence seem to be globally available. Why? From any context Object
is always in the class hierarchy of self
and hence private methods on Object
are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class
class and may have singleton methods.
class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods are
class A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name)
as follows
str = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on Enumerable
) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again.
Related Topics
Calling Ruby Method Without Instantiating Class
Determining Method's Visibility on the Fly
How to Refer to a Submodule's "Full Path" in Ruby
Getting Hash with Symbol as Keys for Mongo in Rails
Regexp Search Through a Very Large File
Ruby 1.9 - No Such File to Load 'Win32/Open3'
How to Efficiently Extract Repeated Elements in a Ruby Array
How to Collapse Double Splat Arguments into Nothing
Using the Right Exception Subclass in Ruby
Openssl Causing Very Slow Rails Boot Time on Windows
How to Effectively Force Minitest to Run My Tests in Order
Ssl_Connect Syscall Returned=5 Errno=0 State=Sslv3 Read Server Hello a (Openssl::Ssl::Sslerror)
How to Get the Real File from S3 Using Carrierwave
Rewrite Template.Js.Erb into Template.Js.Slim
Uninitialized Constant Applicationrecord Error
Rails: Uninitialized Constant Just Happen on Production Server