Skip to content

Instantly share code, notes, and snippets.

@jsl
Created November 14, 2012 17:07
Show Gist options
  • Save jsl/4073369 to your computer and use it in GitHub Desktop.
Save jsl/4073369 to your computer and use it in GitHub Desktop.
Ruby Refinements
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
@zenspider
Copy link

I hate this so much... :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment