matthew-method_lister 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown ADDED
@@ -0,0 +1,177 @@
1
+ About
2
+ =====
3
+
4
+ Method Lister is used to query objects and discover which ancestor implements
5
+ which methods. It's quite common to have a lot of mixins and several classes
6
+ in an object's class hierarchy, especially in a Rails application. To help
7
+ with this Method Lister adds the ability to find out in which classes/modules
8
+ the methods on an object are implemented.
9
+
10
+ Method Lister adds 3 methods to all objects in the system: `ls`, `grep`, and
11
+ `which`. Since these names are sometimes taken you can also use `mls`,
12
+ `mgrep`, and `mwhich`.
13
+
14
+ Method Lister is intended to be used from IRB or during debugging.
15
+
16
+ Install
17
+ =======
18
+
19
+ Get the gem:
20
+
21
+ # Add GitHub as a Gem Source (only have to do this once)
22
+ gem sources -a http://gems.github.com
23
+
24
+ # Install the gem
25
+ sudo gem install matthew-method_lister
26
+
27
+ Open up `~/.irbrc` and add these lines:
28
+
29
+ require 'rubygems'
30
+ require 'method_lister'
31
+
32
+ Usage
33
+ =====
34
+
35
+ `ls` or `mls`
36
+ -------------
37
+
38
+ The `ls` command will list all methods an object responds to, organized by the
39
+ module or class which provides the implementation. For example (results may
40
+ vary, depending on what you have loaded):
41
+
42
+ >> [].ls
43
+ ========== Module Kernel ==========
44
+ PUBLIC: inspect clone method public_methods instance_variable_defined?
45
+ equal? which freeze grep mgrep methods respond_to? dup instance_variables
46
+ __id__ object_id eql? require id singleton_methods send taint frozen?
47
+ instance_variable_get __send__ instance_of? mls to_a type mwhich
48
+ protected_methods instance_eval == display === ls instance_variable_set
49
+ kind_of? extend to_s gem hash pretty_inspect class tainted? =~
50
+ private_methods nil? untaint is_a?
51
+
52
+ ========== Module PP::ObjectMixin ==========
53
+ PUBLIC: pretty_print_instance_variables pretty_print_inspect pretty_print
54
+ pretty_print_cycle
55
+
56
+ ========== Module Enumerable ==========
57
+ PUBLIC: find_all sort_by collect include? detect max sort partition any?
58
+ to_a reject zip find min member? entries inject all? select
59
+ each_with_index grep map
60
+
61
+ ========== Class Array ==========
62
+ PUBLIC: delete_if & map! empty? indexes rindex reject last to_s assoc
63
+ reverse! sort each include? values_at slice * sort! each_index fetch +
64
+ clear pretty_print concat size join flatten! shift - eql? reverse to_ary
65
+ insert [] indices nitems inspect rassoc replace compact! []= | collect
66
+ push delete_at << frozen? reverse_each flatten hash collect! uniq! select
67
+ first to_a fill index reject! zip pack unshift compact transpose <=>
68
+ pretty_print_cycle at == slice! length uniq delete pop map
69
+
70
+ You can show protected and private methods too by passing in "true":
71
+
72
+ >> [].ls true
73
+ ========== Module Kernel ==========
74
+ PUBLIC: inspect clone method public_methods instance_variable_defined?
75
+ equal? which freeze grep mgrep methods respond_to? dup instance_variables
76
+ __id__ object_id eql? require id singleton_methods send taint frozen?
77
+ instance_variable_get __send__ instance_of? mls to_a type mwhich
78
+ protected_methods instance_eval == display === ls instance_variable_set
79
+ kind_of? extend to_s gem hash pretty_inspect class tainted? =~
80
+ private_methods nil? untaint is_a?
81
+
82
+ PRIVATE: select global_variables readline warn singleton_method_added gsub
83
+ exit! method_missing exec abort load chomp! remove_instance_variable print
84
+ eval proc untrace_var srand Integer local_variables
85
+ singleton_method_removed readlines raise chop getc gem_original_require
86
+ system at_exit putc set_trace_func rand test lambda Float p
87
+ initialize_copy singleton_method_undefined chomp fail callcc sub! syscall
88
+ sleep iterator? catch autoload puts ` pp String sprintf split caller gsub!
89
+ open block_given? throw URI gets trap sub loop Array fork format exit
90
+ chop! printf binding autoload? scan trace_var
91
+
92
+ ========== Module PP::ObjectMixin ==========
93
+ PUBLIC: pretty_print_instance_variables pretty_print_inspect pretty_print
94
+ pretty_print_cycle
95
+
96
+ ========== Class Object ==========
97
+ PRIVATE: initialize timeout irb_binding
98
+
99
+ ========== Module Enumerable ==========
100
+ PUBLIC: find_all sort_by collect include? detect max sort partition any?
101
+ to_a reject zip find min member? entries inject all? select
102
+ each_with_index grep map
103
+
104
+ ========== Class Array ==========
105
+ PUBLIC: delete_if & map! empty? indexes rindex reject last to_s assoc
106
+ reverse! sort each include? values_at slice * sort! each_index fetch +
107
+ clear pretty_print concat size join flatten! shift - eql? reverse to_ary
108
+ insert [] indices nitems inspect rassoc replace compact! []= | collect
109
+ push delete_at << frozen? reverse_each flatten hash collect! uniq! select
110
+ first to_a fill index reject! zip pack unshift compact transpose <=>
111
+ pretty_print_cycle at == slice! length uniq delete pop map
112
+
113
+ PRIVATE: initialize_copy initialize
114
+
115
+ `grep` or `mgrep`
116
+ -----------------
117
+
118
+ The `grep` command takes a regular expression and only returns methods which
119
+ match the given regex. In this example we'll use `mgrep` since on Array
120
+ objects `grep` is already taken:
121
+
122
+ >> [].mgrep /f/
123
+ ========== Module Kernel ==========
124
+ PUBLIC: instance_variable_defined? freeze frozen? instance_of? kind_of?
125
+
126
+ ========== Module Enumerable ==========
127
+ PUBLIC: find_all find
128
+
129
+ ========== Class Array ==========
130
+ PUBLIC: delete_if fetch flatten! shift frozen? flatten first fill unshift
131
+
132
+ Similar to `ls` you can pass in an extra argument of "true" to see protected
133
+ and private methods:
134
+
135
+ >> [].mgrep /f/, true
136
+ ========== Module Kernel ==========
137
+ PUBLIC: instance_variable_defined? freeze frozen? instance_of? kind_of?
138
+
139
+ PRIVATE: method_missing set_trace_func singleton_method_undefined fail
140
+ sprintf fork format printf
141
+
142
+ ========== Module Enumerable ==========
143
+ PUBLIC: find_all find
144
+
145
+ ========== Class Array ==========
146
+ PUBLIC: delete_if fetch flatten! shift frozen? flatten first fill unshift
147
+
148
+ Note that `method_missing` is always considered a match, since it could always
149
+ potentially execute.
150
+
151
+ `which` or `mwhich`
152
+ -------------------
153
+
154
+ The `which` command is for finding which classes or modules implement the
155
+ method you're seeking. You can pass the method name in as a string or symbol.
156
+
157
+ >> [].which :to_a
158
+ ========== Module Kernel ==========
159
+ PUBLIC: to_a
160
+
161
+ ========== Module Enumerable ==========
162
+ PUBLIC: to_a
163
+
164
+ ========== Class Array ==========
165
+ PUBLIC: to_a
166
+
167
+ Logically the `which` command is the same as `grep(/^your_method$/)` and so
168
+ the same comments apply about `method_missing` and the optional parameter to
169
+ see protected/private methods.
170
+
171
+ License
172
+ =======
173
+
174
+ Copyright 2008, Matthew O'Connor All rights reserved.
175
+
176
+ This program is free software; you can redistribute it and/or modify it under
177
+ the same terms as Ruby 1.8.7 itself.
@@ -0,0 +1,77 @@
1
+ module MethodLister
2
+ class ColorDisplay < SimpleDisplay
3
+ def initialize
4
+ @ansi = AnsiEscape.new
5
+ end
6
+
7
+ private
8
+
9
+ def location_description(result)
10
+ color(super, :yellow_fg, :bold)
11
+ end
12
+
13
+ def color_method_overloaded_from_kernel(source, method)
14
+ if source != Kernel and Kernel.instance_methods.member? method
15
+ color(method, :green_fg)
16
+ end
17
+ end
18
+
19
+ def color_method_missing(source, method)
20
+ color(method, :red_fg) if method == "method_missing"
21
+ end
22
+
23
+ def color_method_array_primative(source, method)
24
+ exempt_sources = [Kernel, Fixnum, Hash, String, Enumerable, Array]
25
+ unless exempt_sources.member? source
26
+ primatives = %w{[] []= each <<}
27
+ color(method, :magenta_fg) if primatives.member? method
28
+ end
29
+ end
30
+
31
+ def process_method(result, method)
32
+ color_method(result.object, method)
33
+ end
34
+
35
+ def color_method(source, method)
36
+ coloring_methods.each do |coloring_method|
37
+ colored_method = self.send(coloring_method, source, method)
38
+ return colored_method if colored_method
39
+ end
40
+ method
41
+ end
42
+
43
+ def coloring_methods
44
+ private_methods.select {|method| method =~ /^color_method_/}
45
+ end
46
+
47
+ def color(string, *colors)
48
+ output_is_to_tty? ? @ansi.color_string(string, *colors) : string
49
+ end
50
+
51
+ def output_is_to_tty?
52
+ $stdout.tty?
53
+ end
54
+ end
55
+
56
+ class AnsiEscape
57
+ Colors = {
58
+ :none => 0, :black_fg => 30, :red_fg => 31, :green_fg => 32,
59
+ :yellow_fg => 33, :blue_fg => 34, :magenta_fg => 35, :cyan_fg => 36,
60
+ :white_fg => 37, :black_bg => 40, :red_bg => 41, :green_bg => 42,
61
+ :yellow_bg => 43, :blue_bg => 44, :magenta_bg => 45, :cyan_bg => 46,
62
+ :white_bg => 47, :bold => 1, :underline => 4, :blink => 5,
63
+ :reverse => 7, :invisible => 8
64
+ }
65
+
66
+ def color_string(string, *colors)
67
+ color_code(*colors) + string + color_code(:none)
68
+ end
69
+
70
+ private
71
+
72
+ def color_code(*colors)
73
+ ansi_codes = colors.map {|c| Colors[c]}.compact.join(";")
74
+ "\e[#{ansi_codes}m" unless ansi_codes.empty?
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,50 @@
1
+ module MethodLister
2
+ class FindResult
3
+ attr_reader :object
4
+ VISIBILITIES = [:public, :protected, :private]
5
+
6
+ def initialize(options={})
7
+ @object = options[:object] || raise(ArgumentError, "No :object given.")
8
+ @methods = Hash.new
9
+ VISIBILITIES.each do |visibility|
10
+ @methods[visibility] = options[visibility] || Array.new
11
+ end
12
+ end
13
+
14
+ def methods(visibility)
15
+ if visibility == :all
16
+ VISIBILITIES.inject(Array.new) { |result, viz| result + methods(viz) }
17
+ elsif VISIBILITIES.include? visibility
18
+ @methods[visibility]
19
+ else
20
+ raise ArgumentError, "Unknown visibility #{visibility.inspect}"
21
+ end
22
+ end
23
+
24
+ def has_methods?(visibility=:all)
25
+ !methods(visibility).empty?
26
+ end
27
+
28
+ def narrow_to_methods_matching!(rx)
29
+ VISIBILITIES.each do |visibility|
30
+ @methods[visibility] = @methods[visibility].select do |method|
31
+ method =~ rx || method == "method_missing"
32
+ end
33
+ end
34
+ self
35
+ end
36
+
37
+ def ==(other)
38
+ object.eql?(other.object) &&
39
+ methods(:all).sort == other.methods(:all).sort
40
+ end
41
+
42
+ def inspect
43
+ repr = "object=#{object.inspect}"
44
+ VISIBILITIES.each do |visibility|
45
+ repr += " #{visibility}=#{methods(visibility).sort.inspect}"
46
+ end
47
+ "<#{repr}>"
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,107 @@
1
+ module MethodLister
2
+ class Finder
3
+ def find_all(object)
4
+ @results, @seen = Array.new, Hash.new
5
+ record_methods_for_eigenclass(object)
6
+ search_class_hierarchy(object.class)
7
+ @results
8
+ end
9
+
10
+ def ls(object)
11
+ find_all(object).select { |results| results.has_methods? }
12
+ end
13
+
14
+ def grep(rx, object)
15
+ ls(object).map do |result|
16
+ result.narrow_to_methods_matching!(rx)
17
+ end.select { |result| result.has_methods? }
18
+ end
19
+
20
+ def which(method, object)
21
+ grep(/^#{Regexp.escape(method.to_s)}$/, object)
22
+ end
23
+
24
+ private
25
+
26
+ def search_class_hierarchy(klass)
27
+ while klass
28
+ scan :class, klass
29
+ klass = klass.superclass
30
+ end
31
+ end
32
+
33
+ def scan(type, klass_or_module)
34
+ unless @seen.has_key? klass_or_module
35
+ @seen[klass_or_module] = true
36
+ record_methods_for klass_or_module
37
+ scan_modules(type, klass_or_module)
38
+ end
39
+ end
40
+
41
+ def scan_modules(type, klass_or_module)
42
+ modules_for(type, klass_or_module).each do |a_module|
43
+ scan :module, a_module
44
+ end
45
+ end
46
+
47
+ def record_methods_for(klass_or_module)
48
+ record(
49
+ :object => klass_or_module,
50
+ :public => klass_or_module.public_instance_methods(false),
51
+ :protected => klass_or_module.protected_instance_methods(false),
52
+ :private => klass_or_module.private_instance_methods(false)
53
+ )
54
+ end
55
+
56
+ def record(result_options)
57
+ @results << FindResult.new(result_options)
58
+ end
59
+
60
+ def modules_for(obj_type, klass_or_module)
61
+ case obj_type
62
+ when :module
63
+ klass_or_module.included_modules
64
+ when :class
65
+ if superclass = klass_or_module.superclass
66
+ klass_or_module.included_modules - superclass.included_modules
67
+ else
68
+ klass_or_module.included_modules
69
+ end
70
+ when :eigenclass
71
+ eigenclass = get_eigenclass(klass_or_module)
72
+ eigenclass.included_modules - klass_or_module.class.included_modules
73
+ end
74
+ end
75
+
76
+ def record_methods_for_eigenclass(object)
77
+ @seen[object] = true
78
+ return unless eigenclass = get_eigenclass(object)
79
+
80
+ # This complication arises because the methods used to do reflection on
81
+ # eigenclasses will return methods from the object's class. For public
82
+ # and protected methods we can determine where the method came from, but
83
+ # for private methods we have to do a heuristic guess. c.f. scenario
84
+ # "mixed_visibility_methods.rb"
85
+ singleton_methods = object.singleton_methods(false)
86
+ public_methods = eigenclass.public_instance_methods(false)
87
+ protected_methods = eigenclass.protected_instance_methods(false)
88
+ private_methods = eigenclass.private_instance_methods(false)
89
+ ancestor_privates = eigenclass.ancestors.map do |ancestor|
90
+ ancestor.private_instance_methods(false)
91
+ end.flatten.uniq
92
+
93
+ record(:object => object,
94
+ :public => singleton_methods & public_methods,
95
+ :protected => singleton_methods & protected_methods,
96
+ :private => private_methods - ancestor_privates)
97
+
98
+ scan_modules(:eigenclass, object)
99
+ end
100
+
101
+ def get_eigenclass(object)
102
+ class << object; self; end
103
+ rescue TypeError
104
+ nil
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,24 @@
1
+ module Kernel
2
+ def mls(show_non_public=false,
3
+ displayer=MethodLister::ColorDisplay.new,
4
+ finder=MethodLister::Finder.new)
5
+ displayer.display finder.ls(self), show_non_public
6
+ end
7
+ alias :ls :mls
8
+
9
+ def mgrep(regex,
10
+ show_non_public=false,
11
+ displayer=MethodLister::ColorDisplay.new,
12
+ finder=MethodLister::Finder.new)
13
+ displayer.display finder.grep(regex, self), show_non_public
14
+ end
15
+ alias :grep :mgrep
16
+
17
+ def mwhich(method,
18
+ show_non_public=false,
19
+ displayer=MethodLister::ColorDisplay.new,
20
+ finder=MethodLister::Finder.new)
21
+ displayer.display finder.which(method, self), show_non_public
22
+ end
23
+ alias :which :mwhich
24
+ end
@@ -0,0 +1,55 @@
1
+ module MethodLister
2
+ class SimpleDisplay
3
+ def display(findings, show_non_public=false)
4
+ findings.reverse.each do |result|
5
+ list = method_list(result, show_non_public)
6
+ if !list.empty?
7
+ puts header(result)
8
+ puts list
9
+ puts seperator(result)
10
+ end
11
+ end
12
+ nil
13
+ end
14
+
15
+ private
16
+
17
+ def header(result)
18
+ "========== #{location_description(result)} =========="
19
+ end
20
+
21
+ def method_list(result, show_non_public)
22
+ FindResult::VISIBILITIES.map do |visibility|
23
+ (visibility == :public || show_non_public) ?
24
+ method_set(result, visibility) :
25
+ nil
26
+ end.compact.join("\n\n")
27
+ end
28
+
29
+ def method_set(result, visibility)
30
+ if result.has_methods?(visibility)
31
+ "#{visibility.to_s.upcase}: " +
32
+ result.methods(visibility).map {|method|
33
+ process_method(result, method)
34
+ }.join(" ")
35
+ else
36
+ nil
37
+ end
38
+ end
39
+
40
+ def process_method(result, method)
41
+ method
42
+ end
43
+
44
+ def seperator(result)
45
+ ""
46
+ end
47
+
48
+ def location_description(result)
49
+ object = result.object
50
+ return "Class #{object}" if object.kind_of? Class
51
+ return "Module #{object}" if object.kind_of? Module
52
+ return "Eigenclass"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ $: << File.expand_path(File.dirname(__FILE__))
2
+
3
+ require 'method_lister/find_result'
4
+ require 'method_lister/finder'
5
+ require 'method_lister/simple_display'
6
+ require 'method_lister/color_display'
7
+ require 'method_lister/ruby_ext'
@@ -0,0 +1,37 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+
3
+ describe MethodLister::ColorDisplay do
4
+ describe "#display" do
5
+ before do
6
+ @results = [
7
+ result(Object.new, :public => ["foo"]),
8
+ result(Array, :public => ["bar"] + Array.public_instance_methods(false)),
9
+ result(Kernel, :public => ["baz"] + Kernel.public_instance_methods(false)),
10
+ ]
11
+
12
+ @displayer = MethodLister::ColorDisplay.new
13
+
14
+ @output = ""
15
+ stub(@displayer).puts do |*args|
16
+ @output += args.map {|arg| arg.to_s}.join("") + "\n"
17
+ end
18
+ end
19
+
20
+ it "attempts to write out the relevant information" do
21
+ @displayer.display @results
22
+ @output.should =~ /Module Kernel.*.*Class Array.*bar.*Eigenclass.*foo/m
23
+ end
24
+
25
+ it "does not add ANSI codes if output is not a tty" do
26
+ mock(@displayer).output_is_to_tty? { false }.times(any_times)
27
+ @displayer.display @results
28
+ @output.should_not =~ /\e\[0m;/m
29
+ end
30
+
31
+ it "does add ANSI codes if output is a tty" do
32
+ mock(@displayer).output_is_to_tty? { true }.times(any_times)
33
+ @displayer.display @results
34
+ @output.should =~ /\e\[0m/m
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,162 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+
3
+ describe MethodLister::FindResult do
4
+ before do
5
+ names = %w{foo bar baz}
6
+ @public = names.map {|m| "public_#{m}"}
7
+ @protected = names.map {|m| "protected_#{m}"}
8
+ @private = names.map {|m| "private_#{m}"}
9
+ @all = @public + @protected + @private
10
+
11
+ @object = Object.new
12
+ @empty_result = MethodLister::FindResult.new(:object => @object)
13
+ @only_public = MethodLister::FindResult.new(:object => @object,
14
+ :public => @public)
15
+ @only_protected = MethodLister::FindResult.new(:object => @object,
16
+ :protected => @protected)
17
+ @only_private = MethodLister::FindResult.new(:object => @object,
18
+ :private => @private)
19
+ @mixed_result = MethodLister::FindResult.new(:object => @object,
20
+ :public => @public,
21
+ :protected => @protected,
22
+ :private => @private)
23
+ end
24
+
25
+ describe "#object" do
26
+ it "requires at least an associated object" do
27
+ lambda do
28
+ MethodLister::FindResult.new(:public => @public)
29
+ end.should raise_error(ArgumentError)
30
+ end
31
+
32
+ it "knows its associated object" do
33
+ @empty_result.object.should == @object
34
+ end
35
+ end
36
+
37
+ describe "#methods" do
38
+ it "knows all its methods" do
39
+ @empty_result.methods(:all).should be_empty
40
+ @only_public.methods(:all).should == @public
41
+ @only_protected.methods(:all).should == @protected
42
+ @only_private.methods(:all).should == @private
43
+ @mixed_result.methods(:all).should == @all
44
+ end
45
+
46
+ it "knows its public methods" do
47
+ @empty_result.methods(:public).should be_empty
48
+ @only_public.methods(:public).should == @public
49
+ @only_protected.methods(:public).should be_empty
50
+ @only_private.methods(:public).should be_empty
51
+ @mixed_result.methods(:public).should == @public
52
+ end
53
+
54
+ it "knows its protected methods" do
55
+ @empty_result.methods(:protected).should be_empty
56
+ @only_public.methods(:protected).should be_empty
57
+ @only_protected.methods(:protected).should == @protected
58
+ @only_private.methods(:protected).should be_empty
59
+ @mixed_result.methods(:protected).should == @protected
60
+ end
61
+
62
+ it "knows its private methods" do
63
+ @empty_result.methods(:private).should be_empty
64
+ @only_public.methods(:private).should be_empty
65
+ @only_protected.methods(:private).should be_empty
66
+ @only_private.methods(:private).should == @private
67
+ @mixed_result.methods(:private).should == @private
68
+ end
69
+
70
+ it "raises an exception if given an unknown visibility" do
71
+ lambda do
72
+ @empty_result.methods(:foobar)
73
+ end.should raise_error(ArgumentError)
74
+ end
75
+ end
76
+
77
+ describe "#has_methods?" do
78
+ it "knows if it has methods of any visibility" do
79
+ @empty_result.should_not have_methods
80
+ @only_public.should have_methods
81
+ @only_protected.should have_methods
82
+ @only_private.should have_methods
83
+ @mixed_result.should have_methods
84
+ end
85
+
86
+ it "knows if it has methods of visibility :all" do
87
+ @empty_result.should_not have_methods(:all)
88
+ @only_public.should have_methods(:all)
89
+ @only_protected.should have_methods(:all)
90
+ @only_private.should have_methods(:all)
91
+ @mixed_result.should have_methods(:all)
92
+ end
93
+
94
+ it "knows if it has methods of visibility :public" do
95
+ @empty_result.should_not have_methods(:public)
96
+ @only_public.should have_methods(:public)
97
+ @only_protected.should_not have_methods(:public)
98
+ @only_private.should_not have_methods(:public)
99
+ @mixed_result.should have_methods(:public)
100
+ end
101
+
102
+ it "knows if it has methods of visibility :protected" do
103
+ @empty_result.should_not have_methods(:protected)
104
+ @only_public.should_not have_methods(:protected)
105
+ @only_protected.should have_methods(:protected)
106
+ @only_private.should_not have_methods(:protected)
107
+ @mixed_result.should have_methods(:protected)
108
+ end
109
+
110
+ it "knows if it has methods of visibility :private" do
111
+ @empty_result.should_not have_methods(:private)
112
+ @only_public.should_not have_methods(:private)
113
+ @only_protected.should_not have_methods(:private)
114
+ @only_private.should have_methods(:private)
115
+ @mixed_result.should have_methods(:private)
116
+ end
117
+ end
118
+
119
+ describe "#narrow_to_methods_matching!" do
120
+ it "removes all methods not matching the given regex" do
121
+ rx = /foo/
122
+ @mixed_result.methods(:all).select {|meth| meth !~ rx}.should_not be_empty
123
+ @mixed_result.narrow_to_methods_matching!(rx)
124
+ @mixed_result.methods(:all).select {|meth| meth !~ rx}.should be_empty
125
+ end
126
+
127
+ it "never removes method_missing" do
128
+ @private << "method_missing"
129
+ rx = /foo/
130
+ @mixed_result.methods(:all).select {|meth| meth !~ rx}.should_not be_empty
131
+ @mixed_result.narrow_to_methods_matching!(rx)
132
+ @mixed_result.methods(:all).select {|meth| meth !~ rx}.should be_include("method_missing")
133
+ end
134
+ end
135
+
136
+ describe "#==" do
137
+ it "is equal if both have the same methods and object" do
138
+ @mixed_result.should == MethodLister::FindResult.new(
139
+ :object => @mixed_result.object,
140
+ :public => @mixed_result.methods(:public),
141
+ :protected => @mixed_result.methods(:protected),
142
+ :private => @mixed_result.methods(:private)
143
+ )
144
+ end
145
+
146
+ it "is not equal if both have same methods but different objects" do
147
+ @mixed_result.should_not == MethodLister::FindResult.new(
148
+ :object => Object.new,
149
+ :public => @mixed_result.methods(:public),
150
+ :protected => @mixed_result.methods(:protected),
151
+ :private => @mixed_result.methods(:private)
152
+ )
153
+ end
154
+
155
+ it "is not equal if both have the same object but different methods" do
156
+ @mixed_result.should_not == MethodLister::FindResult.new(
157
+ :object => @mixed_result.object,
158
+ :public => ["something_else"]
159
+ )
160
+ end
161
+ end
162
+ end