method_info 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,15 +1,46 @@
1
1
  = method_info
2
2
 
3
- Provides info about methods that can be called on an object and where they are defined.
3
+ Defines a method_info method on every Object which will show the methods that each of the object's ancestors has defined on it. The default settings are chosen to cause the least amount of surprise. This means the output may be a bit verbose, but there are options that can to narrow down the output to what you are interested in. The following options are provided:
4
4
 
5
- Usage:
5
+ * :format (default: nil)
6
+ - :string returns a string representation
7
+ - :array returns an array representation
8
+ - anything else prints out a string representation
9
+ * :ancestors_to_show (default: []) (Overrules the hiding of any ancestors as specified
10
+ by the :ancestors_to_exclude option)
11
+ * :ancestors_to_exclude (default: []) (If a class is excluded, all modules included
12
+ under it are excluded as well, an ancestor specified in :ancestors_to_show will be
13
+ shown regardless of the this value)
14
+ * :method_missing (default: false)
15
+ * :public_methods (default: true)
16
+ * :protected_methods (default: false)
17
+ * :private_methods (default: false)
18
+ * :singleton_methods (default: true)
19
+ * :include_name_of_excluded_ancestors (default: true)
6
20
 
7
- >> require 'method_info'
8
- => true
9
- >> "abc".method_info.ancestors
10
- => [String, Enumerable, Comparable, Object, MethodInfoMethod, Kernel]
11
- >> "abc".method_info.method_owner(:==)
12
- => String
21
+ Examples:
22
+
23
+ >> require 'method_info'
24
+ => true
25
+ >> "abc".method_info
26
+ ::: String :::
27
+ %, *, +, <<, <=>, ==, =~, [], []=, bytes, bytesize, capitalize, capitalize!, casecmp, center, chars, chomp, chomp!, chop, chop!, concat, count, crypt, delete, delete!, downcase, downcase!, dump, each, each_byte, each_char, each_line, empty?, end_with?, eql?, gsub, gsub!, hash, hex, include?, index, insert, inspect, intern, is_binary_data?, is_complex_yaml?, length, lines, ljust, lstrip, lstrip!, match, next, next!, oct, partition, replace, reverse, reverse!, rindex, rjust, rpartition, rstrip, rstrip!, scan, size, slice, slice!, split, squeeze, squeeze!, start_with?, strip, strip!, sub, sub!, succ, succ!, sum, swapcase, swapcase!, taguri, taguri=, to_f, to_i, to_s, to_str, to_sym, to_yaml, tr, tr!, tr_s, tr_s!, unpack, upcase, upcase!, upto
28
+ ::: Enumerable :::
29
+ all?, any?, collect, cycle, detect, drop, drop_while, each_cons, each_slice, each_with_index, entries, enum_cons, enum_slice, enum_with_index, find, find_all, find_index, first, grep, group_by, inject, map, max, max_by, member?, min, min_by, minmax, minmax_by, none?, one?, reduce, reject, reverse_each, select, sort, sort_by, take, take_while, to_a, zip
30
+ ::: Comparable :::
31
+ <, <=, >, >=, between?
32
+ ::: Object :::
33
+ to_yaml_properties, to_yaml_style
34
+ ::: MethodInfo::ObjectMethod :::
35
+ method_info
36
+ ::: Kernel :::
37
+ ===, __id__, __send__, class, clone, display, dup, enum_for, equal?, extend, freeze, frozen?, id, instance_eval, instance_exec, instance_of?, instance_variable_defined?, instance_variable_get, instance_variable_set, instance_variables, is_a?, kind_of?, method, methods, nil?, object_id, private_methods, protected_methods, public_methods, respond_to?, send, singleton_methods, taint, tainted?, tap, to_enum, type, untaint
38
+ Methodless: #<Class:#<String:0x13fd42c>>
39
+ => nil
40
+ ::: Symbol :::
41
+ ===, id2name, inspect, taguri, taguri=, to_i, to_int, to_proc, to_s, to_sym, to_yaml
42
+ Excluded: Object, MethodInfo::ObjectMethod, Kernel
43
+ => nil
13
44
 
