mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to ruby/spec@a6b8805
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60525 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
6530b14cee
commit
8c5b60eb22
218 changed files with 4069 additions and 328 deletions
13
spec/ruby/core/module/fixtures/refine.rb
Normal file
13
spec/ruby/core/module/fixtures/refine.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
module ModuleSpecs
|
||||
class ClassWithFoo
|
||||
def foo; "foo" end
|
||||
end
|
||||
|
||||
module PrependedModule
|
||||
def foo; "foo from prepended module"; end
|
||||
end
|
||||
|
||||
module IncludedModule
|
||||
def foo; "foo from included module"; end
|
||||
end
|
||||
end
|
10
spec/ruby/core/module/fixtures/using.rb
Normal file
10
spec/ruby/core/module/fixtures/using.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
module ModuleSpecs
|
||||
module EmptyRefinement
|
||||
end
|
||||
|
||||
module RefinementForStringToS
|
||||
refine String do
|
||||
def to_s; "hello from refinement"; end
|
||||
end
|
||||
end
|
||||
end
|
616
spec/ruby/core/module/refine_spec.rb
Normal file
616
spec/ruby/core/module/refine_spec.rb
Normal file
|
@ -0,0 +1,616 @@
|
|||
require File.expand_path('../../../spec_helper', __FILE__)
|
||||
require File.expand_path('../fixtures/refine', __FILE__)
|
||||
|
||||
describe "Module#refine" do
|
||||
it "runs its block in an anonymous module" do
|
||||
inner_self = nil
|
||||
mod = Module.new do
|
||||
refine String do
|
||||
inner_self = self
|
||||
end
|
||||
end
|
||||
|
||||
mod.should_not == inner_self
|
||||
inner_self.should be_kind_of(Module)
|
||||
inner_self.name.should == nil
|
||||
end
|
||||
|
||||
it "uses the same anonymous module for future refines of the same class" do
|
||||
selves = []
|
||||
mod = Module.new do
|
||||
refine String do
|
||||
selves << self
|
||||
end
|
||||
end
|
||||
|
||||
mod.module_eval do
|
||||
refine String do
|
||||
selves << self
|
||||
end
|
||||
end
|
||||
|
||||
selves[0].should == selves[1]
|
||||
end
|
||||
|
||||
it "adds methods defined in its block to the anonymous module's public instance methods" do
|
||||
inner_self = nil
|
||||
mod = Module.new do
|
||||
refine String do
|
||||
def blah
|
||||
"blah"
|
||||
end
|
||||
inner_self = self
|
||||
end
|
||||
end
|
||||
|
||||
inner_self.public_instance_methods.should include(:blah)
|
||||
end
|
||||
|
||||
it "returns created anonymous module" do
|
||||
inner_self = nil
|
||||
result = nil
|
||||
mod = Module.new do
|
||||
result = refine String do
|
||||
inner_self = self
|
||||
end
|
||||
end
|
||||
|
||||
result.should == inner_self
|
||||
end
|
||||
|
||||
it "raises ArgumentError if not passed an argument" do
|
||||
lambda do
|
||||
Module.new do
|
||||
refine {}
|
||||
end
|
||||
end.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "raises TypeError if not passed a class" do
|
||||
lambda do
|
||||
Module.new do
|
||||
refine("foo") {}
|
||||
end
|
||||
end.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
ruby_version_is "" ... "2.4" do
|
||||
it "raises TypeError if passed a module" do
|
||||
lambda do
|
||||
Module.new do
|
||||
refine(Enumerable) {}
|
||||
end
|
||||
end.should raise_error(TypeError)
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.4" do
|
||||
it "accepts a module as argument" do
|
||||
inner_self = nil
|
||||
Module.new do
|
||||
refine(Enumerable) do
|
||||
def blah
|
||||
end
|
||||
inner_self = self
|
||||
end
|
||||
end
|
||||
|
||||
inner_self.public_instance_methods.should include(:blah)
|
||||
end
|
||||
end
|
||||
|
||||
it "raises ArgumentError if not given a block" do
|
||||
lambda do
|
||||
Module.new do
|
||||
refine String
|
||||
end
|
||||
end.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "applies refinements to calls in the refine block" do
|
||||
result = nil
|
||||
Module.new do
|
||||
refine(String) do
|
||||
def foo; "foo"; end
|
||||
result = "hello".foo
|
||||
end
|
||||
end
|
||||
result.should == "foo"
|
||||
end
|
||||
|
||||
it "doesn't apply refinements outside the refine block" do
|
||||
Module.new do
|
||||
refine(String) {def foo; "foo"; end}
|
||||
-> () {
|
||||
"hello".foo
|
||||
}.should raise_error(NoMethodError)
|
||||
end
|
||||
end
|
||||
|
||||
it "does not apply refinements to external scopes not using the module" do
|
||||
Module.new do
|
||||
refine(String) {def foo; 'foo'; end}
|
||||
end
|
||||
|
||||
lambda {"hello".foo}.should raise_error(NoMethodError)
|
||||
end
|
||||
|
||||
# When defining multiple refinements in the same module,
|
||||
# inside a refine block all refinements from the same
|
||||
# module are active when a refined method is called
|
||||
it "makes available all refinements from the same module" do
|
||||
refinement = Module.new do
|
||||
refine Integer do
|
||||
def to_json_format
|
||||
to_s
|
||||
end
|
||||
end
|
||||
|
||||
refine Array do
|
||||
def to_json_format
|
||||
"[" + map { |i| i.to_json_format }.join(", ") + "]"
|
||||
end
|
||||
end
|
||||
|
||||
refine Hash do
|
||||
def to_json_format
|
||||
"{" + map { |k, v| k.to_s.dump + ": " + v.to_json_format }.join(", ") + "}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
|
||||
Module.new do
|
||||
using refinement
|
||||
|
||||
result = [{1 => 2}, {3 => 4}].to_json_format
|
||||
end
|
||||
|
||||
result.should == '[{"1": 2}, {"3": 4}]'
|
||||
end
|
||||
|
||||
it "does not make available methods from another refinement module" do
|
||||
refinery_integer = Module.new do
|
||||
refine Integer do
|
||||
def to_json_format
|
||||
to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
refinery_array = Module.new do
|
||||
refine Array do
|
||||
def to_json_format
|
||||
"[" + map { |i| i.to_json_format }.join(",") + "]"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
|
||||
-> () {
|
||||
Module.new do
|
||||
using refinery_integer
|
||||
using refinery_array
|
||||
|
||||
[1, 2].to_json_format
|
||||
end
|
||||
}.should raise_error(NoMethodError)
|
||||
end
|
||||
|
||||
# method lookup:
|
||||
# * The prepended modules from the refinement for C
|
||||
# * The refinement for C
|
||||
# * The included modules from the refinement for C
|
||||
# * The prepended modules of C
|
||||
# * C
|
||||
# * The included modules of C
|
||||
describe "method lookup" do
|
||||
it "looks in the object singleton class first" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
|
||||
obj = ModuleSpecs::ClassWithFoo.new
|
||||
class << obj
|
||||
def foo; "foo from singleton class"; end
|
||||
end
|
||||
result = obj.foo
|
||||
end
|
||||
|
||||
result.should == "foo from singleton class"
|
||||
end
|
||||
|
||||
it "looks in prepended modules from the refinement first" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
include ModuleSpecs::IncludedModule
|
||||
prepend ModuleSpecs::PrependedModule
|
||||
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.foo
|
||||
end
|
||||
|
||||
result.should == "foo from prepended module"
|
||||
end
|
||||
|
||||
it "looks in refinement then" do
|
||||
refinement = Module.new do
|
||||
refine(ModuleSpecs::ClassWithFoo) do
|
||||
include ModuleSpecs::IncludedModule
|
||||
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.foo
|
||||
end
|
||||
|
||||
result.should == "foo from refinement"
|
||||
end
|
||||
|
||||
it "looks in included modules from the refinement then" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
include ModuleSpecs::IncludedModule
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.foo
|
||||
end
|
||||
|
||||
result.should == "foo from included module"
|
||||
end
|
||||
|
||||
it "looks in the class then" do
|
||||
refinement = Module.new do
|
||||
refine(ModuleSpecs::ClassWithFoo) { }
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.foo
|
||||
end
|
||||
|
||||
result.should == "foo"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# methods in a subclass have priority over refinements in a superclass
|
||||
it "does not override methods in subclasses" do
|
||||
subclass = Class.new(ModuleSpecs::ClassWithFoo) do
|
||||
def foo; "foo from subclass"; end
|
||||
end
|
||||
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = subclass.new.foo
|
||||
end
|
||||
|
||||
result.should == "foo from subclass"
|
||||
end
|
||||
|
||||
context "for methods accesses indirectly" do
|
||||
ruby_version_is "" ... "2.4" do
|
||||
it "is not honored by Kernel#send" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.send :foo
|
||||
end
|
||||
|
||||
result.should == "foo"
|
||||
end
|
||||
|
||||
it "is not honored by BasicObject#__send__" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.__send__ :foo
|
||||
end
|
||||
|
||||
result.should == "foo"
|
||||
end
|
||||
|
||||
it "is not honored by Symbol#to_proc" do
|
||||
refinement = Module.new do
|
||||
refine Integer do
|
||||
def to_s
|
||||
"(#{super})"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = [1, 2, 3].map(&:to_s)
|
||||
end
|
||||
|
||||
result.should == ["1", "2", "3"]
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.4" do
|
||||
it "is honored by Kernel#send" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.send :foo
|
||||
end
|
||||
|
||||
result.should == "foo from refinement"
|
||||
end
|
||||
|
||||
it "is honored by BasicObject#__send__" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.__send__ :foo
|
||||
end
|
||||
|
||||
result.should == "foo from refinement"
|
||||
end
|
||||
|
||||
it "is honored by Symbol#to_proc" do
|
||||
refinement = Module.new do
|
||||
refine Integer do
|
||||
def to_s
|
||||
"(#{super})"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = [1, 2, 3].map(&:to_s)
|
||||
end
|
||||
|
||||
result.should == ["(1)", "(2)", "(3)"]
|
||||
end
|
||||
end
|
||||
|
||||
it "is honored by Kernel#binding" do
|
||||
refinement = Module.new do
|
||||
refine String do
|
||||
def to_s
|
||||
"hello from refinement"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
klass = Class.new do
|
||||
using refinement
|
||||
|
||||
def foo
|
||||
"foo".to_s
|
||||
end
|
||||
|
||||
def get_binding
|
||||
binding
|
||||
end
|
||||
end
|
||||
|
||||
result = Kernel.eval("self.foo()", klass.new.get_binding)
|
||||
result.should == "hello from refinement"
|
||||
end
|
||||
|
||||
it "is not honored by Kernel#method" do
|
||||
klass = Class.new
|
||||
refinement = Module.new do
|
||||
refine klass do
|
||||
def foo; end
|
||||
end
|
||||
end
|
||||
|
||||
-> {
|
||||
Module.new do
|
||||
using refinement
|
||||
klass.new.method(:foo)
|
||||
end
|
||||
}.should raise_error(NameError, /undefined method `foo'/)
|
||||
end
|
||||
|
||||
it "is not honored by Kernel#respond_to?" do
|
||||
klass = Class.new
|
||||
refinement = Module.new do
|
||||
refine klass do
|
||||
def foo; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = klass.new.respond_to?(:foo)
|
||||
end
|
||||
|
||||
result.should == false
|
||||
end
|
||||
end
|
||||
|
||||
context "when super is called in a refinement" do
|
||||
it "looks in the included to refinery module" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
include ModuleSpecs::IncludedModule
|
||||
|
||||
def foo
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.foo
|
||||
end
|
||||
|
||||
result.should == "foo from included module"
|
||||
end
|
||||
|
||||
it "looks in the refined class" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = ModuleSpecs::ClassWithFoo.new.foo
|
||||
end
|
||||
|
||||
result.should == "foo"
|
||||
end
|
||||
|
||||
# super in a method of a refinement invokes the method in the refined
|
||||
# class even if there is another refinement which has been activated
|
||||
# in the same context.
|
||||
it "looks in the refined class even if there is another active refinement" do
|
||||
refinement = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo
|
||||
"foo from refinement"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
refinement_with_super = Module.new do
|
||||
refine ModuleSpecs::ClassWithFoo do
|
||||
def foo
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
using refinement_with_super
|
||||
result = ModuleSpecs::ClassWithFoo.new.foo
|
||||
end
|
||||
|
||||
result.should == "foo"
|
||||
end
|
||||
end
|
||||
|
||||
# Refinements are inherited by module inclusion.
|
||||
# That is, using activates all refinements in the ancestors of the specified module.
|
||||
# Refinements in a descendant have priority over refinements in an ancestor.
|
||||
context "module inclusion" do
|
||||
it "activates all refinements from all ancestors" do
|
||||
refinement_included = Module.new do
|
||||
refine Integer do
|
||||
def to_json_format
|
||||
to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
refinement = Module.new do
|
||||
include refinement_included
|
||||
|
||||
refine Array do
|
||||
def to_json_format
|
||||
"[" + map { |i| i.to_s }.join(", ") + "]"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = [5.to_json_format, [1, 2, 3].to_json_format]
|
||||
end
|
||||
|
||||
result.should == ["5", "[1, 2, 3]"]
|
||||
end
|
||||
|
||||
it "overrides methods of ancestors by methods in descendants" do
|
||||
refinement_included = Module.new do
|
||||
refine Integer do
|
||||
def to_json_format
|
||||
to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
refinement = Module.new do
|
||||
include refinement_included
|
||||
|
||||
refine Integer do
|
||||
def to_json_format
|
||||
"hello from refinement"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = 5.to_json_format
|
||||
end
|
||||
|
||||
result.should == "hello from refinement"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
276
spec/ruby/core/module/using_spec.rb
Normal file
276
spec/ruby/core/module/using_spec.rb
Normal file
|
@ -0,0 +1,276 @@
|
|||
require File.expand_path('../../../spec_helper', __FILE__)
|
||||
require File.expand_path('../fixtures/using', __FILE__)
|
||||
|
||||
describe "Module#using" do
|
||||
it "imports class refinements from module into the current class/module" do
|
||||
refinement = Module.new do
|
||||
refine Integer do
|
||||
def foo; "foo"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Module.new do
|
||||
using refinement
|
||||
result = 1.foo
|
||||
end
|
||||
|
||||
result.should == "foo"
|
||||
end
|
||||
|
||||
it "accepts module as argument" do
|
||||
refinement = Module.new do
|
||||
refine Integer do
|
||||
def foo; "foo"; end
|
||||
end
|
||||
end
|
||||
|
||||
-> () {
|
||||
Module.new do
|
||||
using refinement
|
||||
end
|
||||
}.should_not raise_error
|
||||
end
|
||||
|
||||
it "accepts module without refinements" do
|
||||
mod = Module.new
|
||||
|
||||
-> () {
|
||||
Module.new do
|
||||
using mod
|
||||
end
|
||||
}.should_not raise_error
|
||||
end
|
||||
|
||||
it "does not accept class" do
|
||||
klass = Class.new
|
||||
|
||||
-> () {
|
||||
Module.new do
|
||||
using klass
|
||||
end
|
||||
}.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it "raises TypeError if passed something other than module" do
|
||||
-> () {
|
||||
Module.new do
|
||||
using "foo"
|
||||
end
|
||||
}.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it "returns self" do
|
||||
refinement = Module.new
|
||||
|
||||
result = nil
|
||||
mod = Module.new do
|
||||
result = using refinement
|
||||
end
|
||||
|
||||
result.should equal(mod)
|
||||
end
|
||||
|
||||
it "works in classes too" do
|
||||
refinement = Module.new do
|
||||
refine Integer do
|
||||
def foo; "foo"; end
|
||||
end
|
||||
end
|
||||
|
||||
result = nil
|
||||
Class.new do
|
||||
using refinement
|
||||
result = 1.foo
|
||||
end
|
||||
|
||||
result.should == "foo"
|
||||
end
|
||||
|
||||
it "raises error in method scope" do
|
||||
mod = Module.new do
|
||||
def self.foo
|
||||
using ModuleSpecs::EmptyRefinement
|
||||
end
|
||||
end
|
||||
|
||||
-> () {
|
||||
mod.foo
|
||||
}.should raise_error(RuntimeError, /Module#using is not permitted in methods/)
|
||||
end
|
||||
|
||||
it "activates refinement even for existed objects" do
|
||||
result = nil
|
||||
|
||||
Module.new do
|
||||
klass = Class.new do
|
||||
def foo; "foo"; end
|
||||
end
|
||||
|
||||
refinement = Module.new do
|
||||
refine klass do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
obj = klass.new
|
||||
using refinement
|
||||
result = obj.foo
|
||||
end
|
||||
|
||||
result.should == "foo from refinement"
|
||||
end
|
||||
|
||||
it "activates updates when refinement reopens later" do
|
||||
result = nil
|
||||
|
||||
Module.new do
|
||||
klass = Class.new do
|
||||
def foo; "foo"; end
|
||||
end
|
||||
|
||||
refinement = Module.new do
|
||||
refine klass do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
using refinement
|
||||
|
||||
refinement.class_eval do
|
||||
refine klass do
|
||||
def foo; "foo from reopened refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
obj = klass.new
|
||||
result = obj.foo
|
||||
end
|
||||
|
||||
result.should == "foo from reopened refinement"
|
||||
end
|
||||
|
||||
describe "scope of refinement" do
|
||||
it "is active until the end of current class/module" do
|
||||
ScratchPad.record []
|
||||
|
||||
Module.new do
|
||||
Class.new do
|
||||
using ModuleSpecs::RefinementForStringToS
|
||||
ScratchPad << "1".to_s
|
||||
end
|
||||
|
||||
ScratchPad << "1".to_s
|
||||
end
|
||||
|
||||
ScratchPad.recorded.should == ["hello from refinement", "1"]
|
||||
end
|
||||
|
||||
# Refinements are lexical in scope.
|
||||
# Refinements are only active within a scope after the call to using.
|
||||
# Any code before the using statement will not have the refinement activated.
|
||||
it "is not active before the `using` call" do
|
||||
ScratchPad.record []
|
||||
|
||||
Module.new do
|
||||
Class.new do
|
||||
ScratchPad << "1".to_s
|
||||
using ModuleSpecs::RefinementForStringToS
|
||||
ScratchPad << "1".to_s
|
||||
end
|
||||
end
|
||||
|
||||
ScratchPad.recorded.should == ["1", "hello from refinement"]
|
||||
end
|
||||
|
||||
# If you call a method that is defined outside the current scope
|
||||
# the refinement will be deactivated
|
||||
it "is not active for code defined outside the current scope" do
|
||||
result = nil
|
||||
|
||||
Module.new do
|
||||
klass = Class.new do
|
||||
def foo; "foo"; end
|
||||
end
|
||||
|
||||
refinement = Module.new do
|
||||
refine klass do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
def self.call_foo(c)
|
||||
c.foo
|
||||
end
|
||||
|
||||
using refinement
|
||||
|
||||
result = call_foo(klass.new)
|
||||
end
|
||||
|
||||
result.should == "foo"
|
||||
end
|
||||
|
||||
# If a method is defined in a scope where a refinement is active
|
||||
# the refinement will be active when the method is called.
|
||||
it "is active for method defined in a scope wherever it's called" do
|
||||
klass = Class.new do
|
||||
def foo; "foo"; end
|
||||
end
|
||||
|
||||
mod = Module.new do
|
||||
refinement = Module.new do
|
||||
refine klass do
|
||||
def foo; "foo from refinement"; end
|
||||
end
|
||||
end
|
||||
|
||||
using refinement
|
||||
|
||||
def self.call_foo(c)
|
||||
c.foo
|
||||
end
|
||||
end
|
||||
|
||||
c = klass.new
|
||||
mod.call_foo(c).should == "foo from refinement"
|
||||
end
|
||||
|
||||
it "is not active if `using` call is not evaluated" do
|
||||
result = nil
|
||||
|
||||
Module.new do
|
||||
if false
|
||||
using ModuleSpecs::RefinementForStringToS
|
||||
end
|
||||
result = "1".to_s
|
||||
end
|
||||
|
||||
result.should == "1"
|
||||
end
|
||||
|
||||
# The refinements in module are not activated automatically
|
||||
# if the class is reopened later
|
||||
it "is not active when class/module reopens" do
|
||||
refinement = Module.new do
|
||||
refine String do
|
||||
def to_s
|
||||
"hello from refinement"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = []
|
||||
klass = Class.new do
|
||||
using refinement
|
||||
result << "1".to_s
|
||||
end
|
||||
|
||||
klass.class_eval do
|
||||
result << "1".to_s
|
||||
end
|
||||
|
||||
result.should == ["hello from refinement", "1"]
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue