LoginSignup
28
17

More than 5 years have passed since last update.

RailsでRuby標準ライブラリを拡張してautoloadさせる方法と、理想的なディレクトリ構成

Last updated at Posted at 2016-07-25

対象バージョン

Rails 4.2.6

対象読者

  • Rubyの標準ライブラリを拡張したいけど、何でもかんでもlib直下にコードを入れると死ぬ人
  • lib/core_ext に標準ライブラリを格納したはいいけど、 CoreExt module じゃないコードをどうやって autoload させたら良いかわからない人

方法

lib/core_ext/ に拡張コードを実装

lib/core_ext/string.rb
class String
  def and_hello
    self+" and hello"
  end
end

lib 直下を autoload対象にする

config/application.rb
module AppName
  class Application < Rails::Application
....
    config.autoload_paths += ["#{config.root}/lib/"]
  end
end

lib/core_ext.rb を実装

lib/core_ext/string を require する

lib/core_ext.rb
require 'core_ext/string'

module CoreExt
end

config/initializers/core_ext.rb を実装

CoreExt モジュールを呼び出して、拡張コードを読みこませる

config/initializers/core_ext.rb
CoreExt

Q&A形式の解説

config/initializersCoreExt を呼ぶのは何で?

  • Railsのオートロードは、対象のモジュールが呼ばれた時に、初めて読み込まれる
    • なので、config/initializersCoreExt を呼び出すことで、 String の拡張を明示的に読み込ませている

lib/core_ext/stringconfig/initializers とかで直接 require しちゃダメなの?

  • それでも良いと思うけど、Rails way から中途半端に外れるのは何かと危険と考えているので
  • 途中からプロジェクトに参加した人は、そこだけ Rails way から外れているなんて思わない
    • 驚きは最小にしたいよね

config/initializers 直下に string.rb 置いちゃったら楽じゃない?

  • コードが散逸するのが嫌だ
    • 絶対そんなところ探さない自信がある
  • config/initializers は初期処理や、アプリ固有の設定を置くべき場所
  • CoreExt を読み込むという初期処理を置くだけにして、責務を分担している

lib直下に、string.rb を置かないのは何で?

  • なんでもかんでもlib直下に置くのもよく分からなくなるから
  • 標準ライブラリ拡張は、ActiveSupport の様式に従って core_ext に置いた

autoload_paths を lib/core_ext にすれば config/initializers/core_ext.rb 不要じゃない?

  • lib以下のディレクトリに、別に module にしたい実装が追加された時に、ややこしいことになりそうなのでやらない
    • 例えば、 Util::Hoge を実装した場合
    • autoload_paths += ['lib', 'lib/core_ext'] とかすると、2回 core_ext がロードされるはず...
├── core_ext
│   └── string.rb
├── core_ext.rb
└── util
    └── hoge.rb
  • あと、この方法だと String が拡張されないんだよね...
    • module じゃないから、autoload が働かないという解釈でよいのかな?
    • おしえてえらいひと

参考

モジュールが読み込めているか確認する時に便利なメソッド

ActiveSupport::Dependencies.autoloaded_constants

  • autoloadで読み込まれているモジュールを配列で返す

ActiveSupport::Dependencies.autoload_paths

  • autoload対象のpathを配列で返す

参考リンク

28
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
17