I'm trying to understand Ruby's refinements feature, and I've encountered a scenario I don't understand.
Take this example code:
class Traveller
def what_are_you
puts "I'm a Backpacker"
end
def self.preferred_accommodation
puts "Hostels"
end
end
module Refinements
module Money
def what_are_you
puts "I'm a cashed-up hedonist!"
end
module ClassMethods
def preferred_accommodation
puts "Expensive Hotels"
end
end
def self.included(base)
base.extend ClassMethods
end
end
refine Traveller do
include Money
end
end
Now, when I do this in the REPL:
Traveller.new.what_are_you # => I'm a Backpacker
Traveller.preferred_accommodation # => Hostels
using Refinements
Traveller.new.what_are_you # => I'm a cashed-up hedonist!
Traveller.preferred_accommodation # => Hostels (???)
Why is #what_are_you
refined, but .preferred_accommodation
is not?
As @MasashiMiyazaki explained, you have to refine two classes: Traveller
and Traveller
's singleton class. That actually allows you to simplify your code quite a bit:
module Money
refine Traveller do
def what_are_you
puts "I'm a cashed-up hedonist!"
end
end
refine Traveller.singleton_class do
def preferred_accommodation
puts "Expensive Hotels"
end
end
end
Traveller.new.what_are_you #=> I'm a Backpacker
Traveller.preferred_accommodation #=> Hostels
using Money
Traveller.new.what_are_you #=> I'm a cashed-up hedonist!
Traveller.preferred_accommodation #=> Expensive Hotels
Moreover, by putting the above three statements in a module, the refined versions of the two methods are confined to that module:
module M
using Money
Traveller.new.what_are_you #=> I'm a cashed-up hedonist!
Traveller.preferred_accommodation #=> Expensive Hotels
end
Traveller.new.what_are_you #=> I'm a Backpacker
Traveller.preferred_accommodation #=> Hostels
You need to call refine Traveller with singleton_class scope to overwrite class methods. By adding the following code to your Refinements module instead of self.included
, you can get the expected result.
module Refinements
refine Traveller.singleton_class do
include Money::ClassMethods
end
end
This article(http://timelessrepo.com/refinements-in-ruby) will help you to understand Refinements more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With