1 require File.dirname(__FILE__) + '/../spec_helper'
3 # Language-level method behaviour
4 describe "Redefining a method" do
5 it "replaces the original method" do
14 describe "An instance method definition with a splat" do
15 it "accepts an unnamed '*' argument" do
19 foo(1, 2).should == nil
20 foo(1, 2, 3, 4, :a, :b, 'c', 'd').should == nil
23 it "accepts a named * argument" do
26 foo(1, 2).should == [1, 2]
27 foo([:a]).should == [[:a]]
30 it "accepts non-* arguments before the * argument" do
31 def foo(a, b, c, d, e, *f); [a, b, c, d, e, f]; end
32 foo(1, 2, 3, 4, 5, 6, 7, 8).should == [1, 2, 3, 4, 5, [6, 7, 8]]
35 it "creates a method that can be invoked with an inline hash argument" do
36 def foo(a,b,*c); [a,b,c] end
38 foo('abc', 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'shit', *[789, 'yeah']).
40 ['abc', { 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'shit'}, [789, 'yeah']]
43 it "creates a method that can be invoked with an inline hash and a block" do
44 def foo(a,b,*c,&d); [a,b,c,yield(d)] end
46 foo('abc', 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'shit', *[789, 'yeah']) { 3 }.
48 ['abc', { 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'shit'}, [789, 'yeah'], 3]
50 foo('abc', 'rbx' => 'cool', 'specs' => 'fail sometimes', *[789, 'yeah']) do 3 end.should ==
51 ['abc', { 'rbx' => 'cool', 'specs' => 'fail sometimes' }, [789, 'yeah'], 3]
55 foo('abc', 'rbx' => 'cool', 'specs' => 'fail sometimes', *[789, 'yeah'], &l).should ==
56 ['abc', { 'rbx' => 'cool', 'specs' => 'fail sometimes' }, [789, 'yeah'], 3]
59 it "allows only a single * argument" do
60 lambda { eval 'def foo(a, *b, *c); end' }.should raise_error(SyntaxError)
63 it "requires the presence of any arguments that precede the *" do
64 def foo(a, b, *c); end
65 lambda { foo 1 }.should raise_error(ArgumentError)
69 describe "An instance method with a default argument" do
70 it "evaluates the default when no arguments are passed" do
78 it "assigns an empty Array to an unused splat argument" do
83 foo(2).should == [2, []]
86 it "evaluates the default when required arguments precede it" do
90 lambda { foo }.should raise_error(ArgumentError)
91 foo(1).should == [1, 2]
94 it "prefers to assign to a default argument before a splat argument" do
98 lambda { foo }.should raise_error(ArgumentError)
99 foo(1).should == [1,2,[]]
102 it "prefers to assign to a default argument when there are no required arguments" do
103 def foo(a = 1, *args)
106 foo(2,2).should == [2,[2]]
109 it "does not evaluate the default when passed a value and a * argument" do
110 def foo(a, b = 2, *args)
113 foo(2,3,3).should == [2,3,[3]]
117 describe "A singleton method definition" do
118 it "can be declared for a local variable" do
126 it "can be declared for an instance variable" do
134 it "can be declared for a global variable" do
139 $__a__.foo.should == 7
142 it "can be declared for a class variable" do
150 it "can be declared with an empty method body" do
154 DefSpec.foo.should == nil
158 describe "A method defined with extreme default arguments" do
159 it "can redefine itself when the default is evaluated" do
161 def foo(x = (def foo; "hello"; end;1));x;end
165 d.foo(42).should == 42
167 d.foo.should == 'hello'
170 it "may use an fcall as a default" do
171 def foo(x = caller())
174 foo.shift.class.should == String
177 it "evaluates the defaults in the method's scope" do
178 def foo(x = ($foo_self = self; nil)); end
180 $foo_self.should == self
183 it "may use preceding arguments as defaults" do
184 def foo(obj, width=obj.length)
187 foo('abcde').should == 5
190 it "may use a lambda as a default" do
191 def foo(output = 'a', prc = lambda {|n| output * n})
194 foo.should == 'aaaaa'
198 describe "A singleton method defined with extreme default arguments" do
199 it "may use a method definition as a default" do
201 def $__a.foo(x = (def $__a.foo; "hello"; end;1));x;end
203 $__a.foo(42).should == 42
205 $__a.foo.should == 'hello'
208 it "may use an fcall as a default" do
210 def a.foo(x = caller())
213 a.foo.shift.class.should == String
216 it "evaluates the defaults in the singleton scope" do
218 def a.foo(x = ($foo_self = self; nil)); 5 ;end
220 $foo_self.should == a
223 it "may use preceding arguments as defaults" do
225 def a.foo(obj, width=obj.length)
228 a.foo('abcde').should == 5
231 it "may use a lambda as a default" do
233 def a.foo(output = 'a', prc = lambda {|n| output * n})
236 a.foo.should == 'aaaaa'
240 describe "A method definition inside a metaclass scope" do
241 it "can create a class method" do
242 class DefSpecSingleton
244 def a_class_method;self;end
248 DefSpecSingleton.a_class_method.should == DefSpecSingleton
249 lambda { Object.a_class_method }.should raise_error(NoMethodError)
252 it "can create a singleton method" do
255 def a_singleton_method;self;end
258 obj.a_singleton_method.should == obj
259 lambda { Object.new.a_singleton_method }.should raise_error(NoMethodError)
263 describe "A nested method definition" do
264 it "creates an instance method when evaluated in an instance method" do
266 def create_instance_method
267 def an_instance_method;self;end
272 obj = DefSpecNested.new
273 obj.create_instance_method.should == obj
274 obj.an_instance_method.should == obj
276 other = DefSpecNested.new
277 other.an_instance_method.should == other
279 DefSpecNested.instance_methods.should include("an_instance_method")
282 it "creates a class method when evaluated in a class method" do
285 def create_class_method
286 def a_class_method;self;end
292 lambda { DefSpecNested.a_class_method }.should raise_error(NoMethodError)
293 DefSpecNested.create_class_method.should == DefSpecNested
294 DefSpecNested.a_class_method.should == DefSpecNested
295 lambda { Object.a_class_method }.should raise_error(NoMethodError)
296 lambda { DefSpecNested.new.a_class_method }.should raise_error(NoMethodError)
299 it "creates a singleton method when evaluated in the metaclass of an instance" do
301 def create_singleton_method
303 def a_singleton_method;self;end
309 obj = DefSpecNested.new
310 obj.create_singleton_method.should == obj
311 obj.a_singleton_method.should == obj
313 other = DefSpecNested.new
314 lambda { other.a_singleton_method }.should raise_error(NoMethodError)
318 describe "A method definition inside an instance_eval" do
319 it "creates a singleton method" do
322 def an_instance_eval_method;self;end
324 obj.an_instance_eval_method.should == obj
327 lambda { other.an_instance_eval_method }.should raise_error(NoMethodError)
330 it "creates a singleton method when evaluated inside a metaclass" do
334 def a_metaclass_eval_method;self;end
337 obj.a_metaclass_eval_method.should == obj
340 lambda { other.a_metaclass_eval_method }.should raise_error(NoMethodError)
343 it "creates a class method when the receiver is a class" do
344 DefSpecNested.instance_eval do
345 def an_instance_eval_class_method;self;end
348 DefSpecNested.an_instance_eval_class_method.should == DefSpecNested
349 lambda { Object.an_instance_eval_class_method }.should raise_error(NoMethodError)
353 describe "A method definition in an eval" do
354 it "creates an instance method" do
356 def eval_instance_method
357 eval "def an_eval_instance_method;self;end", binding
358 an_eval_instance_method
362 obj = DefSpecNested.new
363 obj.eval_instance_method.should == obj
364 obj.an_eval_instance_method.should == obj
366 other = DefSpecNested.new
367 other.an_eval_instance_method.should == other
369 lambda { Object.new.an_eval_instance_method }.should raise_error(NoMethodError)
372 it "creates a class method" do
375 def eval_class_method
376 eval "def an_eval_class_method;self;end" #, binding
382 DefSpecNestedB.eval_class_method.should == DefSpecNestedB
383 DefSpecNestedB.an_eval_class_method.should == DefSpecNestedB
385 lambda { Object.an_eval_class_method }.should raise_error(NoMethodError)
386 lambda { DefSpecNestedB.new.an_eval_class_method}.should raise_error(NoMethodError)
389 it "creates a singleton method" do
391 def eval_singleton_method
393 eval "def an_eval_singleton_method;self;end", binding
395 an_eval_singleton_method
399 obj = DefSpecNested.new
400 obj.eval_singleton_method.should == obj
401 obj.an_eval_singleton_method.should == obj
403 other = DefSpecNested.new
404 lambda { other.an_eval_singleton_method }.should raise_error(NoMethodError)