You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rubygem-thor/thor-fix-method-missing.patch

121 lines
4.5 KiB

commit 018b25811118c3bb95162324b3feae3a1e2b9923
Author: Yehuda Katz <wycats@gmail.com>
Date: Sat Jul 2 20:51:23 2011 -0700
Get method_missing working again. I'm not sure how it was working before, but the tests didn't pass.
# Altered a bit to work with this version.
diff --git a/lib/thor/task.rb b/lib/thor/task.rb
index 8dcff53..f94d5b6 100644
--- a/lib/thor/task.rb
+++ b/lib/thor/task.rb
@@ -18,8 +18,15 @@ class Thor
# By default, a task invokes a method in the thor class. You can change this
# implementation to create custom tasks.
def run(instance, args=[])
- public_method?(instance) ?
- instance.send(name, *args) : instance.class.handle_no_task_error(name)
+ if private_method?(instance)
+ instance.class.handle_no_task_error(name)
+ elsif public_method?(instance)
+ instance.send(name, *args)
+ elsif local_method?(instance, :method_missing)
+ instance.send(:method_missing, name.to_sym, *args)
+ else
+ instance.class.handle_no_task_error(name)
+ end
rescue ArgumentError => e
handle_argument_error?(instance, e, caller) ?
instance.class.handle_argument_error(self, e) : (raise e)
@@ -71,6 +78,15 @@ class Thor
(collection & [name.to_s, name.to_sym]).empty?
end
+ def private_method?(instance)
+ !(instance.private_methods & [name.to_s, name.to_sym]).empty?
+ end
+
+ def local_method?(instance, name)
+ methods = instance.public_methods(false) + instance.private_methods(false) + instance.protected_methods(false)
+ !(methods & [name.to_s, name.to_sym]).empty?
+ end
+
def sans_backtrace(backtrace, caller) #:nodoc:
saned = backtrace.reject { |frame| frame =~ FILE_REGEXP }
saned -= caller
@@ -105,11 +121,7 @@ class Thor
def run(instance, args=[])
if (instance.methods & [name.to_s, name.to_sym]).empty?
- if ((instance.protected_methods + instance.public_methods) & ([:method_missing, "method_missing"])).empty?
- super
- else
- instance.send(:method_missing, name.to_sym, *args)
- end
+ super
else
instance.class.handle_no_task_error(name)
end
diff --git a/spec/task_spec.rb b/spec/task_spec.rb
index 1c7ea7c..3372de1 100644
--- a/spec/task_spec.rb
+++ b/spec/task_spec.rb
@@ -11,21 +11,18 @@ describe Thor::Task do
describe "#formatted_usage" do
it "includes namespace within usage" do
- Object.stub!(:namespace).and_return("foo")
- Object.stub!(:arguments).and_return([])
- task(:bar => :required).formatted_usage(Object).should == "foo:can_has --bar=BAR"
+ object = Struct.new(:namespace, :arguments).new("foo", [])
+ task(:bar => :required).formatted_usage(object).should == "foo:can_has --bar=BAR"
end
it "removes default from namespace" do
- Object.stub!(:namespace).and_return("default:foo")
- Object.stub!(:arguments).and_return([])
- task(:bar => :required).formatted_usage(Object).should == ":foo:can_has --bar=BAR"
+ object = Struct.new(:namespace, :arguments).new("default:foo", [])
+ task(:bar => :required).formatted_usage(object).should == ":foo:can_has --bar=BAR"
end
it "injects arguments into usage" do
- Object.stub!(:namespace).and_return("foo")
- Object.stub!(:arguments).and_return([ Thor::Argument.new(:bar, nil, true, :string) ])
- task(:foo => :required).formatted_usage(Object).should == "foo:can_has BAR --foo=FOO"
+ object = Struct.new(:namespace, :arguments).new("foo", [Thor::Argument.new(:bar, nil, true, :string)])
+ task(:foo => :required).formatted_usage(object).should == "foo:can_has BAR --foo=FOO"
end
end
@@ -55,15 +52,23 @@ describe Thor::Task do
describe "#run" do
it "runs a task by calling a method in the given instance" do
mock = mock()
- mock.should_receive(:send).with("can_has", 1, 2, 3)
- task.run(mock, [1, 2, 3])
+ mock.should_receive(:can_has).and_return {|*args| args }
+ task.run(mock, [1, 2, 3]).should == [1, 2, 3]
end
it "raises an error if the method to be invoked is private" do
- mock = mock()
- mock.should_receive(:private_methods).and_return(['can_has'])
- mock.class.should_receive(:handle_no_task_error).with("can_has")
- task.run(mock)
+ klass = Class.new do
+ def self.handle_no_task_error(name)
+ name
+ end
+
+ private
+ def can_has
+ "fail"
+ end
+ end
+
+ task.run(klass.new).should == "can_has"
end
end
end