14
45
  == Note on Patches/Pull Requests
15
46
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.0
data/lib/method_info.rb CHANGED
@@ -1,80 +1,4 @@
1
- module MethodInfoMethod
2
- def method_info
3
- MethodInfo.new(self)
4
- end
5
- end
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
3
 
7
- class Object
8
- include MethodInfoMethod
9
- end
10
-
11
- class MethodInfo
12
- def initialize(object)
13
- @object = object
14
- unless @object.singleton_methods.empty?
15
- @eigenclass = class << object; self; end
16
- end
17
- end
18
-
19
- def ancestors
20
- @ancestors = []
21
- if @eigenclass
22
- @ancestors << @eigenclass
23
- end
24
- @ancestors += @object.class.ancestors
25
- end
26
-
27
- # Returns the class or module where method is defined
28
- def method_owner(method)
29
- @object.method(method).owner
30
- end
31
-
32
- # Returns the same value as :method_owner, but also check if the
33
- # method is handled by a method_missing method in the chain. If it
34
- # is :method_missing is returned, otherwise the error raised is
35
- # reraised. This requires an invocation of the method which could
36
- # cause side effects. Hence this method is considered to be
37
- # dangerous.
38
- def method_owner!(method)
39
- method_owner(method)
40
- rescue NameError => e
41
- begin
42
- @object.clone.send(method)
43
- :method_missing
44
- rescue NoMethodError
45
- raise e
46
- end
47
- end
48
-
49
- def method_map
50
- @method_map = Hash.new
51
- current_ancestors = ancestors
52
- @method_map['__ancestors'] = current_ancestors
53
- current_ancestors.each do |ancestor|
54
- @method_map[ancestor] = []
55
- end
56
-
57
- @object.methods.each do |method|
58
- @method_map[method_owner(method)] << method
59
- end
60
- @method_map
61
- end
62
-
63
- def to_s
64
- map = method_map
65
-
66
- result = ""
67
- map['__ancestors'].each do |ancestor|
68
- break if ancestor == Object
69
- next if map[ancestor].empty?
70
- result +=
71
- "=== #{ancestor} ===\n" +
72
- map[ancestor].sort.join(", ") +
73
- "\n"
74
- end
75
- index_of_object = map['__ancestors'].index(Object)
76
- result +=
77
- "=== #{map['__ancestors'][index_of_object..-1].join(", ")} ==="
78
- result
79
- end
80
- end
4
+ require 'method_info/object_method'
@@ -0,0 +1,105 @@
1
+ module MethodInfo
2
+ class AncestorMethodStructure
3
+ # :ancestors_to_show (default: []) (Overrules the hiding of any ancestors as specified
4
+ # by the :ancestors_to_exclude option)
5
+ # :ancestors_to_exclude (default: []) (If a class is excluded, all modules included
6
+ # under it are excluded as well, an ancestor specified in
7
+ # :ancestors_to_show will be shown regardless of the this value)
8
+ # :method_missing (default: false)
9
+ # :public_methods (default: true)
10
+ # :protected_methods (default: false)
11
+ # :private_methods (default: false)
12
+ # :singleton_methods (default: true)
13
+ # :include_name_of_excluded_ancestors (default: true)
14
+ def self.build(object, options)
15
+ methods = []
16
+ methods += object.methods if options[:public_methods]
17
+ methods += object.protected_methods if options[:protected_methods]
18
+ methods += object.private_methods if options[:private_methods]
19
+ methods -= object.singleton_methods unless options[:singleton_methods]
20
+ ancestor_method_structure = AncestorMethodStructure.new(object, options)
21
+
22
+ methods.each do |method|
23
+ ancestor_method_structure.add_method_to_ancestor(method, method_owner(object, method))
24
+ end
25
+ ancestor_method_structure
26
+ end
27
+
28
+ def initialize(object, options)
29
+ @options = options
30
+ @ancestors = []
31
+ @excluded_ancestors = []
32
+ @ancestor_methods = {}
33
+ if options[:singleton_methods]
34
+ begin
35
+ @ancestors << (class << object; self; end)
36
+ rescue TypeError
37
+ end
38
+ end
39
+ all_ancestors = object.class.ancestors
40
+ last_class_was_excluded = false
41
+ all_ancestors.each do |ancestor|
42
+ if options[:ancestors_to_show].include?(ancestor)
43
+ @ancestors << ancestor
44
+ if ancestor.is_a?(Class)
45
+ last_class_was_excluded = false
46
+ end
47
+ elsif options[:ancestors_to_exclude].include?(ancestor)
48
+ if ancestor.is_a?(Class)
49
+ last_class_was_excluded = true
50
+ @excluded_ancestors << ancestor
51
+ end
52
+ else
53
+ if ancestor.is_a?(Class)
54
+ @ancestors << ancestor
55
+ last_class_was_excluded = false
56
+ else
57
+ if last_class_was_excluded
58
+ @excluded_ancestors << ancestor
59
+ else
60
+ @ancestors << ancestor
61
+ end
62
+ end
63
+ end
64
+ end
65
+ @ancestors.each { |ancestor| @ancestor_methods[ancestor] = [] }
66
+ end
67
+
68
+ def add_method_to_ancestor(method, ancestor)
69
+ if @ancestors.include?(ancestor)
70
+ @ancestor_methods[ancestor] << method
71
+ end
72
+ end
73
+
74
+ def to_a
75
+ ancestors_with_methods.map { |ancestor| [ancestor, @ancestor_methods[ancestor].sort] }
76
+ end
77
+
78
+ def to_s
79
+ s = ancestors_with_methods.map do |ancestor|
80
+ "::: %s :::\n%s\n" % [ancestor.to_s, @ancestor_methods[ancestor].sort.join(', ')]
81
+ end.join('')
82
+ methodless_ancestors = @ancestors.select { |ancestor| @ancestor_methods[ancestor].empty? }
83
+ if @options[:include_name_of_methodless_ancestors] && ! methodless_ancestors.empty?
84
+ s += "Methodless: " + methodless_ancestors.join(', ') + "\n"
85
+ end
86
+ if @options[:include_name_of_excluded_ancestors] && ! @excluded_ancestors.empty?
87
+ s += "Excluded: " + @excluded_ancestors.join(', ') + "\n"
88
+ end
89
+ s
90
+ end
91
+
92
+ private
93
+
94
+ def ancestors_with_methods
95
+ @ancestors.
96
+ select { |ancestor| ! @ancestor_methods[ancestor].empty? }
97
+ end
98
+
99
+ # Returns the class or module where method is defined
100
+ def self.method_owner(object, method)
101
+ object.method(method).owner
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,30 @@
1
+ require 'method_info/option_handler'
2
+
3
+ module MethodInfo
4
+ module ObjectMethod
5
+ # Provides information about an object's methods.
6
+ # Options:
7
+ # :format (default: nil)
8
+ # - :string returns a string representation
9
+ # - :array returns an array representation
10
+ # - anything else prints out a string representation
11
+ # :ancestors_to_show (default: []) (Overrules the hiding of any ancestors as specified
12
+ # by the :ancestors_to_exclude option)
13
+ # :ancestors_to_exclude (default: []) (If a class is excluded, all modules included
14
+ # under it are excluded as well, an ancestor specified in
15
+ # :ancestors_to_show will be shown regardless of the this value)
16
+ # :method_missing (default: false)
17
+ # :public_methods (default: true)
18
+ # :protected_methods (default: false)
19
+ # :private_methods (default: false)
20
+ # :singleton_methods (default: true)
21
+ # :include_name_of_excluded_ancestors (default: true)
22
+ def method_info(options = {})
23
+ OptionHandler.handle(self, options)
24
+ end
25
+ end
26
+ end
27
+
28
+ class Object
29
+ include MethodInfo::ObjectMethod
30
+ end
@@ -0,0 +1,44 @@
1
+ require 'method_info/ancestor_method_structure'
2
+
3
+ module MethodInfo
4
+ class OptionHandler
5
+ def self.handle(object, options = {})
6
+ processed_options = process_options(options)
7
+ format = processed_options.delete(:format)
8
+ ancestor_method_structure = AncestorMethodStructure.build(object, processed_options)
9
+ if format == :string
10
+ ancestor_method_structure.to_s
11
+ elsif format == :array
12
+ ancestor_method_structure.to_a
13
+ elsif format
14
+ raise(ArgumentError.new("Unknown value for :format option. Supported values are: nil, :array, :string"))
15
+ else
16
+ puts ancestor_method_structure
17
+ end
18
+ end
19
+
20
+ def self.default_profile
21
+ {
22
+ :ancestors_to_show => [],
23
+ :ancestors_to_exclude => [],
24
+ :format => nil,
25
+ :include_name_of_excluded_ancestors => true,
26
+ :include_name_of_methodless_ancestors => true,
27
+ :private_methods => false,
28
+ :protected_methods => false,
29
+ :singleton_methods => true,
30
+ :public_methods => true
31
+ }
32
+ end
33
+
34
+ def self.process_options(options = {})
35
+ defaults = default_profile
36
+ unknown_options = options.keys - defaults.keys
37
+ if unknown_options.empty?
38
+ defaults.merge(options)
39
+ else
40
+ raise ArgumentError.new("Unsupported options: " + unknown_options.map { |k| k.to_s }.sort.join(', '))
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'method_info/ancestor_method_structure'
3
+
4
+ module MethodInfo
5
+ describe AncestorMethodStructure do
6
+ describe "class" do
7
+ it "should have specs"
8
+ end
9
+
10
+ describe "AncestorMethodStructure::build" do
11
+ it "should print the methods on an object" do
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'method_info/object_method'
3
+
4
+ module MethodInfo
5
+ module ObjectMethod
6
+ describe "method_info" do
7
+ it "passes the object it was called on to the option handler" do
8
+ @obj = Object.new
9
+ OptionHandler.should_receive(:handle).with(@obj, anything)
10
+ @obj.method_info
11
+ end
12
+
13
+ it "passes its options to the option handler" do
14
+ OptionHandler.should_receive(:handle).with(anything, { :a => :one, :b => :two })
15
+ Object.method_info(:a => :one, :b => :two)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,102 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'method_info/option_handler'
3
+
4
+ module MethodInfo
5
+ def suppressing_output
6
+ output = $stdout
7
+ $stdout = File.open('/dev/null', 'w')
8
+ yield
9
+ ensure
10
+ $stdout = output
11
+ end
12
+
13
+ describe OptionHandler do
14
+ before do
15
+ OptionHandler.stub!(:puts)
16
+ end
17
+
18
+ describe "handle" do
19
+ describe "processing options" do
20
+ it "raises an argument error when an unsupported option is passed" do
21
+ lambda { MethodInfo::OptionHandler.handle(:object, :unknown_option => :one) }.
22
+ should raise_error(ArgumentError)
23
+ end
24
+
25
+ it "raises an error mentioning any unsupported options, ordered alphabetically" do
26
+ lambda { MethodInfo::OptionHandler.handle(:object, :unknown_option => :one, :another => :two) }.
27
+ should raise_error(ArgumentError, "Unsupported options: another, unknown_option")
28
+ end
29
+
30
+ it "uses a value from the default profile if an option was not passed" do
31
+ MethodInfo::OptionHandler.stub!(:default_profile).and_return({ :mock_option, :mock_value })
32
+ AncestorMethodStructure.should_receive(:build).with(anything, hash_including(:mock_option => :mock_value))
33
+ MethodInfo::OptionHandler.handle(:object)
34
+ end
35
+ it "uses a value for an option if it was passed in" do
36
+ MethodInfo::OptionHandler.stub!(:default_profile).and_return({ :mock_option, :mock_value })
37
+ AncestorMethodStructure.should_receive(:build).with(anything, hash_including(:mock_option => :passed_value))
38
+ MethodInfo::OptionHandler.handle(:object, :mock_option => :passed_value)
39
+ end
40
+
41
+ it "has the correct default values for options" do
42
+ default_options = MethodInfo::OptionHandler.default_profile
43
+ default_options[:format].should == nil
44
+ default_options[:ancestors_to_show].should == []
45
+ default_options[:ancestors_to_exclude].should == []
46
+ default_options[:include_name_of_excluded_ancestors].should == true
47
+ default_options[:include_name_of_methodless_ancestors].should == true
48
+ default_options[:public_methods].should == true
49
+ default_options[:singleton_methods].should == true
50
+ default_options[:protected_methods].should == false
51
+ default_options[:private_methods].should == false
52
+ end
53
+ end
54
+
55
+ it "builds an ancestor method structure with the object" do
56
+ mock_object = mock('object')
57
+ AncestorMethodStructure.should_receive(:build).with(mock_object, anything)
58
+ MethodInfo::OptionHandler.handle(mock_object)
59
+ end
60
+
61
+ it "passes through regular options when building an ancestor method structure" do
62
+ AncestorMethodStructure.should_receive(:build).with(anything, hash_including(:private_methods => :some_value))
63
+ MethodInfo::OptionHandler.handle(:foo, { :private_methods => :some_value })
64
+ end
65
+
66
+ it "does not pass the :format option when building an ancestor method structure" do
67
+ AncestorMethodStructure.should_receive(:build).with(anything, hash_not_including(:format))
68
+ MethodInfo::OptionHandler.handle(:foo, { :format => :string })
69
+ end
70
+
71
+ it "prints the ancestor_method_structure if the :format option is not set" do
72
+ mock_ams = mock('ancestor_method_structure')
73
+ AncestorMethodStructure.stub!(:build).and_return(mock_ams)
74
+ OptionHandler.should_receive(:puts).with(mock_ams)
75
+ MethodInfo::OptionHandler.handle(:foo)
76
+ end
77
+
78
+ it "returns the array representation of the ancestor_method_structure if the :format option is :array" do
79
+ mock_ams = mock('ancestor_method_structure')
80
+ AncestorMethodStructure.stub!(:build).and_return(mock_ams)
81
+ mock_array_representation = mock('array representation')
82
+ mock_ams.should_receive(:to_a).and_return mock_array_representation
83
+ MethodInfo::OptionHandler.handle(:foo, {:format => :array}).should == mock_array_representation
84
+ end
85
+
86
+ it "returns the string representation of the ancestor_method_structure if the :format option is :string" do
87
+ mock_ams = mock('ancestor_method_structure')
88
+ AncestorMethodStructure.stub!(:build).and_return(mock_ams)
89
+ mock_string_representation = mock('string representation')
90
+ mock_ams.should_receive(:to_s).and_return mock_string_representation
91
+ MethodInfo::OptionHandler.handle(:foo, {:format => :string}).should == mock_string_representation
92
+ end
93
+
94
+ it "raises an error if the :format option is not supported" do
95
+ AncestorMethodStructure.stub!(:build)
96
+ lambda { MethodInfo::OptionHandler.handle(:foo, { :format => :unknown }) }.
97
+ should raise_error(ArgumentError,
98
+ "Unknown value for :format option. Supported values are: nil, :array, :string")
99
+ end
100
+ end
101
+ end
102
+ end
@@ -1,160 +1,9 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe MethodInfo do
4
- describe "ancestors" do
5
- it "has the ancestors that a String has on any system for a String object" do
6
- ancestors = 37.method_info.ancestors
7
- usual_ancestors = [Fixnum, Integer, Precision, Numeric, Comparable, Object, Kernel]
8
- ancestors_without_system_specific_ones = ancestors.
9
- select { |ancestor| usual_ancestors.include?(ancestor) }
10
- ancestors_without_system_specific_ones.should == usual_ancestors
11
- end
12
-
13
- it "does not contain a module that was not included" do
14
- class Forest
15
- end
16
- sherwood = Forest.new
17
- sherwood.method_info.ancestors.should_not include(Enumerable)
18
- end
19
-
20
- it "contains an included module" do
21
- class Zoo
22
- include(Enumerable)
23
- end
24
- artis = Zoo.new
25
- artis.method_info.ancestors.should include(Enumerable)
26
- end
27
-
28
- it "has an object's eigenclass as the first element if it has singleton methods" do
29
- monkey = Object.new
30
- def monkey.talk
31
- "Ook!"
32
- end
33
- eigenclass_of_monkey = class << monkey; self; end
34
- monkey.method_info.ancestors.first.should == eigenclass_of_monkey
35
- end
36
-
37
- it "does not include the object's eigenclass if it has no singleton methods" do
38
- monkey = Object.new
39
- eigenclass_of_monkey = class << monkey; self; end
40
- monkey.method_info.ancestors.should_not include(eigenclass_of_monkey)
41
- end
42
- end
43
-
44
- describe "method_owner" do
45
- class AbstractMethodOwnerDummy
46
- def abstract_instance_method
47
- :abstract_instance_method
48
- end
49
-
50
- def duplicate_instance_method
51
- :abstract_duplicate_instance_method
52
- end
53
-
54
- def method_missing(method)
55
- if method == :missing_method_handled_at_abstract
56
- return :missing_method_handled_at_abstract
57
- end
58
- super
59
- end
60
- end
61
-
62
- class ConcreteMethodOwnerDummy < AbstractMethodOwnerDummy
63
- def concrete_instance_method
64
- :concrete_instance_method
65
- end
66
-
67
- def duplicate_instance_method
68
- :concrete_duplicate_instance_method
69
- end
70
-
71
- def method_missing(method)
72
- if method == :missing_method_handled_at_concrete
73
- return :missing_method_handled_at_concrete
74
- end
75
- super
76
- end
77
- end
78
-
79
- it "is the class of the object for an instance_method" do
80
- ConcreteMethodOwnerDummy.new.method_info.method_owner(:concrete_instance_method).should ==
81
- ConcreteMethodOwnerDummy
82
- end
3
+ require 'method_info'
83
4
 
