How to analyze quickly the code definition from a given code - ruby-on-rails

Let's say I'm in a really huge project and am curious how this line works:
authorize! :read_pipeline_schedule, user_project
authorize! is supposed to be method name. Is it a private function in the class, or DSL provided from a parent block, or including, or declared in a gem? Or maybe none of them?
I was using grep to find internal code and Google for external code such as gems, however I guess it's useful if I can see the call stack of the method. puts caller is printing from the place where I am although it can not be used for analyzing the above case.
I'd like to know the best practice.

You can grep your code and installed gems and, if name is unique enough, you'll quickly locate its definition and associated usages. However, if a name is a common one, like call, then this approach is useless.
Ruby is a dynamic language and, as such, is a nightmare for static analysis. You may guess where this comes from, but you just can't know for sure.
The only way to know is runtime introspection. So, in your example, put a breakpoint right before that line
binding.pry
authorize! :read_pipeline_schedule, user_project
You'll drop out to pry shell. Now you can do
show-source authorize!
And see where exactly this method is defined.

The easiest way is to ask the method itself:
method_object = method(:authorize!)
method_object.owner
# => returns module in which the method resides
method_object.source_location
# => returns file name and line number of source code where the method is defined
Note that source_location may return nil for methods which have no Ruby source code, e.g. dynamically generated methods or methods implemented in the interpreter internals (C functions in YARV, Java methods in JRuby, etc.)

I like caller(0), caller_locations, and the ever-incredible show-source

Related

Rails - Call a method form a model or helper with an alias

I have a helper called GlobalHelper.
There are a couple of constants (e.g. GLOBAL_URL) and methods (e.g. self.get_url) in it.
I'm trying to make an alias or an equivalent of the macros in C (#define URL) to access the constant and methods from any of my views and controllers easily.
For now I have to do it like this:
GlobalHelper.get_url(GlobalHelper::URL_TYPE_PAGE, ["page1"])
And I want to get rid of the GlobalHelper everywhere with alias/macro to get a code like this instead:
aliasmethod(aliasconstant, ["page1"])
How can I do that?
ruby is not c, so you should take a look how to write ideomatic ruby code before trying to bring such concepts into your project.
since i don't know what exactly your get_url method does, i can only give limited recommendations.
one thing that would probably result in much nicer code is using symbols instead of constants:
GlobalHelper.get_url(:page, ["page1"])
when using a Module instead of Class you can include it and call the method directly:
include GlobalHelper
get_url(...)
these are just examples of what could be done. not saying that this is better than explicitly calling GlobalHelper directly. nothing wrong with that at all.

Navigating through source code efficiently in Ruby

