rails libディレクトリに配置した自作ライブラリが読み込まれないときに試したこと
前提
内容
rails で 自作ライブラリCodegenLibというライブラリを利用する際、中々ロードできなかったのでそのときのメモ。(色々な無知が重なった結果の事故)
結果
結果的には、以下に注意すること
- application.rbにautoloadのパスを追加すること.
- lib内のクラス構成とディレクトリ構成は一致させること.(CodegenLib::CppGenerator)なら(lib/codegenlib/cpp_generator.rb)に配置すること.
- ディレクトリ名/ファイル名は、クラス名と一致しており小文字であること(class CppGenerator)はcpp_generator.rbとなっていること
- 余計なrequireは記述しないこと.(railsが勝手にロードしてくれる)
動作するまでの過程
初期構成
最初のディレクトリ構成
-myapp/ + app/ + controllers/ +code_gen_controller.rb + lib/ + CppGenerator.rb + CppHelper.rb
CppGenerator.rb
require './CppHelper.rb' module CodegenLib class CppGenerator end end
code_gen_controller.rb
class CodeGenController def generate g = CodegenLib::CppGenerator.new end end
application.rb
lib内のファイルをオートロードするためには「事前にapplication.rbを編集しなければいけない」、という事は知っていたのでそれを設定。
class Application < Rails::Application config.autoload_paths += %W(#{config.root}/lib/)
動作確認 その1
この状態で動作させると、以下の旨のメッセージがでて失敗
CodeGeneratorController::CodegenLib::CppGeneratorが見つからない
対応 その1 lib内のクラス階層とディレクトリ階層を一致させる
http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/ の記事を読むとクラス階層とディレクトリ階層が一致している必要がありそうなので、libのディレクトリ構成を次のように変更した。
-myapp/ + app/ + controllers/ + code_gen_controller.rb + lib/ + codegenlib/ + CppGenerator.rb + CppHelper.rb
又、モジュール名をCodegenLibからCodegenlibに変更したの、ソースも次のように修正。
CppGenerator.rb
require './CppHelper.rb' module Codegenlib class CppGenerator end end
code_gen_controller.rb
class CodeGenController def generate g = Codegenlib::CppGenerator.new end end
動作確認 その2
Codegenlib::CppGeneratorのファイルが見つかりません
CodeGenController::CppGeneratorよりは一歩前進。
対応 その2 クラスを定義したファイルを小文字に置き換える
RailsによるアジャイルWebアプリケーション開発 4版の18.1ディレクトリ構造を確認すると、クラスやモジュールが含まれるファイルに、クラス名又はモジュール名を小文字にした名前がついていると,Railsはそのファイルを自動的にロードします とある。
上記にならって、ファイル名を変更した。
-myapp/ + app/ + controllers/ +code_gen_controller.rb + lib/ + codegenlib/ + cpp_generator.rb + cpp_helper.rb
cpp_generator.rb
require './cpp_helper.rb' module Codegenlib class CppGenerator end end
動作確認 その3
cpp_helper.rbが見つからないよ
対応 その3 余計なrequireを削除
railsが勝手にロードしてくれるので、requireを削除。
cpp_generator.rb
module Codegenlib class CppGenerator end end
動作確認 その4 無事動作
上記修正で無事オートロードされるようになった。