84
- it "is the superclass of an objects class if that is where the method is first defined" do
85
- ConcreteMethodOwnerDummy.new.method_info.method_owner(:abstract_instance_method).should ==
86
- AbstractMethodOwnerDummy
87
- end
88
-
89
- it "raises an error if the object does not respond to the method" do
90
- lambda { ConcreteMethodOwnerDummy.new.method_info.method_owner(:poof) }.should raise_error(NameError)
91
- end
92
-
93
- it "raises an error if the method is handled by :method_missing" do
94
- lambda { ConcreteMethodOwnerDummy.new.method_info.method_owner(:missing_method_handled_at_concrete) }.should raise_error(NameError)
95
- end
96
-
97
- describe "method_owner!" do
98
- it "is the class of the object for an instance_method" do
99
- ConcreteMethodOwnerDummy.new.method_info.method_owner!(:concrete_instance_method).should ==
100
- ConcreteMethodOwnerDummy
101
- end
102
-
103
- it "is the superclass of an objects class if that is where the method is first defined" do
104
- ConcreteMethodOwnerDummy.new.method_info.method_owner!(:abstract_instance_method).should ==
105
- AbstractMethodOwnerDummy
106
- end
107
-
108
- it "raises an error if the object does not respond to the method" do
109
- lambda { ConcreteMethodOwnerDummy.new.method_info.method_owner!(:poof) }.should raise_error(NameError)
110
- end
111
-
112
- it "is :method_missing if the concrete class handles the method" do
113
- ConcreteMethodOwnerDummy.new.method_info.method_owner!(:missing_method_handled_at_concrete).should ==
114
- :method_missing
115
- end
116
-
117
- it "is :method_missing if the abstract class handles the method" do
118
- ConcreteMethodOwnerDummy.new.method_info.method_owner!(:missing_method_handled_at_abstract).should ==
119
- :method_missing
120
- end
121
-
122
- it "is :method_missing if the object has a method_missing singleton method that handles the method" do
123
- monkey = Object.new
124
- def monkey.method_missing(method)
125
- if method == :missing_method_handled_at_singleton_method
126
- return :missing_method_handled_at_singleton_method
127
- end
128
- super
129
- end
130
- monkey.method_info.method_owner!(:missing_method_handled_at_singleton_method).should ==
131
- :method_missing
132
- end
133
-
134
- it "does not modify an object whose method_missing has side effects" do
135
- monkey = Object.new
136
- monkey.instance_eval { @hair = "brown" }
137
- def monkey.method_missing(method)
138
- @hair = "blue"
139
- end
140
- monkey.method_info.method_owner!(:unknown_method)
141
- monkey.instance_eval('@hair').should == "brown"
142
- end
143
-
144
- # Undesirable behaviour, but I don't think there is an easy way around it
145
- it "will not protect an object's objects from method_missing side effects" do
146
- monkey = Object.new
147
- monkey.instance_eval { @limbs = [:arms, :legs] }
148
- def monkey.method_missing(method)
149
- @limbs.shift
150
- end
151
- monkey.method_info.method_owner!(:unknown_method)
152
- monkey.instance_eval('@limbs').should == [:legs]
153
- end
154
-
155
- it "raises an error if the object does not respond to the method" do
156
- lambda { ConcreteMethodOwnerDummy.new.method_info.method_owner!(:poof) }.should raise_error(NameError)
157
- end
158
- end
5
+ describe MethodInfo do
6
+ it "defines the method_info method on instances of Object" do
7
+ Object.new.should respond_to(:method_info)
159
8
  end