I was trying to find the method being called when Item.where(dst: "video") is called (Item being a Mongoid model). Looking up in the source code, I see that criteria.rb is the place to go to. However, def where calls super. Then Origin::Selectable (included inside Origin::Queryable) defines it:
def where(criterion = nil)
criterion.is_a?(String) ? js_query(criterion) : expr_query(criterion)
end
Now, I would have to see where js_query and expr_query are, see what they do and so on.
It gets tough going through all this source code and modules, finding all the methods and then trying to figure out how it works.
Is there a better way to do this process to find out how things work?
You probably need to improve your editor experience. There are three remarkable abilities (besides many others like Eclipse/Aptana, NetBeans, etc):
RubyMine — not free, but probably the best one;
Atom Editor with RSense plugin — free (plugins are also available for SublimeText and TextMate2;
vim/emacs with [c|e]tags.
Depending on your choice you yield an ability to quickly navigate through your code with either Ctrl+Click or with your preferred keyboard shortcut.
Here on SO this question was asked an amount of times as well: https://stackoverflow.com/search?q=best+ruby+editor
Hope it helps.
If you know the class of the receiver (say A) and the method name (say foo), then you can do:
A.instance_method(:foo).source_location
That will give the file name and the line number in most cases. If it returns nil, then it is likely a C-defined method, which does not rely on other Ruby methods.
Another way is to use the pry gem or the method_source gem.

See where a symbol is defined in irb

I work on a pretty large rails project at work. Sometimes I need to hunt down class / constant definitions. Is there some built-in method in Ruby to do this for me? Example:
irb> SOME_CONSTANT.__file__
=> /some/path/to/a/file
This isn't exactly what you're looking for, but methods do have a .source_location method on them. You can use this to find out where a class is actually implemented. (Since ruby lets you reopen classes, this could be in multiple places)
for example, given an instance of an object, i:
i.methods.map do |method_name|
method_obj = i.method(method_name)
file, line = method_obj.source_location
file #map down to the file name
end.uniq
will give you a list of all the files where i's methods are implemented.
This will work for classes that have at least 1 method implemented in ruby. It won't work for constants, though.
At the very beginning before any file is loaded, insert a line that defines the class/constant that you want to check as something other than a module. For example, suppose you have class or other kind of constant A within your code, and want to know where it is defined. Then, at the very beginning of the main file, write
A = nil
Then, when the program is run, whenever it first meets the definition of class/constant A, it will show something like
some_path_to_a_file:line_number in `some_method': A is not a class (TypeError)
or
some_path_to_a_file:line_number: warning: already initialized constant A
Then, some_path_to_a_file:line_number will be the location where A is defined.
If you're using Ruby 1.9.2, #YenTheFirst's answer is correct: call #source_location on a Method object.
If you're using Ruby 1.8.7, then #source_location doesn't exist (yet). You'll need something like this implementation of a method. (There's another one or two floating around, but I can't find the other one real quick).

How do I find where a ruby method is declared?

I have a ruby method (deactivate!) that is on an activeRecord class. However, I can't seem to find where that method is declared.
There have been numerous developers on this project, so it could be anywhere. There is a deactivate! on an unrelated class, but it doesn't seem to get called.
Any ideas how to find all the superclasses for an instace, or where to find the code for deactivate!?
First question would be: is it an actual method? Does obj.method(:deactivate!) raise an error?
If it doesn't, then you can use Method#source_location(in Ruby 1.9 only, and backports can't support it):
obj.method(:deactivate!).source_location
If it does raise a NoMethodError, it is handled via method_missing. This makes it hard to track. If it accepts arguments, I'd try sending the wrong type and using the backtrace of the raised exception.
Are you using state_machine? If you have an event transition called :deactivate, the model will have the method #deactivate! created automatically.
When I need to find where a method is declared on some class, say 'Model', I do
Model.ancestors.find {|c| c.instance_methods(false).include? :deactivate! }
This searches the ancestor tree in the same order that ruby does for the first that has the method in instance_methods(false), which only includes non-inherited methods.
Note: before ruby 1.9, the methods were listed as strings not symbols, so it would be
Model.ancestors.find {|c| c.instance_methods(false).include?('deactivate!') }
As a first stab, try the Jump to Declaration feature of your IDE. Depending on how good your IDE's static type inference is, it should take you right there.
If that doesn't work, set a breakpoint on that call, fire up the debugger and step into the method.

When you say Ruby is reflective, does this mainly refer to "duck typing"?

I was reading a text describing Ruby and it said the following:
Ruby is considered a “reflective”
language because it’s possible for a
Ruby program to analyze itself (in
terms of its make-up), make
adjustments to the way it works, and
even overwrite its own code with other
code.
I'm confused by this term 'reflective' - is this mainly talking about the way Ruby can look at a variable and figure out whether it's an Integer or a String (duck typing), e.g.:
x = 3
x = "three" # Ruby reassigns x to a String type
To say Ruby is "reflective" means that you can, for instance, find out at runtime what methods a class has:
>> Array.methods
=> ["inspect", "private_class_method", "const_missing",
[ ... and many more ... ]
(You can do the same thing with an object of the class.)
Or you can find out what class a given object is...
>> arr = Array.new
=> []
>> arr.class
=> Array
And find out what it is within the class hierarchy...
>> arr.kind_of?
>> arr.kind_of? Array
=> true
>> arr.kind_of? String
=> false
In the quote where they say "it’s possible for a Ruby program to analyze itself" that's what they're talking about.
Other languages such as Java do that too, but with Ruby it's easier, more convenient, and more of an everyday part of using the language. Hence, Ruby is "reflective."
No, it means that you can issue a ruby command to get information about, well, just about anything. For example, you can type the command File.methods() to get a listing of all methods belonging to the File module. You can do similar things with classes and objects -- listing methods, variables, etc.
Class reopening is a good example of this. Here's a simple example:
class Integer
def moxy
if self.zero?
self - 2
elsif self.nonzero?
self + 2
end
end
end
puts 10.moxy
By reopening a standard Ruby class - Integer - and defining a new method within it called 'moxy', we can perform a newly defined operation directly on a number. In this case, I've defined this made up 'moxy' method to subtract 2 from the Integer if it's zero and add two if it's nonzero. This makes the moxy method available to all objects of class Integer in Ruby. (Here we use the 'self' keyword to get the content of the integer object).
As you can see, it's a very powerful feature of Ruby.
EDIT: Some commenters have questioned whether this is really reflection. In the English language the word reflection refers to looking in on your own thoughts. And that's certainly an important aspect of reflection in programming also - using Ruby methods like is_a, kind_of, instance_of to perform runtime self-inspection. But reflection also refers to the the ability of a program to modify its own behavior at runtime. Reopening classes is one of the key examples of this. It's also called monkey patching. It's not without its risks but all I am doing is describing it here in the context of reflection, of which it is an example.
It refers mainly at how easy is to inspect and modify internal representations during run-time in Ruby programs, such as classes, constants, methods and so on.
Most modern languages offer some kind of reflective capabilities (even statically typed ones such as Java), but in Ruby, it is so easy and natural to use these capabilities, that it really make a real difference when you need them.
It just makes meta-programming, for example, an almost trivial task, which is not true at all in other languages, even dynamic ones.

Resources