61

Rails3アプリケーション用の新しいエンジンを作成しています。ご想像のとおり、このエンジンは私のアプリケーションのlibディレクトリにあります。

しかし、私はそれを開発するのにいくつかの問題があります。実際、エンジンで何かを変更するたびにサーバーを再起動する必要があります。

これを回避する方法はありますか?

Railsにlibディレクトリまたは特定のファイルと各リクエストの要件を完全にリロードさせることはできますか?

ご協力いただきありがとうございます :)

4

11 に答える 11

50

上記のいずれもうまくいかなかったので、Rails コードを少し掘り下げて、次のように思いつきました。

新しいファイル: config/initializers/reload_lib.rb

if Rails.env == "development"
  lib_reloader = ActiveSupport::FileUpdateChecker.new(Dir["lib/**/*"]) do
    Rails.application.reload_routes! # or do something better here
  end

  # For Rails 5.1+
  ActiveSupport::Reloader.to_prepare do
    lib_reloader.execute_if_updated
  end

  # For Rails pre-5.1 
  ActionDispatch::Callbacks.to_prepare do
    lib_reloader.execute_if_updated
  end

end

はい、うんざりすることはわかっていますが、ハックです。完全なリロードをトリガーするより良い方法があるかもしれませんが、これは私にとってはうまくいきます。私の具体的なユースケースは、Rails ルートにマウントされた Rack アプリだったので、開発中に作業したときにリロードする必要がありました。

基本的には、 /lib 内のファイルが最後にロードされてから変更された (タイムスタンプが変更された) かどうかをチェックし、変更された場合はリロードをトリガーします。

config/application.rb にこれがあることにも言及するかもしれません

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

これにより、デフォルトで lib ディレクトリ内のすべてが確実にロードされます。

イェーイ!

于 2010-12-06T16:49:59.973 に答える
37
于 2013-05-18T14:10:54.177 に答える
21

