# 如果想要找某個方法的定義，該怎麼找?

> 

Published: 2016-04-27
URL: https://kaochenlong.com/use-the-source

---

在寫程式的過程中，如果遇到某個方法不會用或不知道該傳什麼參數怎麼辦? 不要急著翻 Google 或 Stackoverflow 網站，先翻官方的使用說明手冊吧，RTFM 是最好的方法！

* [Ruby API](http://ruby-doc.org/core/)
* [Rails API](http://api.rubyonrails.org/)

除了翻手冊之外，像 Ruby 或 Rails 這樣 open source 的工具，另一個好方法就是直接翻它的原始碼出來看，看看它是怎麼實作的。

&lt;!--more--&gt;

## 原始碼挖挖挖!

在開發 Ruby / Rails 專案時，通常我遇到一些很有趣或很有點厲害的寫法，就會想挖出來看看它是怎麼做的。直接開 Rails Console 來試一下：

```ruby
$ rails console
Loading development environment (Rails 5.0.0.beta3)

&gt;&gt; 3.days.ago
=&gt; Sun, 24 Apr 2016 09:02:02 UTC +00:00
```

`3.days.ago` 這樣就能印出三天前的時間，超方便! 但它怎麼做的...?

你可以使用 `method` 這個方法來回傳一個 `Method` 類別的實體，並且準備對它做一些操作：

```ruby
# 我先用 method 方法取得 `days` 這個方法物件
&gt;&gt; 3.method(:days)
=&gt; #&lt;Method: Fixnum(Numeric)#days&gt;
```

雖然「用 method 這個 method 回傳一個 Method 的實體」這句話唸起來超饒舌，但這個方法取得的物件還滿好用的，例如：

```ruby
# 使用 owner 方法取得定義這個方法的類別或模組
&gt;&gt; 3.method(:days).owner
=&gt; Numeric
```

看來是定義在 `Numeric` 這個類別或模組裡。使用 `source_location` 可以挖出檔案在哪：

```ruby
&gt;&gt; 3.method(:days).source_location
=&gt; [&quot;/Users/user/.rvm/gems/ruby-2.3.0/gems/activesupport-5.0.0.beta3/lib/active_support/core_ext/numeric/time.rb&quot;, 45]
```

既然檔案路徑都有了，就可以去打開來看看是怎麼寫的了。但如果是 Ruby 內建的方法，就沒辦法直接取得原始碼的路徑，`source_location` 方法會回傳 nil：

```ruby
&gt;&gt; method(:puts).source_location
=&gt; nil
```

那怎辦? 例如想要知道陣列內建的 `sort` 是怎麼做排序的話，就去翻翻官方手冊吧。

連到官方手冊，跳轉到關於 Array 類別的 [sort](http://ruby-doc.org/core/Array.html#method-i-sort) 章節：

![](/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBY1U9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b8d6cd477aafe01297b32a0092ead03a2f140408/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJY0c1bkJqb0dSVlE2RkhKbGMybDZaVjkwYjE5c2FXMXBkRnNIYVFJQUJXa0NBQVE9IiwiZXhwIjpudWxsLCJwdXIiOiJ2YXJpYXRpb24ifX0=--578d6799c87a604ca574298502ba874c9075e929/ruby-source-1.png)

除了介紹以及使用範例外，如果對原始檔有興趣，也可以點一下右上角的那個「放大鏡」，看看這個方法是怎麼用 C 語言實作的：

![](/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBY1k9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--6c696f39977a08733f3a7f8f70df7b197ea0cab5/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJY0c1bkJqb0dSVlE2RkhKbGMybDZaVjkwYjE5c2FXMXBkRnNIYVFJQUJXa0NBQVE9IiwiZXhwIjpudWxsLCJwdXIiOiJ2YXJpYXRpb24ifX0=--578d6799c87a604ca574298502ba874c9075e929/ruby-source-2.png)

然後就可以再繼續追下去了。如果對 Ruby 的原始碼有興趣，也可在 Github 上取得完整的原始碼。[連結](https://github.com/ruby/ruby)

## 小結

曾有朋友問，要怎麼樣才能從新手變成比較資深的開發者。

除了官網的手冊要看之外，有空挖挖原始碼、讀原始碼，看看這些大大是怎麼做出這些功能進而吸收變成自己的經驗值，都是讓你可以更快變強的好方法 :)