160
9
  end
data/spec/spec_helper.rb CHANGED
@@ -4,6 +4,7 @@ require 'method_info'
4
4
  require 'spec'
5
5
  require 'spec/autorun'
6
6
 
7
+ require 'ruby-debug'
8
+
7
9
  Spec::Runner.configure do |config|
8
-
9
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: method_info
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom ten Thij
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-10 00:00:00 -05:00
12
+ date: 2010-02-18 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -52,6 +52,12 @@ files:
52
52
  - features/step_definitions/method_info_steps.rb
53
53
  - features/support/env.rb
54
54
  - lib/method_info.rb
55
+ - lib/method_info/ancestor_method_structure.rb
56
+ - lib/method_info/object_method.rb
57
+ - lib/method_info/option_handler.rb
58
+ - spec/method_info/ancestor_method_structure_spec.rb
59
+ - spec/method_info/object_method_spec.rb
60
+ - spec/method_info/option_handler_spec.rb
55
61
  - spec/method_info_spec.rb
56
62
  - spec/spec.opts
57
63
  - spec/spec_helper.rb
@@ -84,5 +90,8 @@ signing_key:
84
90
  specification_version: 3
85
91
  summary: Get info about an object's methods
86
92
  test_files:
93
+ - spec/method_info/ancestor_method_structure_spec.rb
94
+ - spec/method_info/object_method_spec.rb
95
+ - spec/method_info/option_handler_spec.rb
87
96
  - spec/method_info_spec.rb
88
97
  - spec/spec_helper.rb