Since we are talking Rails, the easiest way is to 'require' your lib/* .rb files using 'require_dependency'. So long as the controller/helper/etc (.rb files under app/) uses require_dependency instead of just require reloading works, without the need to do anything funky.

Before I went down that track, the only solution that worked was the one on hemju.com, but I really did not want to have to hack the ApplicationController for Dev speed.

于 2011-07-25T04:51:43.017 に答える
13

追加する必要があります

config.autoload_paths += %W(#{config.root}/lib)

config/application.rb の Application クラスに

https://rails.lighthouseapp.com/projects/8994/tickets/5218-rails-3-rc-does-not-autoload-from-lib

于 2010-09-16T10:07:57.950 に答える
3

RAILS 3 では、lib ファイルを自動リロードする秘密のソースを次に示します。以下のコードは、例としては少しやり過ぎですが、それを機能させるために私がしたことです。YoYo#gogo でメッセージを変更し、ページ読み込みごとに画面で確認できます。初期化子を削除しても、同じままです。

/config/initializers/lib_reload.rb (新しいファイル)

ActiveSupport::Dependencies.explicitly_unloadable_constants << 'YoYo'
ActiveSupport::Dependencies.autoload_once_paths.delete(File.expand_path(File.dirname(__FILE__))+'/lib')

/lib/yo_yo.rb

class YoYo
  def gogo
    "OH HAI THERE"
  end
end

/app/controllers/home_controller

require 'yo_yo'
class HomeController < ApplicationController
  def index
    @message = YoYo.new.gogo
  end
end
于 2010-07-20T13:35:25.017 に答える
3

これらのファイルのいずれかが変更されたときに、rails /lib ディレクトリ内のすべての ruby​​ ファイルをリロードする@pbhoganの回答から着想を得た私のバージョンを次に示します。

また、すでに初期化されている定数に関するメッセージを回避するために、警告を無効にします。

Rails 3.2.8 以降で動作

if Rails.env.development?

  lib_ruby_files = Dir.glob(File.join("lib/**", "*.rb"))
  lib_reloader ||= ActiveSupport::FileUpdateChecker.new(lib_ruby_files) do
    lib_ruby_files.each do |lib_file|
      silence_warnings { require_dependency(lib_file) }
    end
  end

  ActionDispatch::Callbacks.to_prepare do
    lib_reloader.execute_if_updated
  end

end
于 2012-09-26T21:30:01.490 に答える
1

更新された回答

私のブログにすべての調査結果をまとめています。

古い答え

私もこれに対する解決策を探しました.(完全を期すために、また他の人をこの方向に向けるために)ここに私が見つけたものがあります.

Rails3.1以降、エンジンはコマンドで簡単に生成できますrails plugin new my_plugin --full。これにより、エンジンのスケルトンが生成されます。

--fullこれは、エンジンがインクルードするアプリケーションに直接「マージ」されることを意味します。たとえば、インクルードするアプリで定義されているかのように、コントローラーに直接アクセスできるようにする必要があります。これにより、たとえば、インクルードmy_engine/app/helpers/my_helper.rbアプリの に直接マージされるヘルパー ファイルを作成できますapp/helpers/my_helper.rb helper

--mountableエンジンの名前空間を作成して、そのコントローラーなどが含まれるアプリケーションのコントローラーなどと衝突しないようにする別のオプションがあります。これにより、たとえば、インクルードアプリmy_engine/app/helpers/my_engine/my_helper.rbのヘルパーと衝突しないヘルパーがapp/helpers/my_helper.rb存在します。

今より興味深い部分

生成されたエンジンのtestフォルダー内にdummy、完全な Rails アプリケーションを保持するフォルダーがあります。何のために?

エンジンを開発する場合、その機能は単独で完全に機能することを意図しており、単独で完全にテストする必要もあります。したがって、別の Rails アプリの「内部」でエンジンを開発するのは「間違った」方法です (ただし、Rails アプリからエンジンに既存の機能を抽出する場合、これは直感的に正しいと感じることがよくあります)。含まれるアプリケーションへのすべてのリクエストでコードを実行します。

"正しい" 方法は次のように思われます: アプリを使用する完全な Rails アプリであるかのように、エンジンを開発してテストしますdummy。エンジンが提供する必要がある機能を使用するコントローラー、モデル、ビューなどを作成するなど、「通常の」Rails アプリで実行できるすべての操作を実行できます。また、通常は、ディレクトリで使用rails sしてサーバーを起動しtest/dummy、 でダミー アプリにアクセスすることもできlocalhost:3000ます。テストを実行すると、dummyアプリは統合テストに自動的に使用されます。けっこういい!:-)

物を置く場所に注意する必要があります。

  • 別の Rails アプリ内で使用することを意図した機能はすべて に入りmy_engine/app、エンジンの機能をテストするためだけに必要な機能は に入りtest/dummy/appます。

その後、次のGemfileようにエンジンをメイン アプリに簡単にロードするgem 'my_engine', :path => 'path/to/my_engine'か、Gem として GitHub に公開できます。

(興味深いことの 1 つ (そしてこのトピックの主題に戻る) は、ダミーのサーバーを起動すると、エンジンのすべての変更がサーバーに反映されているように見えるということです! どういうわけか、Rails 内にエンジンを含めることは可能のようです。アプリをキャッシュせずに...? これがどのように起こるかわかりません。)

要約すると、エンジンは完全に自立できる機能を提供するため、独自に開発およびテストする必要があります。その後、安定した状態に達すると、その機能を必要とする他のアプリに含めることができます。

役立つリソースを次に示します。

この回答がお役に立てば幸いです。私はまだエンジン全般に非常に慣れていないので、間違った情報があれば教えてください。修正します。

于 2012-09-20T07:35:10.690 に答える
0

Rails 3 では、「load_once_paths」が「autoload_once_paths」になることに注意してください。

また、明示的に何かを入れない限り、空にする必要があるようです。

于 2010-09-16T19:07:45.670 に答える
0

また、(@dishod のソリューションに加えて) application.rb の次の行をコメントアウトし、モジュール名がファイル名と同じであることを確認してください (そうしないと、Rails はそれを見つけることができません)。 )

#Dir.glob("./lib/*.{rb}").each { |file| require file } # require each file from lib directory
于 2011-10-28T06:23:10.457 に答える