Created
November 14, 2012 17:07
-
-
Save jsl/4073369 to your computer and use it in GitHub Desktop.
Ruby Refinements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'minitest/autorun' | |
# Demonstrates the way that refinements are applied in Ruby 2.0.0preview1. | |
module RegularStringCounts | |
refine String do | |
def num_caps | |
self.scan(/[A-Z]/).count | |
end | |
end | |
end | |
module Always42Caps | |
refine String do | |
def num_caps ; 42 ; end | |
end | |
end | |
class Person | |
attr_reader :name | |
using RegularStringCounts | |
def initialize(name) | |
@name = name | |
end | |
def caps_in_name | |
name.num_caps | |
end | |
end | |
describe "simple refinements on a class" do | |
it "should use the refined method" do | |
Person.new("JoeY").caps_in_name.must_equal 2 | |
end | |
end | |
describe "when eval'ing code inside a class that has used refinements" do | |
it "should use the refinement" do | |
Person.new("JoeY").instance_eval{ "Test STRING".num_caps.must_equal 7 } | |
end | |
end | |
describe "on an class inherited from one that is refined" do | |
class Programmer < Person ; end | |
it "should use the refined method from the parent class" do | |
Programmer.new("JoeY").caps_in_name.must_equal 2 | |
end | |
end | |
describe "refinements affecting context where method is invoked in class hierarchy" do | |
it "should prefer the refinement applied in the parent class where method is invoked" do | |
class MoreRefinedPerson < Person | |
using Always42Caps | |
end | |
# Ruby ignores the child class refinement, since the parent class actually responds to | |
# the message :caps_in_name. Is this intended behavior or a bug? | |
MoreRefinedPerson.new("JoeY").caps_in_name.must_equal 2 | |
end | |
end | |
describe "refinement rules based on the calling context" do | |
class Foo ; end # Foo is unrefined | |
it "should not respond to the method when it is not defined in the calling context or on the Foo class (sanity check)" do | |
Foo.new.instance_eval{ proc {'Hey'.num_caps}.must_raise NoMethodError } | |
end | |
it "should respond to the method when it is defined in the calling context" do | |
using RegularStringCounts | |
Foo.new.instance_eval{ 'Hey'.num_caps.must_equal 1 } | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I hate this so much... :(