Ruby の 定番対話ツール pry 徹底攻略 | Runtime invocation #pry #ruby

# Ruby の 定番対話ツール pry 徹底攻略 | :running::coffee::flushed: Runtime invocation
## :musical_score: 概要
Ruby の 定番対話ツール pry 徹底攻略
:running::coffee::flushed: Runtime invocation について

## :running::coffee::flushed: Runtime invocation
pry は Developer Console としての機能と軽量デバッガとしての機能を持つ
irb の代替として利用される。

この用途で pry を利用する際は、実行環境で実行中のプログラムのまっただ中で
起動する必要がある。
pry はこれを簡単に実現する。

## :coffee::flushed: :link: Invoking on a binding
pry  のセッションを開始する最も一般的な方法は、 `binding.pry` です。
`binding.pry` により pry のセッションが起動すると、ローカル変数などバインドされている変数を引き継ぎます。

起動直後に、 `whereami` を実行し、
表示中のファイル名（フルパス）と
シンタックスハイライトされたソースコードを表示します

### <i class="fa fa-code" style="font-size:1em;"></i> 対象コード

~~~ruby
require 'pry'
class Hoge
  def hoge
    hage = "hoge"
    binding.pry
    puts hage
  end
end

Hoge.new.hoge
~~~

### :running: 実行
実行して、 pry の起動を確認。
起動後に `whereami` を実行して同じ内容が出力されることを確認。

