クラスメソッドをPryのコマンドにできるGemをリリースしました
作ったGemはこれです
使い方
まず.pryrc
内で下のようにクラスをセットします。
PrySingular.make_commands HogeJob, FactoryBot
これでPryの中で設定したクラスの特異メソッドをコマンドとして使うことができます。
pry(main)> perform_now
引数を渡すこともできます(あくまでコマンドなので引数との間はスペースが必要)
pry(main)> create :user
コマンドにしたいメソッドを直接指定することもできます。
PrySingular.make_commands FactoryBot, only: [:build, :attributes_for]
コマンドにしたくないメソッドを指定することもできます。
PrySingular.make_commands FactoryBot, except: :create
コマンドなのでObject
を汚してメソッドを生やすことはありません。
[1] pry(main)> self => main [2] pry(main)> self.respond_to?(:create) => false
また、内部ではsingleton_methods(true)を使っているので、class
とかrubyのコアな部分まではコマンドを設定しません。
作った理由
FactoryBotのcreate
とかActsAsTenantのwithout_tenant
とかをいちいちrails cの中で書くのめんどい〜みたいな話が周りで起こり、.pryrcの話がにわかに盛り上がりました。そのとき職場の人がPry::ClassCommand
でゴニョゴニョといっていたのを聞いたのが始まりです。
最初はFactoryBotとPryを連携させたいな〜と思って作っていたのですが、書いていくうちに「これクラス設定してもらって全部できるようにしたほうが便利だな」と思って実装してみました。
実装
コアな部分はここです
def import_class_command(klass, options) singular_methods = adapt_options_singleton_methods(klass, options) set_pry_command do singular_methods.each do |klass_method| command "#{klass_method}", "#{klass}.#{klass_method}" do extend PrySingular::Slop klass.class_eval <<-EOS #{parse_singular_method_command(Readline::HISTORY.to_a.last)} EOS end end end end def set_pry_command(&block) commands = Pry::CommandSet.new &block Pry.config.commands.import(commands) end
module PrySingular module Slop def parse_singular_method_command(items) method, args = items.split(" ", 2) method + ' ' + args.gsub(' ', '') end end end
command
はStringオブジェクトをメソッドの名前、メソッドの説明の順に引数に取って、コマンドが呼ばれたらブロックの中身を実行してくれるPryのメソッドです。
仕組みとしてはコマンドが呼ばれたらReadline::HISTORY
の最新のものを一度メソッドと引数に分けてから引数の空白を削除し、対象のクラスをレシーバーにclass_eval
して直接実行しています。
pry(main)> create :user
と呼ばれたら最終的に
FactoryBot.class_eval <<-EOS create :user EOS
が実行されるといった具合です。 なのでコマンドの実装の中身は全て、クラスにReadlineから受け取った文字列をズルっとわたしているだけです。
Gemを作ってみて
Gem作成は初めてでしたが、RubyGemsのおかげで簡単に公開することができました。
PryのDSLの柔軟性にも助けられましたし、オプションの設定方法もRailsのパクリです。 巨人の肩は高い 。
反省点としてはリリースしてはだめじゃんを繰り返して既にversionが0.1.7なことですね…
まだまだテストもカバレッジ足りないしリファクタもできると思うし、そもそもまだバグもあるかもしれないので、よいGemにできるようやっていきです。
よかったら使ってみてください、バグとかこれがあったら面白いとかあればissueやコメントで教えてくれたら泣いて喜びます。
2019/07/21 追記
インターフェースをmake_commandsにしたり内部のコードいろいろかえました
*1:ブログに乗せることも快く了承いただき本当にありがとうございます