web-dev-qa-db-ja.com

Rails 4でlibファイルを自動ロードする

開発中に/libディレクトリにコードを自動ロードするには、イニシャライザで次の行を使用します。

config/initializers/custom.rb:

RELOAD_LIBS = Dir[Rails.root + 'lib/**/*.rb'] if Rails.env.development?

Rails 3 Quicktipから:開発モードでlibフォルダーを自動的にリロードする

これはうまく機能しますが、プロダクションで使用するには非効率的です。リクエストごとにlibをロードするのではなく、起動時にロードするだけです。同じブログに、これを行う方法を説明した 別の記事 があります。

config/application.rb:

# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

しかし、私が開発中でも、それに切り替えると、lib関数を使用しようとするとNoMethodErrorsが発生します。

私のlibファイルの1つの例:

lib/extensions.rb:

Time.class_eval do
  def self.milli_stamp
    Time.now.strftime('%Y%m%d%H%M%S%L').to_i
  end
end

Time.milli_stampを呼び出すとNoMethodErrorがスローされます

私は他の人がSOについて同様の質問に答えたことを実感していますが、それらはすべて命名規則や他の問題を扱っていたように思えました - 私のlibクラスはすでにworkリクエストごとのロードの場合は、 - startuploadingごとに変更します。これを行うための正しい方法は何ですか?

223
Yarin

私はこれがあなたの問題を解決するかもしれないと思います:

  1. config/application.rbに:

    config.autoload_paths << Rails.root.join('lib')
    

    そして正しい命名規則をlibで守ってください。

    inlib/foo.rb

    class Foo
    end
    

    lib/foo/bar.rbに:

    class Foo::Bar
    end
    
  2. あなたが本当にlib/extensions.rbのようなファイルでいくつかのモンキーパッチをやりたいなら、あなたはそれを手動で必要とするかもしれません:

    inconfig/initializers/require.rb

    require "#{Rails.root}/lib/extensions" 
    

P.S。

543
ifyouseewendy

これは直接質問に答えるものではありませんが、私はそれが質問を完全に回避するための良い代替案だと思います。

すべてのautoload_pathsまたはeager_load_paths面倒を避けるために、 "app"ディレクトリの下に "lib"または "misc"ディレクトリを作成してください。通常どおりにコードを配置します。Railsは、モデルファイルのロード(および再ロード)と同じようにファイルをロードします。

33
lulalala

これは、Railsがクラスローディングを処理する方法の解決策を探すときに、この答えを見つけてくれる私のような人を助けるかもしれません...私はクラスを定義するよりむしろ名前が適切に私のファイル名と一致するmoduleを定義しなければなりません:

ファイルlib/development_mail_interceptor.rb(はい、Railscastのコードを使用しています:))

module DevelopmentMailInterceptor
  class DevelopmentMailInterceptor
    def self.delivering_email(message)
      message.subject = "intercepted for: #{message.to} #{message.subject}"
      message.to = "[email protected]"
    end
  end
end

機能しますが、クラスをモジュール内に配置していなければロードされません。

6
sameers

開発モードでのすべてのリクエストに対して、モンキーパッチ/エクステンションをロードするにはconfig.to_prepareを使用してください。

config.to_prepare do |action_dispatcher|
 # More importantly, will run upon every request in development, but only once (during boot-up) in production and test.
 Rails.logger.info "\n--- Loading extensions for #{self.class} "
 Dir.glob("#{Rails.root}/lib/extensions/**/*.rb").sort.each do |entry|
   Rails.logger.info "Loading extension(s): #{entry}"
   require_dependency "#{entry}"
 end
 Rails.logger.info "--- Loaded extensions for #{self.class}\n"

終わり

0
Madx