开发者

Finding out where methods are defined in Ruby/Rails (as opposed to Java)

开发者 https://www.devze.com 2023-03-30 05:03 出处:网络
I am just getting started with Ruby on Rails. Coming from the Java world, one thing that I am wondering is how do Ruby/Rails developers find out where methods are actu开发者_开发百科ally defined.

I am just getting started with Ruby on Rails. Coming from the Java world, one thing that I am wondering is how do Ruby/Rails developers find out where methods are actu开发者_开发百科ally defined.

I am used to just clicking on the method in Eclipse to find where is is defined even in third party libraries (supposing I have the source code).

A concrete example: I am trying to find out how the Authlogic gem apparently changes the constructor of my User class to require an additional parameter (called :password_confirmation) even though the User class doesn't even inherit from anything related to Authlogic.

Probably I am just overlooking something really obvious here (or maybe I still can't wrap my head around the whole "convention over configuration" thing ;-))


It's slightly difficult to quickly find the method location for dynamic languages like Ruby.

You can use object.methods or object.instance_methods to quickly find out the methods.

If you are using Ruby 1.9, you can do something like this:

object.method(:method_name).source_location 

For more information on source_location - click here


The Pry gem is designed precisely for this kind of explorative use-case.

Pry is an interactive shell that lets you navigate your way around a program's source-code using shell-like commands such as cd and ls.

You can pull the documentation for any method you encounter and even view the source code, including the native C code in some cases (with the pry-doc plugin). You can even jump directly to the file/line where a particular method is defined with the edit-method command. The show-method and show-doc commands also display the precise location of the method they're acting on.

Watch the railscast screencast for more information.

Here are some examples below:

pry(main)> show-doc OpenStruct#initialize

From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/ostruct.rb @ line 46:
Number of lines: 11

visibility:  private
signature:  initialize(hash=?)

Create a new OpenStruct object.  The optional hash, if given, will
generate attributes and values.  For example.

  require 'ostruct'
  hash = { "country" => "Australia", :population => 20_000_000 }
  data = OpenStruct.new(hash)

  p data        # -> <OpenStruct country="Australia" population=20000000>

By default, the resulting OpenStruct object will have no attributes.

pry(main)> 

You can also look up sourcecode with the show-method command:

pry(main)> show-method OpenStruct#initialize

From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/ostruct.rb @ line 46:
Number of lines: 9

def initialize(hash=nil)
  @table = {}
  if hash
    for k,v in hash
      @table[k.to_sym] = v
      new_ostruct_member(k)
    end
  end
end
pry(main)> 

See http://pry.github.com for more information :)


None of people advising Pry gem mentionned the method called find-method, which is probably what author was looking for.

Here's the example:

pry(main)> find-method current_user

Devise::Controllers::Helpers
Devise::Controllers::Helpers#current_user
WebsocketRails::ConnectionAdapters::Base
WebsocketRails::ConnectionAdapters::Base#current_user_responds_to?

Then, you can browse the method code by following @banister's tips.


You could use something like pry. See its railscast also.


There are several ways to change an existing class. E.g. if you want to modify the String class write:

class String
  def my_custom_method
    puts "hello!"
  end
end

But there are other options like mixing in modules or adding/modifying methods by using meta-programming.

Anyhow, having some object you can always:

puts obj.methods.inspect

Either do it in your code or use the debugger.

The other option is to read the code. In particular you should read the gem's unit tests (./spec, ...). There are quite a lot of authors stating that unit tests make documentation obsolete.


In Ruby you can also add both class and instance methods to a given class by using mixins.

Essentially if you have a module you can add its methods to a given class using both include and extend class methods. A brief example on how those works is the following

Module A
  def foo
    "foo"
  end
end

Module B
  def bar
    "bar"
  end
end

Class YourClass
  include A
  extend B
end

p YourClass.new.foo # gives "foo" because the foo method is added as instance method
p YourClass.bar     # gives "baz" because the bar method is added as class method

Because Ruby is a dynamic language, these statements can be used everywhere. So to come to your question there is no need to extend an authlogic class to get its methods. Many plugins uses this instruction when loaded

ActiveRecord::Base.send :include, ModuleName

In this way they tell to every AR object to include some plugin defined module and you get all the methods in AR objects.

Another technique used by many acts_as plugins is to include their modules only when the acts_as call is used in the base class.

Other useful references

  • What is the difference between include and extend in Ruby?
  • A quick tutorial about mixins
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号