Example
View the source of a class method ...
require 'detective'
Detective.view_source('ActiveRecord::Base.find_by_sql')
Result
def find_by_sql(sql)
connection.select_all(sanitize_sql(sql), "#{name} Load").collect!
{ |record| instantiate(record) }
end
Detective is hosted on gemcutter
[sudo] gem install detective
More examples and details on Detective homepage
http://github.com/aseldawy/detective
--
Posted via http://www.ruby-forum.com/.
On Sat, Nov 21, 2009 at 9:42 PM, Ahmed Eldawy <ahmed....@badrit.com>wrote:
> Detective is a new gem build by BadrIT (www.badrit.com) to investigate
> the ruby source code.
>
> Example
> View the source of a class method ...
>
> require 'detective'
>
> Detective.view_source('ActiveRecord::Base.find_by_sql')
>
> Result
>
> def find_by_sql(sql)
> connection.select_all(sanitize_sql(sql), "#{name} Load")ollect!
> { |record| instantiate(record) }
> end
>
>
Interesting - just got a problem when have fun with it in irb:
I have a simple hello.rb:
class Foo
def bar
puts "hey"
end
end
in irb:
>> require 'hello'
=> true
>> require 'detective'
=> true
>> Detective.view_source "Foo#bar"
=> " def bar\n puts "hey"\n end\n"
>> class Foo
>> def bar
>> puts "changed"
>> end
>> end
=> nil
>> Detective.view_source "Foo#bar"
=> "Cannot find source code"
>> Foo.new.bar
changed
A bug or I did something wrong?
Thanks,
Jan
Flower Born wrote:
> On Sat, Nov 21, 2009 at 9:42 PM, Ahmed Eldawy
> <ahmed....@badrit.com>wrote:
>
--
Posted via http://www.ruby-forum.com/.
I like the idea behind Detective, but if it can't cope with dynamically
defined methods, then it won't be terribly useful in practice.
method_missing trickery and dynamic metaprogramming are fairly common in
Ruby.
Best,
--
Marnen Laibow-Koser
http://www.marnen.org
mar...@marnen.org
I tried Detective with it and here's the result
print Detective.view_source('QuickMagick::Image#resize', :rdoc)
/usr/local/lib/ruby/gems/1.8/gems/quick_magick-0.7.1/lib/quick_magick/image.rb,
line 185
185: append_to_operators(method, QuickMagick::geometry(*args) )
It showed me just the body of the method not the header. But I think
this is enough. Actually this is what ruby executes, so there's nothing
more to tell you.
For methods working using method_missing, you are correct. Detective
will not show it to you. I'll consider this in the next gem release.
I've released a new version which supports method_missing like methods.
Here's an example
Detective is now also working with method_missing …
Detective.view_source('ActiveRecord::Base#find_by_id')
Result
def method_missing(method_id, *args, &block)
method_name = method_id.to_s
if self.class.private_method_defined?(method_name)
raise NoMethodError.new("Attempt to call private method",
method_name, args)
end
# If we haven't generated any methods yet, generate them, then
# see if we've created the method we're looking for.
if !self.class.generated_methods?
self.class.define_attribute_methods
if self.class.generated_methods.include?(method_name)
return self.send(method_id, *args, &block)
end
end
if self.class.primary_key.to_s == method_name
id
elsif md = self.class.match_attribute_method?(method_name)
attribute_name, method_type = md.pre_match, md.to_s
if @attributes.include?(attribute_name)
__send__("attribute#{method_type}", attribute_name, *args,
&block)
else
super
end
elsif @attributes.include?(method_name)
read_attribute(method_name)
else
super
end
end
The trouble is that find_by_id is a class method of AR::Base, not an
instance method (you should be looking for
ActiveRecord::Base.find_by_id). It seems you have correctly returned
the instance method_missing (ActiveRecord::Base#method_missing), but
it's highly unlikely that this will fulfill a request for find_by_id.
I haven't bothered to look at the Detective source. Since you
mentioned something about finding the lines in the file and then
opening the file itself to get the source code, I suggest you may want
to take a look at ruby2ruby.
--
-yossef
So you get content of the function just like you written it, but
unfrotunatelly, all metaprogramming is lost
Marcin Raczkowski wrote:
> It's not using introspecition (like ruby2ruby) but simply finds a
> declaration of function in file!
>
> So you get content of the function just like you written it,
That's correct. It is not meant to be a kind of reverse-engineering. It
relies on the fact that the source code is *somewhere* on your machine.
It just finds it quickly and displays it to you. It needs to show the
original code with its comments and indentation. This allows the
developer to easily override a method or find bugs.
> but unfrotunatelly, all metaprogramming is lost
Not exactly. Methods overrided with a plugin or gem can still be shown
correctly. There's an example of a method overrided and it shows the new
code not the old one. Also there's another example with a method defined
using define_method and it still gets the correct source code and its
location.
However, it cannot find methods defined in a string using eval() method.
It will tell you "cannot find source code". It will not show you an
incorrect or false code. Though, I think methods defined using eval
scripts are very rare in the real world. Do you know famous examples for
it?
I'm thinking now of using introspecition with methods that I cannot find
its source code. This will be some kind of plan B. I'll consider this in
a future release.