@ledsun blog

無味の味は佳境に入らざればすなわち知れず

activerecord_umlをrails runnerから起動する

結論

このコミットです。 github.com

springを使いたい

activerecord_umlは、Railsアプリケーションを読み込んでいます。 大きなRailsアプリケーションでは起動に時間が掛かります。 RailsではGitHub - rails/spring: Rails application preloaderを使って起動時間を減らしています。

activerecord_umlもspringを使えば起動時間を短くできるはずです。

#! /usr/bin/env ruby
require "activerecord_uml"
begin
  load File.join(Dir.pwd,"bin/spring")
rescue  LoadError
end
require(File.join(Dir.pwd, "config/application"))
Rails.application.require_environment!
ActiverecordUml.draw

こんな感じです。実行してみると

~ ~/activerecord_uml/exe/activerecord_uml
Version: 2.1.1
Usage: spring COMMAND [ARGS]
Commands for Spring itself:
  binstub         Generate Spring based binstubs. Use --all to generate a binstub for all known commands. Use --remove to revert.
  help            Print available commands.
  server          Explicitly start a Spring server in the foreground
  status          Show current status.
  stop            Stop all Spring processes for this project.
Commands for your application:
  rails           Run a rails command. The following sub commands will use Spring: console, runner, generate, destroy, test.
  rake            Runs the rake command
  rspec           Runs the rspec command
(中略)
activerecord_umlというクラスがみつかりません
Traceback (most recent call last):
    6: from /Users/shigerunakajima/activerecord_uml/exe/activerecord_uml:12:in `<main>'
  5: from /Users/shigerunakajima/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord_uml-0.5.0/lib/activerecord_uml.rb:29:in `draw'
   4: from /Users/shigerunakajima/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord_uml-0.5.0/lib/activerecord_uml.rb:29:in `map'
  3: from /Users/shigerunakajima/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord_uml-0.5.0/lib/activerecord_uml.rb:29:in `block in draw'
    2: from /Users/shigerunakajima/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord_uml-0.5.0/lib/activerecord_uml.rb:29:in `new'
  1: from /Users/shigerunakajima/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord_uml-0.5.0/lib/activerecord_uml/diagram_drawer.rb:18:in `initialize'
/Users/shigerunakajima/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord_uml-0.5.0/lib/activerecord_uml/diagram_drawer.rb:18:in `const_get': wrong constant name activerecord_uml (NameError)

springコマンドが単体で実行されたような出力が表示され、コマンドの引数にactiverecord_umlが追加されているようです。

springはRails専用

springのソースコードをみると、springを有効にするコマンドはハードコードされています。

https://github.com/rails/spring/blob/master/lib/spring/client.rb#L20-L23

      "binstub"   => Client::Binstub,
      "stop"      => Client::Stop,
      "status"    => Client::Status,
      "rails"     => Client::Rails,

activerecord_umlをspringで動かすためには、Client::ActiverecordUmlを作る必要がありそうです。

よく考えると作ったところで、次の作業のどちらかが必要です。

  • RailsアプリケーションのGemfileを修正して改変したspringを使わせる
  • Railsアプリケーションと独立に改変したspringを使う

どちらも微妙です。

activerecord_umlを使うのに、観察対象のRailsアプリケーションを変更したくないです。 さらに複数のRailsバージョンへの対応も考えなければいけません。

Railsアプリケーションと複数のspringを使うと、どちらのspringが動いているか考えなければいけなります。 springがひとつ動いているだけでも難しいのに、複数動かすのは狂気の沙汰に思えます。

rails runnerを使う

bundle installせずにrails runnerからgemのコマンドを実行する - @ledsun blogで、rails runnerからactiverecord_umlを実行できることはわかっています。

解決しなければいけないのは、activerecord_umlが依存するruby scriptを読み込むことです。 実行コマンドからの相対パスで取得できることに気がつきました。

File.join __dir__,"../lib/activerecord_uml"

あとは、Kernel#systemを使ってrails runnerを起動すれば、springを使ってactiverecod_umlを起動できます。

system  "echo 'require \"#{File.join __dir__,"../lib/activerecord_uml"}\"; ActiverecordUml.draw' | #{File.join Dir.pwd,"bin/rails"} runner - #{ARGV.join ' '}"