Dockerを使った開発時にpryやirbの履歴を保存したい

こんにちは!kossyです!

今回は開発環境にDockerを使ってRailsアプリを開発する際に、pryやirbの履歴を保存する方法についてブログに残してみたいと思います。




環境
Ruby 2.6.9
Rails 6.0.3
docker-compose version 1.27.0



docker-compose.ymlの編集

まずはdocker-compose.ymlを編集します。

# docker-compose.yml

volumes:
  - history:/usr/local/history

environment:
  IRB_HISTORY_PATH: /usr/local/history/.irb_history
  PRY_HISTORY_PATH: /usr/local/history/.pry_history

environmentにirbもpryも指定していますが、「普段使うデバッガだけ記載する」でもOKです。(複数人で開発する場合はいろんなデバッガを使われる可能性があるので複数記載するでもOK)

.irbrcの作成

irbをメインのデバッガとして使いたい場合は、アプリケーションのルートディレクトリ直下に.irbrcを作成します。

# .irbrc

path = ENV['IRB_HISTORY_PATH']
if path
  IRB.conf[:HISTORY_FILE] = path
end

ENV定数からirbの履歴を保存するパスを取得し、もしパスが設定されていれば、IRBクラスのconfigにパスを指定しています。

.pryrcの作成

pryをメインのデバッガとして使いたい場合は、アプリケーションのルートディレクトリ直下に.pryrcを作成します。

# .pryrc

path = ENV['PRY_HISTORY_PATH']
if path
  Pry.config.history_file = path
end

こちらも.irbrcとやっていることはほとんど一緒で、参照するパスと扱うクラスが違うだけですね。

IRB.confのソースコードを読んでみる

せっかくなので、IRBクラスのソースコードを読んでみましょうか。

docker-composeコマンドでコンテナを立てて rails c でコンソールを立ち上げて検証してみます。

# railsという名前のコンテナを立てる
docker-compose run --rm rails bundle exec rails c
IRB.method(:conf).source_location
=> ["/usr/local/lib/ruby/2.6.0/irb.rb", 350]

source_locationを実行したところ、irb.rbの350行目にconfメソッドが生えているようです。

github.com

コメント部分の記述が詳しかったので、こちらを読んでみます。

# === History
#
# By default, irb will store the last 1000 commands you used in
# <code>IRB.conf[:HISTORY_FILE]</code> (<code>~/.irb_history</code> by default).
#
# If you want to disable history, add the following to your +.irbrc+:
#
#     IRB.conf[:SAVE_HISTORY] = nil
#

デフォルトでは1000コマンドまで保存できて、IRB.conf[:HISTORY_FILE]に保存されるとのこと。(デフォルトは~/.irb_history)

また、履歴の保存をしたくない場合は、.irbrcに IRB.conf[:SAVE_HISTORY] = nil と記載すればOKとのこと。

irb.rbは約900行ほどのファイルなのですが、1/3はコメントが記載されてました。何ができるか知りたい場合は公式ドキュメントに加えて、コメント部分も読んでみるとよさそうです。


Pry.configのソースコードを読んでみる

次はPry.configのソースコードを確認してみましょうか。

Pry.config.method(:history_file).source_location
=> ["/bundle/ruby/2.6.0/gems/pry-0.13.1/lib/pry/config/attributable.rb", 13]

実際にhistory_fileの記載があったのはこちらのファイルでした。

github.com

# @return [String]
attribute :history_file

# 省略

history_file: Pry::History.default_file,

Pry::History.default_fileの定義はこちら。

    def self.default_file
      history_file =
        if (xdg_home = Pry::Env['XDG_DATA_HOME'])
          # See XDG Base Directory Specification at
          # https://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
          xdg_home + '/pry/pry_history'
        elsif File.exist?(File.expand_path('~/.pry_history'))
          '~/.pry_history'
        else
          '~/.local/share/pry/pry_history'
        end
      File.expand_path(history_file)
    end

ざっくり言うと基本的にはpry_historyというファイルに履歴が格納されていくコードになっていました。

もう一度.pryrcのコードを見てみます。

# .pryrc

path = ENV['PRY_HISTORY_PATH']
if path
  Pry.config.history_file = path
end

history_fileがattribute として定義されていて書き込みが可能になっているので、default_fileメソッドで定義されたファイルパスを.pryrcで上書きしていることになりますね。

おわりに

dockerの場合だとvolumeの設定をしないとコマンドの実行履歴が揮発してしまうので、一手間加えないとコマンドの実行履歴が保存されないんですね。(コンテナの中で全て完結するんだからそれはそう)

IRBやPryのソースコードを読むことがほとんどなかったので、いい勉強になりました。

大いに参考にさせていただいた記事

素晴らしい記事の執筆、誠にありがとうございます。

r7kamura.com