Context: I am trying to put up a Decorator pattern in Ruby. As a Decorator should delegate all unknown methods to the underlying objects, I used the Delegator class.
I could have used SimpleDelegator but I wanted to fully understand what I was doing.
So the basic code I came out with was :
class Decorator < Delegator
def initialize(component)
super
#component = component
end
def __setobj__(o); #component = o end
def __getobj__; #component end
def send(s, *a); __send__(s, *a) end
end
Which is ~exactly the same as the implementation of SimpleDelegator. Seems good.
But the thing I did not want was for the code handling the Decorator to know it is manipulating a Decorator. I want full transparency.
At this moment Decorator.new(Object.new).class returned Decorator
So I tinkered a bit and came up with this :
class Decorator < Delegator
undef_method :==
undef_method :class
undef_method :instance_of?
# Stores the decorated object
def initialize(component)
super
#component = component
end
def __setobj__(o); #component = o end
def __getobj__; #component end
def send(s, *a); __send__(s, *a) end
end
This way, I can safely use class or instance_of? on my Decorated object, it will send the method to the underlying object via method_missing (which is implemented by Delegator).
The thing is : I don't understand why I had to undef :class and :instance_of?. I can see that BasicObject defines :== so I had to undefine it but what about those two ?
I looked at the BasicObject documentation and a bit in the C code but did not find anything. I looked the same at the Delegator documentation and code, and did not find anything either.
It seems Delegator include the Kernel module, but Kernel#class or Kernel#instance_of? don't exist.
Where those two method came from ? Why did I need to undefine them if they were not implemented at all ?
I guess I must be missing something about Ruby's object model or something.
Thanks.
You can get a hint by inspecting the method:
Decorator.instance_method(:class)
# => #<UnboundMethod: Decorator(#<Module:0x00000102137498>)#class>
The method's owner is Decorator but actually defined in #<Module:0x00000102137498>. So there is an anonymous module that defines it. Interesting... let's look at:
Decorator.ancestors
# => [Decorator, Delegator, #<Module:0x00000102137498>, BasicObject]
There's that module again, between Delegator and BasicObject. So Delegator doesn't directly derive from BasicObject. If you look at the source code in lib/delegate.rb you find:
class Delegator < BasicObject
kernel = ::Kernel.dup
kernel.class_eval do
[:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m|
undef_method m
end
end
include kernel
# ...
So a copy of the Kernel module is made, which doesn't have to_s, inspect, etc... but still has class and instance_of?. It's included in Delegator and that's where they come from.
Note that Object inherits the same methods by including the Kernel module (but it includes the full module, of course):
42.method(:class) # => #<Method: Fixnum(Kernel)#class>
This is stated in the Object doc:
Object mixes in the Kernel module, making the built-in kernel
functions globally accessible. Although the instance methods of Object
are defined by the Kernel module, we have chosen to document them here
for clarity.
Related
From Wikibooks' Ruby Programming/Overview:
When I said that every Ruby object has a class, I lied. The truth is, every object has two classes: a “regular” class and a singleton class. An object’s singleton class is a nameless class whose only instance is that object. Every object has its very own singleton class, created automatically along with the object. Singleton classes inherit from their object’s regular class and are initially empty, but you can open them up and add methods to them, which can then be called on the lone object belonging to them. This is Ruby’s secret trick to avoid “class methods” and keep its type system simple and elegant
The above passage says that Ruby's secret trick to avoid class methods. I don't understand what the author means here. Where is Ruby stopping us to avoid class methods? for an example, look at the example shown below
class Raj
def self.hi
puts 'Hi'
end
def hello
puts 'hello'
end
end
object=Raj.new
object.hello
Raj.hi
As you can see in the preceding example, the class methods can still be created.
yes?
I understand that there are no true class methods in Ruby; instead, they are methods that are created for the Raj object.
But, in any case, it's allowing me to create the method 'hi,' right?
So, what does it mean when it says, 'This is Ruby's secret trick for avoiding "class methods" and keeping its type system simple and elegant'?
I understand that there are no true class methods in Ruby; instead, they are methods that are created for the Raj object.
That's exactly it, though.
def self.hi
puts 'Hi'
end
This is not a class method or static method. Those don't exist in Ruby. That's the whole point. Your class Raj defines an object of type Class. We can see its type with the #class function.
> Raj.class
=> Class
We can also see its ancestors.
> Raj.class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
Class inherits from Module, since (for the most part) classes can do everything modules can. Module, in turn, inherits from Object, which has some modules of its own mixed in (PP:ObjectMixin is for pretty-printing, and Kernel gets you the nice helpers like puts) and eventually inherits from the root class BasicObject.
But this isn't the whole story, for Raj has its own class as well: its singleton class. We can see the full story by calling #singleton_class instead of #class.
> Raj.singleton_class.ancestors
=>
[#<Class:Raj>,
#<Class:Object>,
#<Class:BasicObject>,
Class,
Module,
Object,
PP::ObjectMixin,
Kernel,
BasicObject]
Now there's a lot more going on. Raj is an instance of the singleton class of Raj, which inherits from the singleton class of Object, which in turn inherits from the singleton class of BasicObject, which inherits from Class and all of the stuff we saw before.
So when you define a method on the class Raj, you're defining it (as an instance method) on the singleton class #<Class:Raj>. And that class (currently) has one instance: Raj.
By the way, it's also useful to know that the term "singleton class" is a bit of a lie. As you can see, the class is very much not a singleton in general. For instance, the singleton class of Object, called #<Class:Object> above, actually has several instances: Object, Raj, String, and most Ruby classes. Personally, I prefer to call them eigenclasses for that reason, but "singleton class" is the official (and more well-known) term.
The author is talking about the singleton class in this sentence, there is a really nice article to deep dive into ruby singleton class: https://medium.com/#leo_hetsch/demystifying-singleton-classes-in-ruby-caf3fa4c9d91
Here is a nice example extracted from this article:
class Vehicle
def initialize(kms)
#kms = kms
end
def drive
puts "let's go!"
end
end
car = Vehicle.new(1000)
bus = Vehicle.new(3000)
def car.drive
print "I'm driving a car! "
super
end
car.drive # "I'm driving a car! let's go!"
bus.drive # "let's go!"
As you can see, here the #drive method has been overridden but only for the car object, the bus object is still using the #drive method defined in the Vehicle class.
This new method is defined on the singleton class (or shadow class) of the object, this is allowing you to define new methods on the fly on an object without polluting all the objects of this class.
This means that Ruby doesn't implement class methods.
Indeed, the Ruby OBJECT Model, allows you to "emulate" the definition of class methods by defining instance methods on the Eigenclass:
class Greeting
def self.hello
'hello world!'
end
def self.eigenclass
class << self
self
end
end
end
Greeting.eigenclass # => #<Class:Greeting>
Greeting.eigenclass.name # => nil
Greeting.singleton_methods # => [:hello, :eigenclass]
Greeting.eigenclass.instance_methods(false) # => [:hello, :eigenclass]
First, we define a Greeting.eigenclass method. This method returns self in the context of the eigenclass — by using the class << self ... end syntax. In this case, self contains an unnamed instance of the class Class (a.k.a an anonymous class). This anonymous class keeps track of the class to which it is attached — the Greeting class in our case.
Then, we can see that the singleton methods of the Greeting class are the instance methods of the Greeting eigenclass.
Feel free to have a look to this very detailed article to learn more about this concept.
To illustrate #Sébastien P.'s answer:
dice = [1,2,3,4,5,6] #an ordinary array instance
def dice.throw #now it has an extra
sample
end
p dice.throw #=>3
2 main techniques for creating class methods (without the obvious "def self.method") are:
Defining them in "class << self" block
Defining ClassMethod module and extending it later
I personally prefer second way, seems cleaner. Does anyone has any reason to prefer one technique over the other?
There's also "class_method" method, but I never used it, it has quite complex implementation and seem to do a lot more than previous 2.
self.method is the simplest option when you just need to create one method without dependencies or related logic.
class << self allows you to do far more than define methods on the metaclass. This is useful when you're defining methods which need to work with other parts of the metaclass (eg. aliasing existing method names).
For instance:
class Logger
class << self
attr_reader :payload
def log(message)
#payload = message
end
end
end
The module extension method comes in handy for method reuse and to group multiple coherent methods.
For instance:
module QueryMethods
def find
end
def where
end
end
module FactoryMethods
def build
end
def create
end
end
class BusinessModel
extend QueryMethods
extend FactoryMethods
end
First, the class << foo syntax opens up foo's singleton class (eigenclass). This allows you to specialise the behaviour of methods called on that specific object.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
class << self opens up self's singleton class, so that methods can be redefined for the current self object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module ("static") methods
class << self is good at keeping all of your class methods in the same block. If methods are being added in def self.method from 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.
Pros of “class << self” style
I'm near the finish of the Ruby track in Code Academy, and I'm curious about a peculiar thing: I was under the impression that a class is a repository of constants, methods, etc... and that in order to access most of them, you would first need to create an instance of that class or in some cases the methods of themselves can be invoked (as in they are all technically part of the global object). And then I saw something like this:
#Worked
Time.now
I understood as this as the method [now] of instance of class [Time] being invoked. I then tried to invoke the method on its own:
#Failed
now
and that failed, and I assumed that while a method can be created in the general scope [as part of the global object], if it relies on initialized variables of "parent" class, it cannot be called on its own, because it would not know which object to search for those initialized variables. Following that I created a test class:
class Clock
def initialize
#hours = 1
#minutes = 30
end
def showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
#this worked
watch = Clock.new
watch.showTime
#this failed
showTime
I then just created a basic method (assuming it's in the global level)
def mymethod
puts "The mighty METHOD!"
end
#Works
mymethod
and calling this method the way I did, without referencing the global object worked. So... the questions I have are as follows:
How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
Why can't I call the method [now] on its own? Am I right that it relies on resources that it cannot find when called this way?
Why could I not call the method showTime on its own? But if I define any method on the "global" level I can access it without referencing the global object
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.
This is known as a class method. If CodeAcademy didn't cover it, that's a shame. Here's some examples:
# basic way
class Foo
def self.bar; :ok; end
end
Foo.bar # => :ok
# alternate syntax
class Foo
class << self
def bar; :ok; end
end
end
# alternate syntax, if Foo class already exists
def Foo.bar; :ok; end
# alternate approach if Foo class already exists
Foo.class_exec do
def bar; :ok; end
end
# to define a class method on an anonymous 'class' for a single instance
# you won't need to use this often
Foo.new.singleton_class.class_exec do
def bar; :ok; end
end
# to define a class method on an instance's actual class
Foo.new.class.class_exec do
def bar; :ok; end
end
Another way to get class methods is to extend a module.
module FooMethods
def bar; :ok; end
end
module Foo
extend FooMethods
end
Foo.bar # => :ok
Note that with Modules, the methods are always defined as instance methods. This way they can be either extended into class scope or included into instance scope. Modules can also have class methods, using the exact same syntax / examples as shown above with classes. However there's not such as easy to load a module's class methods via include or extend.
How can [Time.now] be called in this fashion? Shouldn't there be an
instance of Time first created?
The Time.now method is a class method, not an instance method and therefore can be called directly on the Time class rather than an instance of it Time.new
Class methods are defined on the class themselves using the self keyword:
class Time
def self.now
# code
end
end
Time.now # works
Why can't I call the method [now] on its own? Am I right that it
relies on resources that it cannot find when called this way?
When you call a method "on its own" you're actually implicitly calling it on self:
self.now
The above is the same as just doing:
now
Why could I not call the method showTime on its own? But if I define
any method on the "global" level I can access it without referencing
the global object
You defined the showTime method on a specific class so you have to send that method to that class. When you define a method in the "global" scope you're implicitly defining it on self and the subsequent call to mymethod is actually self.mymethod so it will work.
Time.now is a class method.
To define a class method, you need to define the method with self. : def self.method_name
class Clock
#hours = 1
#minutes = 30
def self.showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
Clock.showTime
#=> The time is: 1:30
If you want to call now on its own, you can do so inside Time class :
class Time
puts now
#=> 2017-01-19 22:17:29 +0100
end
One example of Ruby delegation is to use a SimpleDelegator:
class FooDecorator < SimpleDelegator
include ActiveModel::Model
# ...
end
That's very convenient, since anything not responded to by FooDecorator is passed to the underlying object.
But this overwrites the constructor's signature, which makes it incompatible with things like ActiveModel::Model that expect to see a particular signature.
Another example of Ruby delegation is to use Forwardable:
class Decorator
include ActiveModel::Model
extend Forwardable
attr_accessor :members
def_delegator :#members, :bar, :baz
def_delegators :#members, :a, :b, :c
end
But now you have to be explicit about which methods you want to delegate, which is brittle.
Is there a way to get the best of both worlds, where I...
don't tamper with the constructor
get pass-through delegation for any equivalently named method on the delegated object
Have you looked at the Delegator docs? You could basically re-implement your own Delegator subclass with the __getobj__ and __setobj__ methods. Or, you could just subclass SimpleDelegator and specify your own constructor that calls super(obj_to_delegate_to), no?
You could always just implement method_missing on your decorator and pass through any not-found method to the underlying object, too.
Edit: Here we go. The use of an intermediate inherited class breaks the super() chaining, allowing you to wrap the class as desired:
require 'active_model'
require 'delegate'
class Foo
include ActiveModel::Model
attr_accessor :bar
end
class FooDelegator < Delegator
def initialize
# Explicitly don't call super
end
def wrap(obj)
#obj = obj
self
end
def __getobj__
#obj
end
end
class FooDecorator < FooDelegator
include ActiveModel::Model
def name
self.class.name
end
end
decorator = FooDecorator.new.wrap(Foo.new bar: "baz")
puts decorator.name #=> "decorator"
puts decorator.bar #=> "bar"
Why do you want ActiveModel::Model? Do you truly need all of the features?
Could you merely do the same thing?
extend ActiveModel::Naming
extend ActiveModel::Translation
include ActiveModel::Validations
include ActiveModel::Conversion
I'm aware that changes to ActiveModel::Model could break your decorator in terms of the expected behavior, but you're coupling pretty tightly to it anyway.
Allowing modules to control constructors is a code smell. Might be ok, but you should second guess it and be well aware of why it does so.
ActiveModel::Model defines initialize to expect a hash. I'm not sure how you expect to get the particular object that you want to wrap.
SimpleDelegator uses __setobj__ inside of it's constructor, so you can use that after including a module that overrides your constructor.
If you want automatic forwarding you can just define the methods you need on your decorator when you set the object. If you can control how your object is created, make a build method (or something like that) which calls the initialize that needs to be used for ActiveModel::Model and __setobj__ that's used for SimpleDelegator:
require 'delegate'
require 'forwardable'
class FooCollection < SimpleDelegator
extend Forwardable
include ActiveModel::Model
def self.build(hash, obj)
instance = new(hash)
instance.send(:set_object, obj)
instance
end
private
def set_object(obj)
important_methods = obj.methods(false) - self.class.instance_methods
self.class.delegate [*important_methods] => :__getobj__
__setobj__(obj)
end
end
This allows you to used the ActiveModel interface but adds the SingleForwardable module to the singleton class of the decorator which gives you the delegate method. All you need to do then is pass it a collection of method names and a method to use to get the object for forwarding.
If you need to include or exclude particular methods, just change the way important_methods is created. I didn't think much about that, so double-check what's actually being used there before grabbing this code. For example, once the set_object method is called once, you can skip calling it later, but this is built to expect that all wrapped objects have the same interface.
As you pointed out on twitter, the draper gem uses the delegate method (from ActiveSupport) inside of method_missing. With that approach, each missed hit will incur the cost of opening the class and defining the method for forwarding. The upside is that it's lazy and you don't need to calculate which methods need to be forwarded and that hit is only incurred on the first miss; subsequent method calls won't be missed because you're defining that method.
The code I made above will get all those methods and define them at once.
If you need more flexibility and expect your decorator to not be the same type of object you can use SingleForwardable for the same effect but it will define methods for each wrapped instance instead of affecting the decorator class:
require 'delegate'
require 'forwardable'
class FooCollection < SimpleDelegator
include ActiveModel::Model
def self.build(hash, obj)
instance = new(hash)
instance.set_object(obj)
instance
end
def set_object(obj)
important_methods = obj.methods(false) - self.class.instance_methods
singleton_class.extend SingleForwardable
singleton_class.delegate [*important_methods] => :__getobj__
__setobj__(obj)
end
end
But all of this is using SimpleDelegator and if you're not actually using method_missing, you can cut that out (assuming you've calculated the important_methods part correctly:
require 'forwardable'
class FooCollection
include ActiveModel::Model
def self.build(hash, obj)
instance = new(hash)
instance.set_object(obj)
instance
end
def set_object(obj)
important_methods = obj.methods(false)# - self.class.instance_methods
singleton_class.extend SingleForwardable
singleton_class.delegate [*important_methods] => :__getobj__
__setobj__(obj)
end
def __getobj__
#obj
end
def __setobj__(obj)
__raise__ ::ArgumentError, "cannot forward to self" if self.equal?(obj)
#obj = obj
end
end
If you do that, however, it kills the use of super so you can't override a method defined on your wrapped object and call super to get the original value like you can with method_missing used in SimpleDelegator.
I wrote casting to add behavior to objects without worrying about wrappers. You can't override methods with it, but if all you're doing is adding new behaviors and new methods, then it will be much simpler to use by just adding a bucket of methods to an existing object. It's worth checking it out. I gave a presentation about the delegate and forwardable libraries at RubyConf 2013
Foo = Module.new
class MyClass
include Foo
end
When a module is included in a class, an anonymous proxy class is created and set as MyClass's superclass.
MyClass.ancestors => [MyClass, Foo, ...]
But what happens internally when a module is extended? How does Ruby handle this?
I think what you ask is Object#extend
So with extend, I can include any module's methods into that object.
For example I have a module called HelperModule:
module HelperModule
def foo
puts "from module helper"
end
end
Usage Example 1:
obj = Object.new
obj.extend HelperModule
obj.foo # => "from module helper"
Usage Example 2:
class MyClass
extend HelperModule
end
MyClass.foo # => "from module helper"
Internally, according to Metaprogramming Ruby:
Object#extend() is simply a shortcut that includes a module in the receiver’s eigenclass.
A brief explanation of ruby's methods call :
find the object's class, see if the method defined there
find that class's superclass, see if the method defined there
obj
|
| class
| superclass superclass
---> ObjectClass --------------> SuperClass1 --------------> SuperClass2 ....
The detailed explanation about eigenclass and method call path, please reference this awesome book Metaprogramming Ruby
Thanks
Whats happens internally when a module in extended in Ruby?
When a module M is included in a class C, an anonymous proxy class ⟦M′⟧ (called an include class) is created such that its method table pointer points to M's method table. (Same for the constant table and module variables.) ⟦M′⟧'s superclass is set to C's superclass and C's superclass is set to ⟦M′⟧.
Also, if M includes other modules, the process is applied recursively.
Actually, that's just the default behavior. What really happens is that include calls M.append_features(C), and you can customize all of that behavior by overriding that method.
I find the source code of Module#append_features in Rubinius quite readable.
obj.extend SomeModule is the same as obj.eigenclass.include SomeModule (Note: this is just pseudocode, but you will get the idea...).
In a nutshell, Ruby's include method will emulate inheritance: it will allow the including class access to the included module's instance methods, variables and constants as if they had been defined in the including class itself. Ruby does this by creating an anonymous proxy class (known as an eigenclass or singleton class), as you mentioned, which references the included module, and inserting it into the ancestors of the including class as the immediate superclass. This is what is known as a mixin in Ruby.
Using extend, however, interacts with the singleton class a little bit more:
module Foo
def baz
'baz'
end
end
module Blah
def blah
'blah'
end
end
class Bar
extend Foo
include Blah
def self.magic
'magic'
end
end
Extending Foo in Bar is identical (right down to its implementation in C) to saying
Bar.singleton_class.send( :include, Foo )
This means that it is the singleton class of Bar in which the methods and constants of Foo are essentially embedded, and thus class Bar, being an instance of its singleton class, will inherit this new functionality as so-called 'class' methods. In Ruby, modules and classes can only have instance methods, and thus the creation of a 'class' method will actually just create an instance method in the class's singleton class, to be inherited in this manner.
Bar.baz
# => 'baz'
Bar.magic
# => 'magic'
Bar.blah
# => NoMethodError
Bar.new.baz
# => NoMethodError
Bar.new.magic
# => NoMethodError
Bar.new.blah
# => 'blah'
Here you can see the differences in behavior of include and extend. To verify their behavior with regards to class ancestry, you can ask for the ancestors of Bar and its singleton class, and it will show you that module Blah is the immediate parent of Bar, but module Foo is the immediate parent of the singleton class.
Bar.ancestors
# => [Bar, Blah, Object, Kernel, BasicObject]
Bar.singleton_class.ancestors
# => [Foo, Class, Module, Object, Kernel, BasicObject]
From these results, you can see how inclusion emulates inheritance in the including class, and how extension is merely inclusion within the singleton class.
You might try looking at the answers I got for this question awhile back; they did an excellent job of explaining the behavior of the include and extend functionality.
This article has also helped me understand their differences.