Say I am monkey patching a method in a class, how could I call the overridden method from the overriding method? I.e. Something a bit like super
E.g.
class Foo
def bar()
"Hello"
end
end
class Foo
def bar()
super() + " World"
end
end
>> Foo.new.bar == "Hello World"
EDIT: It has been 9 years since I originally wrote this answer, and it deserves some cosmetic surgery to keep it current.
You can see the last version before the edit here.
You can’t call the overwritten method by name or keyword. That’s one of the many reasons why monkey patching should be avoided and inheritance be preferred instead, since obviously you can call the overridden method.
Avoiding Monkey Patching
Inheritance
So, if at all possible, you should prefer something like this:
class Foo
def bar
'Hello'
end
end
class ExtendedFoo < Foo
def bar
super + ' World'
end
end
ExtendedFoo.new.bar # => 'Hello World'
This works, if you control creation of the Foo objects. Just change every place which creates a Foo to instead create an ExtendedFoo. This works even better if you use the Dependency Injection Design Pattern, the Factory Method Design Pattern, the Abstract Factory Design Pattern or something along those lines, because in that case, there is only place you need to change.
Delegation
If you do not control creation of the Foo objects, for example because they are created by a framework that is outside of your control (like ruby-on-rails for example), then you could use the Wrapper Design Pattern:
require 'delegate'
class Foo
def bar
'Hello'
end
end
class WrappedFoo < DelegateClass(Foo)
def initialize(wrapped_foo)
super
end
def bar
super + ' World'
end
end
foo = Foo.new # this is not actually in your code, it comes from somewhere else
wrapped_foo = WrappedFoo.new(foo) # this is under your control
wrapped_foo.bar # => 'Hello World'
Basically, at the boundary of the system, where the Foo object comes into your code, you wrap it into another object, and then use that object instead of the original one everywhere else in your code.
This uses the Object#DelegateClass helper method from the delegate library in the stdlib.
“Clean” Monkey Patching
Module#prepend: Mixin Prepending
The two methods above require changing the system to avoid monkey patching. This section shows the preferred and least invasive method of monkey patching, should changing the system not be an option.
Module#prepend was added to support more or less exactly this use case. Module#prepend does the same thing as Module#include, except it mixes in the mixin directly below the class:
class Foo
def bar
'Hello'
end
end
module FooExtensions
def bar
super + ' World'
end
end
class Foo
prepend FooExtensions
end
Foo.new.bar # => 'Hello World'
Note: I also wrote a little bit about Module#prepend in this question: Ruby module prepend vs derivation
Mixin Inheritance (broken)
I have seen some people try (and ask about why it doesn’t work here on StackOverflow) something like this, i.e. includeing a mixin instead of prepending it:
class Foo
def bar
'Hello'
end
end
module FooExtensions
def bar
super + ' World'
end
end
class Foo
include FooExtensions
end
Unfortunately, that won’t work. It’s a good idea, because it uses inheritance, which means that you can use super. However, Module#include inserts the mixin above the class in the inheritance hierarchy, which means that FooExtensions#bar will never be called (and if it were called, the super would not actually refer to Foo#bar but rather to Object#bar which doesn’t exist), since Foo#bar will always be found first.
Method Wrapping
The big question is: how can we hold on to the bar method, without actually keeping around an actual method? The answer lies, as it does so often, in functional programming. We get a hold of the method as an actual object, and we use a closure (i.e. a block) to make sure that we and only we hold on to that object:
class Foo
def bar
'Hello'
end
end
class Foo
old_bar = instance_method(:bar)
define_method(:bar) do
old_bar.bind(self).() + ' World'
end
end
Foo.new.bar # => 'Hello World'
This is very clean: since old_bar is just a local variable, it will go out of scope at the end of the class body, and it is impossible to access it from anywhere, even using reflection! And since Module#define_method takes a block, and blocks close over their surrounding lexical environment (which is why we are using define_method instead of def here), it (and only it) will still have access to old_bar, even after it has gone out of scope.
Short explanation:
old_bar = instance_method(:bar)
Here we are wrapping the bar method into an UnboundMethod method object and assigning it to the local variable old_bar. This means, we now have a way to hold on to bar even after it has been overwritten.
old_bar.bind(self)
This is a bit tricky. Basically, in Ruby (and in pretty much all single-dispatch based OO languages), a method is bound to a specific receiver object, called self in Ruby. In other words: a method always knows what object it was called on, it knows what its self is. But, we grabbed the method directly from a class, how does it know what its self is?
Well, it doesn’t, which is why we need to bind our UnboundMethod to an object first, which will return a Method object that we can then call. (UnboundMethods cannot be called, because they don’t know what to do without knowing their self.)
And what do we bind it to? We simply bind it to ourselves, that way it will behave exactly like the original bar would have!
Lastly, we need to call the Method that is returned from bind. In Ruby 1.9, there is some nifty new syntax for that (.()), but if you are on 1.8, you can simply use the call method; that’s what .() gets translated to anyway.
Here are a couple of other questions, where some of those concepts are explained:
How do I reference a function in Ruby?
Is Ruby’s code block same as C♯’s lambda expression?
“Dirty” Monkey Patching
alias_method chain
The problem we are having with our monkey patching is that when we overwrite the method, the method is gone, so we cannot call it anymore. So, let’s just make a backup copy!
class Foo
def bar
'Hello'
end
end
class Foo
alias_method :old_bar, :bar
def bar
old_bar + ' World'
end
end
Foo.new.bar # => 'Hello World'
Foo.new.old_bar # => 'Hello'
The problem with this is that we have now polluted the namespace with a superfluous old_bar method. This method will show up in our documentation, it will show up in code completion in our IDEs, it will show up during reflection. Also, it still can be called, but presumably we monkey patched it, because we didn’t like its behavior in the first place, so we might not want other people to call it.
Despite the fact that this has some undesirable properties, it has unfortunately become popularized through AciveSupport’s Module#alias_method_chain.
An aside: Refinements
In case you only need the different behavior in a few specific places and not throughout the whole system, you can use Refinements to restrict the monkey patch to a specific scope. I am going to demonstrate it here using the Module#prepend example from above:
class Foo
def bar
'Hello'
end
end
module ExtendedFoo
module FooExtensions
def bar
super + ' World'
end
end
refine Foo do
prepend FooExtensions
end
end
Foo.new.bar # => 'Hello'
# We haven’t activated our Refinement yet!
using ExtendedFoo
# Activate our Refinement
Foo.new.bar # => 'Hello World'
# There it is!
You can see a more sophisticated example of using Refinements in this question: How to enable monkey patch for specific method?
Abandoned ideas
Before the Ruby community settled on Module#prepend, there were multiple different ideas floating around that you may occasionally see referenced in older discussions. All of these are subsumed by Module#prepend.
Method Combinators
One idea was the idea of method combinators from CLOS. This is basically a very lightweight version of a subset of Aspect-Oriented Programming.
Using syntax like
class Foo
def bar:before
# will always run before bar, when bar is called
end
def bar:after
# will always run after bar, when bar is called
# may or may not be able to access and/or change bar’s return value
end
end
you would be able to “hook into” the execution of the bar method.
It is however not quite clear if and how you get access to bar’s return value within bar:after. Maybe we could (ab)use the super keyword?
class Foo
def bar
'Hello'
end
end
class Foo
def bar:after
super + ' World'
end
end
Replacement
The before combinator is equivalent to prepending a mixin with an overriding method that calls super at the very end of the method. Likewise, the after combinator is equivalent to prepending a mixin with an overriding method that calls super at the very beginning of the method.
You can also do stuff before and after calling super, you can call super multiple times, and both retrieve and manipulate super’s return value, making prepend more powerful than method combinators.
class Foo
def bar:before
# will always run before bar, when bar is called
end
end
# is the same as
module BarBefore
def bar
# will always run before bar, when bar is called
super
end
end
class Foo
prepend BarBefore
end
and
class Foo
def bar:after
# will always run after bar, when bar is called
# may or may not be able to access and/or change bar’s return value
end
end
# is the same as
class BarAfter
def bar
original_return_value = super
# will always run after bar, when bar is called
# has access to and can change bar’s return value
end
end
class Foo
prepend BarAfter
end
old keyword
This idea adds a new keyword similar to super, which allows you to call the overwritten method the same way super lets you call the overridden method:
class Foo
def bar
'Hello'
end
end
class Foo
def bar
old + ' World'
end
end
Foo.new.bar # => 'Hello World'
The main problem with this is that it is backwards incompatible: if you have method called old, you will no longer be able to call it!
Replacement
super in an overriding method in a prepended mixin is essentially the same as old in this proposal.
redef keyword
Similar to above, but instead of adding a new keyword for calling the overwritten method and leaving def alone, we add a new keyword for redefining methods. This is backwards compatible, since the syntax currently is illegal anyway:
class Foo
def bar
'Hello'
end
end
class Foo
redef bar
old + ' World'
end
end
Foo.new.bar # => 'Hello World'
Instead of adding two new keywords, we could also redefine the meaning of super inside redef:
class Foo
def bar
'Hello'
end
end
class Foo
redef bar
super + ' World'
end
end
Foo.new.bar # => 'Hello World'
Replacement
redefining a method is equivalent to overriding the method in a prepended mixin. super in the overriding method behaves like super or old in this proposal.
Take a look at aliasing methods, this is kind of renaming the method to a new name.
For more information and a starting point take a look at this replacing methods article (especially the first part).
The Ruby API docs, also provides (a less elaborate) example.
The class that will make override must to be reloaded after class that contains the original method, so require it in the file that will make overrride.
Related
Say I have this class:
class Foo
def destroy_target(target)
Missile.launch(target)
end
end
I want to temporarily neuter the destructive power of Foo, for example for testing purposes, so I do this:
backup = Foo.instance_method(:destroy_target)
class Foo
def destroy_target(target)
Pillow.launch(target)
end
end
Here's my question: how do I "reattach" the original method to Foo, as if it was never overridden in the first place?
I realize I can do this:
class Foo
def destroy_target(target)
backup.bind(self).call(target)
end
end
But obviously this is not optimal, as I'm now wrapping the original function. I want to be able to detach and reattach the method an indefinite amount of times without adding any overhead.
Asked a different way; how do I attach a DetachedMethod to a class "properly", i.e. without defining a new method that calls the detached one.
Note: I am not interested in alternative ways of temporarily changing the functionality of a class. I specifically want to know how to replace a method with a different method, then restore the original method cleanly.
I tested your first example, and it seems to work fine. I couldn't find any side-effect, but it doesn't mean there isn't.
Did you consider refinements?
For a Class
class Missile
def self.launch(t)
puts "MISSILE -> #{t}"
end
end
class Pillow
def self.launch(t)
puts "PILLOW -> #{t}"
end
end
class Foo
def destroy_target(target)
Missile.launch(target)
end
end
module PillowLauncher
refine Foo do
def destroy_target(target)
Pillow.launch(target)
end
end
end
module Test
using PillowLauncher
Foo.new.destroy_target("Tatooine")
#=> PILLOW -> Tatooine
end
Foo.new.destroy_target("Tatooine")
#=> MISSILE -> Tatooine
It might bring the advantage of being a bit more standard and understandable than your example.
For a Module
If Foo is a Module, you cannot call refine Foo directly, you'd get a TypeError: wrong argument type Module (expected Class).
You can, however, refine its singleton_class :
module Foo
def self.destroy_target(target)
Missile.launch(target)
end
end
module PillowLauncher
refine Foo.singleton_class do
def destroy_target(target)
Pillow.launch(target)
end
end
end
module Test
using PillowLauncher
Foo.destroy_target('Tatooine')
#=> PILLOW -> Tatooine
end
Foo.destroy_target('Tatooine')
#=> MISSILE -> Tatooine
I'm not sure about your note :
I am not interested in alternative ways of temporarily changing
the functionality of a class. I specifically want to know how to
replace a method with a different method, then restore the original
method cleanly.
My proposed code seems to do both.
This appears to work:
Foo.instance_exec {
define_method(:destroy_target, backup)
}
But I'm not completely sure if this is side effect free. If somebody knows for sure I'd appreciate a comment.
This also appears to work if Foo is a module defined like this:
module Foo
extend self
def destroy_target(target)
Missile.launch(target)
end
end
From what I understand about self, it refers to the current instance of the class.
Isn't this the default behaviour at all times anyways? For example, isn't
self.var_one = method(args)
equivalent to
var_one = method(args)
If so, what is the use of self?
There are several important uses, most of which are basically to disambiguate between instance methods, class methods, and variables.
First, this is the best way to define class methods:
class Foo
def self.bar
"class method bar"
end
def bar
"instance method bar"
end
end
Foo.bar #returns "class method bar"
foo = Foo.new
foo.bar #returns "instance method bar"
Also, within instance methods self refers to the instance, within class methods it refers to the class, and it can always be used to distinguish from local variables.
class Bar
def self.foo
"foo!"
end
def baz
"baz!"
end
def self.success
foo #looks for variable foo, doesn't find one, looks for class method foo, finds it, returns "foo!"
end
def self.fail
baz #looks for variable baz, doesn't find one, looks for class method baz, doesn't find one, raises exception
end
def instance_success
baz #looks for variable baz, doesn't find one, looks for instance method baz, finds it, returns "baz!"
end
def instance_fail
foo #looks for variable foo, doesn't find one, looks for instance method foo, doesn't find one, raises exception
end
def local_variable
baz = "is my favorite method"
baz #looks for variable baz, finds it, returns "is my favorite method"
end
def disambiguate
baz = " is my favorite method"
self.baz + baz #looks for instance method baz, finds it, looks for local variable baz, finds it, returns "baz! is my favorite method"
end
end
So, in the end, you can avoid using self in many cases, but it's often helpful to use it to make sure that you don't inadvertently create naming conflicts later on. Sometimes those can create bugs that are very hard to find. In the end it's often a matter of personal style.
As noted in the comments, one more really important thing:
In a class, if you have a method like this:
def bar=(string)
...
end
And in another method you call:
def other_method
bar = "abcd"
end
It isn't going to call your bar= method, it's going to create a local variable bar. So, in this case you use self to tell Ruby not to create a local variable:
def other_method
self.bar = "abcd"
end
The same thing applies if you want to take an argument with the name of a method:
def example
...
end
def other_thing(example)
self.example(example)
end
If you left off self Ruby would assume you meant the local variable with the same name.
So, in general, self in method names is used to distinguish between class and instance variables, and everywhere else you use it when Ruby needs help distinguishing between method calls and local variables or local variable assignment.
I hope that makes sense.
In most cases self.foo is indeed redundant because you can just write foo for the same effect, but in this case it is not and the self is required.
var_one = method(args) will create a local variable called var_one, it will not call any method or do anything else to self.
self.var_one = method(args) will call the method var_one= on self with the argument method(args).
Another case where the use of self is non-optional would be if you want to pass it as an argument to a method, i.e. some_method(self) - you can't do that without the self keyword.
One other use of self is to declare class methods (similar to static methods in Java).
class foo
def self.bar
#do class related stuff here
end
end
That being said, you could also have used def foo.bar instead for the method signature.
Here's an example:
def run miles
self.miles = miles
end
In this case self will help. In most cases self is redundant.
Just want to enquire what the right practice is.
My preference is to use procs, simply because I think that defining methods inside of methhods is a bit untidy and should be done only when necessary. To get around it, I simply use procs.
What is the right / better way to do it and why? (apart from the proc's ability to access the main method's variables defined before itself)
def meth( params_prime )
calculations = do_something_with_whatever
def sub_meth( params_sub )
do_something_with_params_sub
end
sub_meth_params(calculations) # is this better?
proc1 = proc{ |params_sub| do_something_with_params_sub }
proc1.call(calculations) # or is this?
end
It is not clear what your specific use-case is, but I would definitely go for procs or lambdas. There is less overhead when defining a proc or lambda dynamically, they are passable, so if needed you could return them and they could be used outside the function.
Using "def" exposes the method as an instance method outside of the current method scope (so in the containing class, which could be Object in your case). This may or may not be with you want. If you want to use an anonymous function only available in the local scope, use a lambda.
Also Proc vs Lambda: I generally prefer to use lambdas since they behave a little more "predictable", meaning: as you would expect (check passed variables, and return just returns from the lambda, proc returns from the called scope). But from your example it is hard to deduce what would apply. I think the key-difference is: lambas are ment to be passed around, and thus behave a little more sanely. If this is not your use-case, use Proc :) (a write-up of the difference).
If you want to use sub_func to encapsulate it from call from other methods you can use a class to group function and sub_func together and make sub_func private. Otherwise if you want to pass this function as a parameter further you can declare it as lamda.
def func params_prime
sub_func = ->(params_sub){do_something_with_params}
sub_func.call(params_prime)
end
Defining methods inside methods is a feature of Ruby that may have its use. But something is telling me that you are asking a very advanced question while you are still a beginner level Rubyist. Do you know what default definee is? If not, check this article by Yugui.
Procs are very important in Ruby, but newbies tend to use them instead of defining methods in appropriate objects, which is the exact smell I'm getting from your question. The normal way of doing things in OO languages of Ruby family is to define methods on objects:
class Foo
def bar *params
# do something with params
end
end
Since you do not understand the meaning of defining methods inside methods, refrain from doing it for the next 6 months. Once you understand objects, you can start experimenting with this very advanced feature again.
APPENDIX:
Since you demonstrated intrest, let me show you that using def in def at the top level is a frownable-upon thing to do. Normally, when you define a method on some class without further adornment, it becomes a public instance method of that class:
class X
def foo; "foo" end
end
X.instance_methods.include? :foo
#=> true
When you use def in a def, the definee for the inner def is going to be X:
class X
def bar
def baz
"baz"
end
"bar"
end
end
When you execute the above code, instance method #bar becomes defined on X:
X.instance_methods.include? :bar
#=> true
But #baz not yet:
X.instance_methods.include? :baz
#=> false
Only after you call #bar at least once does the method become defined on X:
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
And now I would like to ask you to appreciate how terrible thing just happened: An instance just modified its mother class. That's a violation. A violation of such a basic principle of OO design, that I'm not even sure it has a name. This technique is great for obfuscated coding competitions, but in production, it's taboo. Ruby gives you the freedom to break that taboo, gives you the rope to hang yourself on, but you don't do it under any kind of normal circumstances.
So what can be worse than a def inside a def in a class definition? The answer is, a def inside a def at the top level. Let me show you why. Normally, when you define methods with def at the top level, the default definee is Object, but the top level defnitions become private instance methods of object. This is to prevent the unintended consequence of top level defs, because almost all Ruby objects inherit from Object. For example, if you define:
class Object
def foo; "foo" end
end
Now all your objects will respond to foo:
foo #=> "foo"
1.foo #=> "foo"
[].foo #=> "foo
When we define methods at the top level, we usually just intend to use the method at the top level, and don't want every single object to inherit it. For that reason, top level defs become private:
hello #=> NameError: undefined local variable or method `hello' for main:Object
1.hello #=> NoMethodError: undifined method 'hello' for 1:Fixnum
Now we use def at the top level:
def hello; "hello" end
We can see that method #hello is has not become an instance methods of Object:
Object.instance_methods.include? :hello
#=> false
Mysteriously, it became its private method:
Object.private_instance_methods.include? :hello
#=> true
This way, we avoid the unintended consequence of defining #hello method for every single object. But the inheritance is there. The error message has changed:
1.hello #=> NoMethodError: private method 'hello' called for 1:Fixnum
And we can forcibly call the method via #send:
1.send :hello
#=> "hello"
Mysteriously, at the top level, we are allowed to call this private method without #send:
hello
#=> "hello"
And now, what happens when you do def in def at the top level:
def bar
def baz; "baz" end
"bar"
end
You define a private instance method Object#bar in an expected way. But when you call it, alas, the top level magic no longer works and a public method Object#baz gets defined:
bar #=> "bar"
This way, not just the top level, but every single Ruby object got polluted with your #baz method:
1.baz #=> "baz"
Class.baz #=> "baz"
This is why I told you to refrain from using this idiom until you progress from the level of unconscious incompetence to the level of conscious incompetence. I recommend you to read more about top level methods in Ruby.
I'm wondering if there's a way to return an object instead of a string when calling an object without any methods.
For instance:
class Foo
def initialize
#bar = Bar.new
end
end
Is there any way to define the Foo class so that the following happens:
foo = Foo.new
foo #returns #bar
In the specific case I'm interested in I'm using a presenter in a Rails view. The presenter sets up one main object and then loads a bunch of related content. The important part looks like this:
class ExamplePresenter
def initialize( id )
#example = Example.find( id )
end
def example
#example
end
...
end
If I want to return the example used by the ExamplePresenter I can call:
#presenter = ExamplePresenter.new(1)
#presenter.example
It would be nice if I could also return the example object by just calling:
#presenter
So, is there a way to set a default method to return when an object is called, like to_s but returning an object instead of a string?
If I understand correctly, you want to return the instance of Example when you call the ExamplePresenter instance. Such a direct mechanism does not exist in any language, and even if it did, it would block all access to the ExamplePresenter instance and its methods. So it is not logical.
There is something you can do however. You can make the ExamplePresenter class delegate methods to the Example instance inside it. Effectively you do not get a real Example from #presenter but you get an ExamplePresenter that passes all eligible methods into its internal Example effectively acting in behalf of it.
Some ways of doing this is:
method_missing
class ExamplePresenter
… # as defined in the question
def method_missing symbol, *args
if #example.respond_to?(symbol)
#example.send(symbol, *args)
else
super
end
end
end
This will pass any method call down to the internal Example if the ExamplePresenter cannot respond to it. Be careful, you may expose more than you want of the internal Example this way, and any method already defined on ExamplePresenter cannot be passed along.
You can use additional logic inside method_missing to limit exposure or pre/post process the arguments/return values.
Wrapper methods
You can define wrapper methods on ExamplePresenter that do nothing but pass everything to the internal Example. This gives you explicit control on how much of it you want to expose.
class ExamplePresenter
… # as before
def a_method
#example.a_method
end
def another_method(argument, another_argument)
#example.another_method(argument, another_argument)
end
end
This gets tedious fast, but you can also add logic to alter arguments before passing it along to the Example or post process the results.
You can also mix and match the above two methods
Delegator library
There is a library in Ruby stdlib called Delegator built exactly for this purpose. You may look into it.
Although this is not recommended, you can do:
class Foo
def self.new
#bar = Bar.new
end
end
If you actually do need to create an instance of Foo, then
class << Foo
alias original_new :new
end
class Foo
def self.new
self.original_new # It will not be useful unless you assign this to some variable.
#bar = Bar.new
end
end
Say I am monkey patching a method in a class, how could I call the overridden method from the overriding method? I.e. Something a bit like super
E.g.
class Foo
def bar()
"Hello"
end
end
class Foo
def bar()
super() + " World"
end
end
>> Foo.new.bar == "Hello World"
EDIT: It has been 9 years since I originally wrote this answer, and it deserves some cosmetic surgery to keep it current.
You can see the last version before the edit here.
You can’t call the overwritten method by name or keyword. That’s one of the many reasons why monkey patching should be avoided and inheritance be preferred instead, since obviously you can call the overridden method.
Avoiding Monkey Patching
Inheritance
So, if at all possible, you should prefer something like this:
class Foo
def bar
'Hello'
end
end
class ExtendedFoo < Foo
def bar
super + ' World'
end
end
ExtendedFoo.new.bar # => 'Hello World'
This works, if you control creation of the Foo objects. Just change every place which creates a Foo to instead create an ExtendedFoo. This works even better if you use the Dependency Injection Design Pattern, the Factory Method Design Pattern, the Abstract Factory Design Pattern or something along those lines, because in that case, there is only place you need to change.
Delegation
If you do not control creation of the Foo objects, for example because they are created by a framework that is outside of your control (like ruby-on-rails for example), then you could use the Wrapper Design Pattern:
require 'delegate'
class Foo
def bar
'Hello'
end
end
class WrappedFoo < DelegateClass(Foo)
def initialize(wrapped_foo)
super
end
def bar
super + ' World'
end
end
foo = Foo.new # this is not actually in your code, it comes from somewhere else
wrapped_foo = WrappedFoo.new(foo) # this is under your control
wrapped_foo.bar # => 'Hello World'
Basically, at the boundary of the system, where the Foo object comes into your code, you wrap it into another object, and then use that object instead of the original one everywhere else in your code.
This uses the Object#DelegateClass helper method from the delegate library in the stdlib.
“Clean” Monkey Patching
Module#prepend: Mixin Prepending
The two methods above require changing the system to avoid monkey patching. This section shows the preferred and least invasive method of monkey patching, should changing the system not be an option.
Module#prepend was added to support more or less exactly this use case. Module#prepend does the same thing as Module#include, except it mixes in the mixin directly below the class:
class Foo
def bar
'Hello'
end
end
module FooExtensions
def bar
super + ' World'
end
end
class Foo
prepend FooExtensions
end
Foo.new.bar # => 'Hello World'
Note: I also wrote a little bit about Module#prepend in this question: Ruby module prepend vs derivation
Mixin Inheritance (broken)
I have seen some people try (and ask about why it doesn’t work here on StackOverflow) something like this, i.e. includeing a mixin instead of prepending it:
class Foo
def bar
'Hello'
end
end
module FooExtensions
def bar
super + ' World'
end
end
class Foo
include FooExtensions
end
Unfortunately, that won’t work. It’s a good idea, because it uses inheritance, which means that you can use super. However, Module#include inserts the mixin above the class in the inheritance hierarchy, which means that FooExtensions#bar will never be called (and if it were called, the super would not actually refer to Foo#bar but rather to Object#bar which doesn’t exist), since Foo#bar will always be found first.
Method Wrapping
The big question is: how can we hold on to the bar method, without actually keeping around an actual method? The answer lies, as it does so often, in functional programming. We get a hold of the method as an actual object, and we use a closure (i.e. a block) to make sure that we and only we hold on to that object:
class Foo
def bar
'Hello'
end
end
class Foo
old_bar = instance_method(:bar)
define_method(:bar) do
old_bar.bind(self).() + ' World'
end
end
Foo.new.bar # => 'Hello World'
This is very clean: since old_bar is just a local variable, it will go out of scope at the end of the class body, and it is impossible to access it from anywhere, even using reflection! And since Module#define_method takes a block, and blocks close over their surrounding lexical environment (which is why we are using define_method instead of def here), it (and only it) will still have access to old_bar, even after it has gone out of scope.
Short explanation:
old_bar = instance_method(:bar)
Here we are wrapping the bar method into an UnboundMethod method object and assigning it to the local variable old_bar. This means, we now have a way to hold on to bar even after it has been overwritten.
old_bar.bind(self)
This is a bit tricky. Basically, in Ruby (and in pretty much all single-dispatch based OO languages), a method is bound to a specific receiver object, called self in Ruby. In other words: a method always knows what object it was called on, it knows what its self is. But, we grabbed the method directly from a class, how does it know what its self is?
Well, it doesn’t, which is why we need to bind our UnboundMethod to an object first, which will return a Method object that we can then call. (UnboundMethods cannot be called, because they don’t know what to do without knowing their self.)
And what do we bind it to? We simply bind it to ourselves, that way it will behave exactly like the original bar would have!
Lastly, we need to call the Method that is returned from bind. In Ruby 1.9, there is some nifty new syntax for that (.()), but if you are on 1.8, you can simply use the call method; that’s what .() gets translated to anyway.
Here are a couple of other questions, where some of those concepts are explained:
How do I reference a function in Ruby?
Is Ruby’s code block same as C♯’s lambda expression?
“Dirty” Monkey Patching
alias_method chain
The problem we are having with our monkey patching is that when we overwrite the method, the method is gone, so we cannot call it anymore. So, let’s just make a backup copy!
class Foo
def bar
'Hello'
end
end
class Foo
alias_method :old_bar, :bar
def bar
old_bar + ' World'
end
end
Foo.new.bar # => 'Hello World'
Foo.new.old_bar # => 'Hello'
The problem with this is that we have now polluted the namespace with a superfluous old_bar method. This method will show up in our documentation, it will show up in code completion in our IDEs, it will show up during reflection. Also, it still can be called, but presumably we monkey patched it, because we didn’t like its behavior in the first place, so we might not want other people to call it.
Despite the fact that this has some undesirable properties, it has unfortunately become popularized through AciveSupport’s Module#alias_method_chain.
An aside: Refinements
In case you only need the different behavior in a few specific places and not throughout the whole system, you can use Refinements to restrict the monkey patch to a specific scope. I am going to demonstrate it here using the Module#prepend example from above:
class Foo
def bar
'Hello'
end
end
module ExtendedFoo
module FooExtensions
def bar
super + ' World'
end
end
refine Foo do
prepend FooExtensions
end
end
Foo.new.bar # => 'Hello'
# We haven’t activated our Refinement yet!
using ExtendedFoo
# Activate our Refinement
Foo.new.bar # => 'Hello World'
# There it is!
You can see a more sophisticated example of using Refinements in this question: How to enable monkey patch for specific method?
Abandoned ideas
Before the Ruby community settled on Module#prepend, there were multiple different ideas floating around that you may occasionally see referenced in older discussions. All of these are subsumed by Module#prepend.
Method Combinators
One idea was the idea of method combinators from CLOS. This is basically a very lightweight version of a subset of Aspect-Oriented Programming.
Using syntax like
class Foo
def bar:before
# will always run before bar, when bar is called
end
def bar:after
# will always run after bar, when bar is called
# may or may not be able to access and/or change bar’s return value
end
end
you would be able to “hook into” the execution of the bar method.
It is however not quite clear if and how you get access to bar’s return value within bar:after. Maybe we could (ab)use the super keyword?
class Foo
def bar
'Hello'
end
end
class Foo
def bar:after
super + ' World'
end
end
Replacement
The before combinator is equivalent to prepending a mixin with an overriding method that calls super at the very end of the method. Likewise, the after combinator is equivalent to prepending a mixin with an overriding method that calls super at the very beginning of the method.
You can also do stuff before and after calling super, you can call super multiple times, and both retrieve and manipulate super’s return value, making prepend more powerful than method combinators.
class Foo
def bar:before
# will always run before bar, when bar is called
end
end
# is the same as
module BarBefore
def bar
# will always run before bar, when bar is called
super
end
end
class Foo
prepend BarBefore
end
and
class Foo
def bar:after
# will always run after bar, when bar is called
# may or may not be able to access and/or change bar’s return value
end
end
# is the same as
class BarAfter
def bar
original_return_value = super
# will always run after bar, when bar is called
# has access to and can change bar’s return value
end
end
class Foo
prepend BarAfter
end
old keyword
This idea adds a new keyword similar to super, which allows you to call the overwritten method the same way super lets you call the overridden method:
class Foo
def bar
'Hello'
end
end
class Foo
def bar
old + ' World'
end
end
Foo.new.bar # => 'Hello World'
The main problem with this is that it is backwards incompatible: if you have method called old, you will no longer be able to call it!
Replacement
super in an overriding method in a prepended mixin is essentially the same as old in this proposal.
redef keyword
Similar to above, but instead of adding a new keyword for calling the overwritten method and leaving def alone, we add a new keyword for redefining methods. This is backwards compatible, since the syntax currently is illegal anyway:
class Foo
def bar
'Hello'
end
end
class Foo
redef bar
old + ' World'
end
end
Foo.new.bar # => 'Hello World'
Instead of adding two new keywords, we could also redefine the meaning of super inside redef:
class Foo
def bar
'Hello'
end
end
class Foo
redef bar
super + ' World'
end
end
Foo.new.bar # => 'Hello World'
Replacement
redefining a method is equivalent to overriding the method in a prepended mixin. super in the overriding method behaves like super or old in this proposal.
Take a look at aliasing methods, this is kind of renaming the method to a new name.
For more information and a starting point take a look at this replacing methods article (especially the first part).
The Ruby API docs, also provides (a less elaborate) example.
The class that will make override must to be reloaded after class that contains the original method, so require it in the file that will make overrride.