![runntime_invocation1.png](https://qiita-image-store.s3.amazonaws.com/0/43480/6fe19472-8007-b6ae-9560-6b2b333e2885.png)

### :walking: 停止
`exit` で一階層戻ることを繰り返して、 起動時の階層から抜けるか
`exit-all` ( もしくは `!!@` ) で、すべての階層を一気に抜けると
pry のセッションが終了し、以降のプログラムが実行されます。

例えば、先ほどのプログラムは最後に `hage` 変数の内容を `puts` しているため、
pry のセッションが終了後に `hoge` が出力されます

~~~
$ ruby hoge.rb
From: /path/to/current/hoge.rb @ line 6 Hoge#hoge:

    3: def hoge
    4:   hage = "hoge"
    5:   binding.pry
 => 6:   puts hage
    7: end

[1] pry(#<Hoge>)> !!@
hoge
~~~

## :coffee::flushed::moyai: Invoking on an object

pry のセッションは、必ずしも `Binding` で起動しなければならないわけではない。
どんな Ruby のオブジェクトからでも pry のセッションを開始できます。

### <i class="fa fa-code" style="font-size:1em;"></i> 対象コード

~~~ruby
require 'pry'

Person = Struct.new(:name, :age) do
  def to_s
    "#{name} (#{age})"
  end
end

tanaka =Person.new('tanaka', 97)
tanaka.pry
~~~

### :running: 実行
実行して、 pry の起動を確認。

~~~
$ ruby person.rb
hoge
[1] pry(#<Person>)> name
=> "tanaka"
[2] pry(#<Person>)> age
=> 97
[3] pry(#<Person>)> to_s
=> "tanaka (97)"
[4] pry(#<Person>)> whereami
Inside #<Person>.
~~~

## :sound::seat::wrench::car: Customizing your runtime session

Binding 時に `Pry.config` の設定を行うことで
.pryrc の読み込み有無など、セッションのカスタマイズが可能です。 [^1]

さらにディープなカスタマイズをしたいなら、 command set を利用可能です。

### :link: Binding + `Pry.config`

* ~/.pryrc

~~~
puts "load .pryrc"
~~~

* ~/.pry_history

~~~
hoge = "sample history"
~~~

* test_bind.rb

~~~ruby
require 'pry'
Pry.config.should_load_rc = false
Pry.config.history.should_save = false
Pry.config.history.should_load = false

binding.pry
hoge = "last line"
~~~

* 実行結果

以上のことを確認できる。

~/.pryrc が読み込まれてないため。 "load .pryrc" が出力されない。
~/.pry_history が読み込まれてないため。 Ctrl + r で参照する履歴がない。
~/.pry_history に保存していないため、数コマンド操作後に ~/.pry_history を確認しても中身が増えていない。

~~~
$ ruby test_bind.rb

From: /path/to/current/test_bind.rb @ line 7 :

    2: Pry.config.should_load_rc = false
    3: Pry.config.history.should_save = false
    4: Pry.config.history.should_load = false
    5:
    6: binding.pry
 => 7: hoge = "last line"

[1] pry(main)> cat ~/.pry_history
hoge = "sample history"

[2] pry(main)> hoge = "test"
=> "test"
[3] pry(main)> cat ~/.pry_history
hoge = "sample history"

[4] pry(main)> hist
1: cat ~/.pry_history
2: hoge = "test"
3: cat ~/.pry_history
~~~

* test_bind.rb (設定変更して再実行する)

~~~ruby
require 'pry'
Pry.config.should_load_rc = true
Pry.config.history.should_save = true
Pry.config.history.should_load = true

binding.pry
hoge = "last line"
~~~

* 実行結果

~~~
$ ruby test_bind.rb
load .pryrc

From: /path/to/current/test_bind.rb @ line 7 :

    2: Pry.config.should_load_rc = true
    3: Pry.config.history.should_save = true
    4: Pry.config.history.should_load = true
    5:
    6: binding.pry
 => 7: hoge = "last line"
    8:

[1] pry(main)> hoge = "sample history"
=> "sample history"
[2] pry(main)> add = "add line"
=> "add line"
[3] pry(main)> add = "add line2"
=> "add line2"
[4] pry(main)> cat ~/.pry_history
hoge = "sample history"
add = "add line"
add = "add line2"
cat ~/.pry_history
~~~

### <i class="fa fa-code" style="font-size:1em;"></i> command set

* .pryrc

~~~ruby
require 'pry'
command_set = Pry::CommandSet.new do
  command "now" do |name|
    output.puts Time.now
  end
end

Pry::Commands.import command_set
~~~

* 実行

~~~
$ pry
[1] pry(main)> now
2015-01-14 13:53:57 +0900
[2] pry(main)> exit

# pryrc を読み込まない場合は、拡張した CommandSet を利用できない
$ pry -f
[1] pry(main)> now
NameError: undefined local variable or method `now' for main:Object
from (pry):1:in `__pry__'
~~~

## :point_right::worried::question: The whereami command
pry のセッション確立時に実行される `whereami` は独立したコマンドとしても実行可能です。
引数を数値で与えると、表示範囲の行数を変更できます。

### <i class="fa fa-code" style="font-size:1em;"></i> 対象コード

~~~ruby
require 'pry'
class Hoge
  def hoge
    hage = "hoge"
    binding.pry
    puts hage
  end
end

Hoge.new.hoge
~~~

### :running: 実行

~~~
$ ruby hoge.rb
load .pryrc

From: /path/to/current/hoge.rb @ line 6 Hoge#hoge:

    3: def hoge
    4:   hage = "hoge"
    5:   binding.pry
 => 6:   puts hage
    7: end

[1] pry(#<Hoge>)> whereami 10

From: /path/to/current/hoge.rb @ line 6 Hoge#hoge:

     1: require 'pry'
     2: class Hoge
     3:   def hoge
     4:     hage = "hoge"
     5:     binding.pry
 =>  6:     puts hage
     7:   end
     8: end
     9:
    10: Hoge.new.hoge
~~~

## <i class="fa fa-history" style="font-size:1em;"></i>:deciduous_tree: The pry-backtrace command
`pry-backtrace` command で、その名の通りバックトレースを参照できます。

### <i class="fa fa-code" style="font-size:1em;"></i> 対象コード
~~~ruby
require 'pry'
class Hoge
  def hoge
    binding.pry
    "hoge"
  end
end

class Hige
  def use_hoge
    Hoge.new.hoge
  end
end

def hage
  Hige.new.use_hoge
end

hage
~~~

### :running: 実行

~~~
[1] pry(#<Hoge>)> pry-backtrace
Backtrace:
--
/home/path/to/ruby/gems/2.1.0/gems/pry-byebug-2.0.0/lib/pry-byebug/processor.rb:100:in `block in resume_pry'
/home/path/to/ruby/gems/2.1.0/gems/pry-byebug-2.0.0/lib/pry-byebug/processor.rb:26:in `block in run'
/home/path/to/ruby/gems/2.1.0/gems/pry-byebug-2.0.0/lib/pry-byebug/processor.rb:25:in `catch'
/home/path/to/ruby/gems/2.1.0/gems/pry-byebug-2.0.0/lib/pry-byebug/processor.rb:25:in `run'
/home/path/to/ruby/gems/2.1.0/gems/pry-byebug-2.0.0/lib/pry-byebug/processor.rb:96:in `resume_pry'
/home/path/to/ruby/gems/2.1.0/gems/pry-byebug-2.0.0/lib/pry-byebug/processor.rb:57:in `at_line'
/home/path/to/ruby/gems/2.1.0/gems/byebug-3.5.1/lib/byebug/context.rb:80:in `at_line'
backtrace.rb:5:in `hoge'
backtrace.rb:11:in `use_hoge'
backtrace.rb:16:in `hage'
backtrace.rb:19:in `<main>'
~~~

## :man::woman: 親記事
<i class="fa fa-external-link-square" style="font-size:1em;"></i> [Ruby の 定番対話ツール pry 徹底攻略](http://qiita.com/tbpgr/items/12a60f2f9e3de61517b5)

## :books: 外部資料
* <i class="fa fa-external-link" style="font-size:1em;"></i> [pry Wiki | The Runtime invocation](https://github.com/pry/pry/wiki/Runtime-invocation)

## :books: 脚注
[^1]: <i class="fa fa-external-link" style="font-size:1em;"></i> [Ruby の 定番対話ツール pry 徹底攻略 | .pryrc file](http://qiita.com/tbpgr/items/28a438592585f592b6eb)