From 8806a202ee9863811d3cc5d46511f5786624bafd Mon Sep 17 00:00:00 2001 From: Oleg Andreev Date: Fri, 2 May 2008 01:02:44 +0400 Subject: [PATCH] added helper Kernel#extract to work with method overloading (useful for complicated APIs like View#find) --- lib/strokedb/core_ext/kernel.rb | 28 +++++++++++++++ spec/lib/strokedb/core_ext/extract_spec.rb | 42 ++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 spec/lib/strokedb/core_ext/extract_spec.rb diff --git a/lib/strokedb/core_ext/kernel.rb b/lib/strokedb/core_ext/kernel.rb index 96ea8116..18589d74 100644 --- a/lib/strokedb/core_ext/kernel.rb +++ b/lib/strokedb/core_ext/kernel.rb @@ -15,4 +15,32 @@ def require_one_of(*args) end end + + # Helps to extract arguments for an overloaded methods: + # def some_method(*args) + # store, name, options = extract(Store, String, Hash, args) + # end + # + # This method tries to extract arguments according to their type. + # If the correct type is missing, var is set to nil. + # If some of the input arguments are not matched, ArgumentError is raised. + # + def extract(*template_and_args) + args = template_and_args.pop + result = [] + + args.each do |a| + unless while t = template_and_args.shift + if t === a + result << a + break(true) + else + result << nil + end + end + raise ArgumentError, "Unexpected argument #{a.inspect} is passed!" + end + end + result + template_and_args.map{ nil } + end end \ No newline at end of file diff --git a/spec/lib/strokedb/core_ext/extract_spec.rb b/spec/lib/strokedb/core_ext/extract_spec.rb new file mode 100644 index 00000000..cab3f573 --- /dev/null +++ b/spec/lib/strokedb/core_ext/extract_spec.rb @@ -0,0 +1,42 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "Kernel#extract" do + + it "should correctly extract various arguments" do + extract(Regexp, String, Hash, [ ]).should == [nil, nil, nil] + + extract(Regexp, String, Hash, [/a/ ]).should == [/a/, nil, nil] + extract(Regexp, String, Hash, [ "a" ]).should == [nil, "a", nil] + extract(Regexp, String, Hash, [ {1=>2}]).should == [nil, nil, {1=>2}] + + extract(Regexp, String, Hash, [//, "" ]).should == [//, "", nil] + extract(Regexp, String, Hash, [//, {}]).should == [//, nil, {} ] + extract(Regexp, String, Hash, [ "", {}]).should == [nil, "", {}] + + extract(Regexp, String, Hash, [//, "", {}]).should == [//, "", {} ] + end + + it "should raise ArgumentError when wrong arguments are passed" do + + bad_case(Regexp, String, Hash, [123]) + bad_case(Regexp, String, Hash, ["", //]) + bad_case(Regexp, String, Hash, [{}, ""]) + bad_case(Regexp, String, Hash, [true]) + bad_case(Regexp, String, Hash, [false]) + bad_case(Regexp, String, Hash, [//,false]) + bad_case(Regexp, String, Hash, [nil]) + bad_case(Regexp, String, Hash, ["", nil]) + bad_case(Regexp, String, Hash, [nil, nil]) + bad_case(Regexp, String, Hash, [{}, {}]) + bad_case(Regexp, String, Hash, [//, //]) + bad_case(Regexp, String, Hash, [ [] ]) + bad_case(Regexp, String, Hash, [Object.new]) + bad_case(Regexp, String, Hash, [Object.new, Object.new]) + + end + + def bad_case(*args) + lambda { extract(*args) }.should raise_error(ArgumentError) + end + +end \ No newline at end of file