detective 0.2.0 → 0.3.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.rdoc +42 -2
- data/VERSION +1 -1
- data/detective.gemspec +2 -2
- data/lib/detective.rb +18 -7
- data/test/test_detective.rb +50 -23
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= detective
|
2
2
|
|
3
|
-
Detective is a gem
|
3
|
+
Detective is a gem built by BadrIT (http://www.badrit.com/) to investigate the ruby source code.
|
4
4
|
Check the examples below.
|
5
5
|
|
6
6
|
== Motivation
|
@@ -9,6 +9,9 @@ Not able to know who and where that function has been overrided?
|
|
9
9
|
It's time to get help from a private Detective.
|
10
10
|
Detective allows you show the source and find the location of some ruby method.
|
11
11
|
|
12
|
+
== Installation
|
13
|
+
gem install detective
|
14
|
+
|
12
15
|
== Examples
|
13
16
|
View the source of a class method ...
|
14
17
|
require 'detective'
|
@@ -67,12 +70,49 @@ Result
|
|
67
70
|
(new) You have an alternative output ...
|
68
71
|
Detective.view_source('AuthenticatedSystem#current_user', :rdoc)
|
69
72
|
|
70
|
-
|
73
|
+
Result
|
71
74
|
/home/aseldawy/aptana_studio/archiving_system/lib/authenticated_system.rb, line 11
|
72
75
|
11: def current_user
|
73
76
|
12: @current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_user == false
|
74
77
|
13: end
|
75
78
|
|
79
|
+
(new) Detective is now also working with method_missing ...
|
80
|
+
Detective.view_source('ActiveRecord::Base#find_by_id')
|
81
|
+
|
82
|
+
Result
|
83
|
+
def method_missing(method_id, *args, &block)
|
84
|
+
method_name = method_id.to_s
|
85
|
+
|
86
|
+
if self.class.private_method_defined?(method_name)
|
87
|
+
raise NoMethodError.new("Attempt to call private method", method_name, args)
|
88
|
+
end
|
89
|
+
|
90
|
+
# If we haven't generated any methods yet, generate them, then
|
91
|
+
# see if we've created the method we're looking for.
|
92
|
+
if !self.class.generated_methods?
|
93
|
+
self.class.define_attribute_methods
|
94
|
+
if self.class.generated_methods.include?(method_name)
|
95
|
+
return self.send(method_id, *args, &block)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
if self.class.primary_key.to_s == method_name
|
100
|
+
id
|
101
|
+
elsif md = self.class.match_attribute_method?(method_name)
|
102
|
+
attribute_name, method_type = md.pre_match, md.to_s
|
103
|
+
if @attributes.include?(attribute_name)
|
104
|
+
__send__("attribute#{method_type}", attribute_name, *args, &block)
|
105
|
+
else
|
106
|
+
super
|
107
|
+
end
|
108
|
+
elsif @attributes.include?(method_name)
|
109
|
+
read_attribute(method_name)
|
110
|
+
else
|
111
|
+
super
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
76
116
|
No luck with native methods ...
|
77
117
|
Detective.view_source('String#length')
|
78
118
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/detective.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{detective}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ahmed ElDawy"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-22}
|
13
13
|
s.description = %q{A ruby gem built by BadrIT (http://www.badrit.com/) that allows you to view the source code of a method}
|
14
14
|
s.email = %q{ahmed.eldawy@badrit.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/detective.rb
CHANGED
@@ -70,11 +70,6 @@ module Detective
|
|
70
70
|
private
|
71
71
|
|
72
72
|
def self.get_location_thread(the_klass, method_name, class_method)
|
73
|
-
if class_method
|
74
|
-
raise "Invalid class method name #{method_name} for class #{the_klass}" unless the_klass.respond_to? method_name
|
75
|
-
else
|
76
|
-
raise "Invalid instance method name #{method_name} for class #{the_klass}" unless the_klass.instance_methods.include? method_name
|
77
|
-
end
|
78
73
|
result = ""
|
79
74
|
t = Thread.new do
|
80
75
|
begin
|
@@ -144,9 +139,14 @@ private
|
|
144
139
|
the_method.call *args
|
145
140
|
# If the next line executed, this indicates an error because the method should be cancelled before called
|
146
141
|
puts "method called!"
|
147
|
-
rescue => e
|
142
|
+
rescue NoMethodError => e
|
143
|
+
puts "No method found #{method_name}"
|
144
|
+
puts e.inspect
|
145
|
+
puts e.backtrace.join("\n")
|
146
|
+
rescue Exception => e
|
148
147
|
puts "error"
|
149
148
|
puts e.inspect
|
149
|
+
puts e.backtrace.join("\n")
|
150
150
|
ensure
|
151
151
|
exit!
|
152
152
|
end
|
@@ -175,7 +175,7 @@ private
|
|
175
175
|
the_method = the_klass.new.method(method_name)
|
176
176
|
# Revert initialize method
|
177
177
|
the_klass.class_eval do
|
178
|
-
#
|
178
|
+
# undef causes a warning with :initialize
|
179
179
|
# undef initialize
|
180
180
|
alias initialize old_initialize
|
181
181
|
end
|
@@ -191,6 +191,17 @@ private
|
|
191
191
|
|
192
192
|
# Return the method and its parameters
|
193
193
|
[the_method, Array.new(required_args)]
|
194
|
+
rescue NameError => e
|
195
|
+
if method_name != 'method_missing' &&
|
196
|
+
(
|
197
|
+
class_method && the_klass.respond_to?(:method_missing) ||
|
198
|
+
!class_method && the_klass.instance_methods.include?('method_missing')
|
199
|
+
)
|
200
|
+
method_name = 'method_missing'
|
201
|
+
retry
|
202
|
+
else
|
203
|
+
raise
|
204
|
+
end
|
194
205
|
end
|
195
206
|
|
196
207
|
end
|
data/test/test_detective.rb
CHANGED
@@ -4,9 +4,21 @@ class BadrIT
|
|
4
4
|
def self.hello
|
5
5
|
puts "hello BadrIT"
|
6
6
|
end
|
7
|
-
end
|
8
|
-
module IPhone; end
|
9
7
|
|
8
|
+
def hi
|
9
|
+
puts "hi BadrIT"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module IPhone
|
14
|
+
end
|
15
|
+
|
16
|
+
class SomeClass
|
17
|
+
def method_missing(args)
|
18
|
+
puts "no method called #{args}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
10
22
|
|
11
23
|
class TestDetective < Test::Unit::TestCase
|
12
24
|
def test_simple_method
|
@@ -31,14 +43,8 @@ class TestDetective < Test::Unit::TestCase
|
|
31
43
|
end
|
32
44
|
|
33
45
|
def test_instance_method
|
34
|
-
BadrIT
|
35
|
-
|
36
|
-
puts "testing"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
source = Detective.view_source('BadrIT#test')
|
41
|
-
assert_equal 'def test puts "testing" end', source.gsub(/\s+/, ' ').strip
|
46
|
+
source = Detective.view_source('BadrIT#hi')
|
47
|
+
assert_equal 'def hi puts "hi BadrIT" end', source.gsub(/\s+/, ' ').strip
|
42
48
|
end
|
43
49
|
|
44
50
|
def test_method_with_args
|
@@ -93,14 +99,9 @@ class TestDetective < Test::Unit::TestCase
|
|
93
99
|
def test_using_threads
|
94
100
|
fork_supported = Detective.const_get(:ForkSupported)
|
95
101
|
Detective.const_set(:ForkSupported, false)
|
96
|
-
BadrIT.class_eval do
|
97
|
-
def self.noway
|
98
|
-
puts "Go away"
|
99
|
-
end
|
100
|
-
end
|
101
102
|
|
102
|
-
source = Detective.view_source('BadrIT.
|
103
|
-
assert_equal 'def self.
|
103
|
+
source = Detective.view_source('BadrIT.hello')
|
104
|
+
assert_equal 'def self.hello puts "hello BadrIT" end', source.gsub(/\s+/, ' ').strip
|
104
105
|
|
105
106
|
Detective.const_set(:ForkSupported, fork_supported)
|
106
107
|
end
|
@@ -109,14 +110,10 @@ class TestDetective < Test::Unit::TestCase
|
|
109
110
|
BadrIT.class_eval do
|
110
111
|
def initialize(arg0, arg1, arg2)
|
111
112
|
end
|
112
|
-
|
113
|
-
def some_method
|
114
|
-
puts "me myself"
|
115
|
-
end
|
116
113
|
end
|
117
114
|
|
118
|
-
source = Detective.view_source('BadrIT#
|
119
|
-
assert_equal 'def
|
115
|
+
source = Detective.view_source('BadrIT#hi')
|
116
|
+
assert_equal 'def hi puts "hi BadrIT" end', source.gsub(/\s+/, ' ').strip
|
120
117
|
end
|
121
118
|
|
122
119
|
def test_method_with_eval
|
@@ -153,4 +150,34 @@ class TestDetective < Test::Unit::TestCase
|
|
153
150
|
source = Detective.view_source('BadrIT.hello', :rdoc)
|
154
151
|
assert_equal "#{__FILE__}, line 4 4: def self.hello 5: puts \"hello BadrIT\" 6: end", source.gsub(/\s+/, ' ').strip
|
155
152
|
end
|
153
|
+
|
154
|
+
def test_should_find_private_methods
|
155
|
+
BadrIT.class_eval do
|
156
|
+
private
|
157
|
+
def hidden_method
|
158
|
+
puts "secret"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
source = Detective.view_source('BadrIT#hidden_method')
|
162
|
+
assert_equal 'def hidden_method puts "secret" end', source.gsub(/\s+/, ' ').strip
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_should_find_private_class_methods
|
166
|
+
BadrIT.class_eval do
|
167
|
+
class << self
|
168
|
+
def hidden_method
|
169
|
+
puts "secret"
|
170
|
+
end
|
171
|
+
|
172
|
+
private :hidden_method
|
173
|
+
end
|
174
|
+
end
|
175
|
+
source = Detective.view_source('BadrIT.hidden_method')
|
176
|
+
assert_equal 'def hidden_method puts "secret" end', source.gsub(/\s+/, ' ').strip
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_method_missing
|
180
|
+
source = Detective.view_source('SomeClass#habal')
|
181
|
+
assert_equal 'def method_missing(args) puts "no method called #{args}" end', source.gsub(/\s+/, ' ').strip
|
182
|
+
end
|
156
183
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: detective
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ahmed ElDawy
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-22 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|