Rails 3アプリケーション用の新しいエンジンを作成しています。ご想像のとおり、このエンジンはアプリケーションのlibディレクトリにあります。
ただし、開発にはいくつかの問題があります。実際、エンジンで何かを変更するたびにサーバーを再起動する必要があります。
これを回避する方法はありますか?
Railsを指定して、libディレクトリまたは特定のファイルと各リクエストの要件を完全にリロードすることはできますか?
ご協力いただきありがとうございます :)
TL; DR
これをconfig/application.rbに入れます
config.eager_load_paths += ["#{Rails.root}/lib"]
libファイルのrequire
ステートメントを削除
行け!
詳細に説明させてください。
この答えが受け入れられる理由はわかりません。なぜなら、各リクエストでのlibフォルダーのリロードには役立たないからです。最初に、Rails 2で動作すると思ったが、質問では、Rails 3であり、3.0.0のリリース日は回答の日付。
他の回答は複雑すぎるか、実際の解決策を提供していません。
私は気になっていたので少し物事を調査することにしました、そして私は人々がこれに対する回避策を持っていることを発見し、それは開発中のapp/models
内にlibファイルを保存し、完了したらそれを/lib
に移動することを含むことさえ発見しました私たちはもっとうまくできるでしょう?
私のソリューションは以下に対してテストされています:
これをconfig/application.rb
に入れてください:
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
それだけです!™
たとえば、config/environments/development.rb
に配置した場合、not workになるため、ここに配置してください。
require
ステートメントもこのソリューションを機能させないため、/lib
コードのrequire
ステートメントをすべて削除してください。
このコードは暗黙的にコードを必要とするため、環境チェック(不要)を実行し、上記のコードの代わりに、次のような記述を行うことにします。
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"] if Rails.env.development?
このシナリオでは、すべての非開発環境でまだ必要であるため、古いrequire
ステートメントに注意する必要があります。
したがって、まだ環境チェックを行うことに決めた場合は、requireステートメントの逆チェックを行ってください。さもないと噛まれてしまいます!
require "beer_creator" unless Rails.env.development?
不要なことについて段落全体を書くことも不要だと思うかもしれませんが、不要なことをするときに必要なことについて人々に警告することも必要だと思います。
このトピックについて詳しく知りたい場合は、 この小さなチュートリアル をご覧ください。
私は上記のどれも私のために働くことができなかったので、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ディレクトリ内のすべてが確実にロードされます。
いいね!
Railsについて話しているので、最も簡単な方法は、 'require_dependency'を使用してlib/* .rbファイルを 'require'することです。 controller/helper/etc(app /の下の.rbファイル)がリロード作業を単に必要とするのではなく、require_dependencyを使用し、ファンキーなことをする必要がない限り。
私がその道を進む前に、働いていた唯一の解決策は hemju.com のものでしたが、開発速度のためにApplicationControllerをハックする必要は本当にありませんでした。
追加する必要があります
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
In 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
更新された回答
私のブログですべての発見を要約します。
古い回答
私もこれに対する解決策を探しましたが、(完全を期すために、また他の人にこの方向を示すために)ここで見つけました。
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
フォルダー内には、完全なRailsアプリケーション!何のためにあるのかを保持するdummy
フォルダーがあります。
エンジンを開発するとき、その機能は独自に完全に機能することを意図しており、独自に完全にテストする必要もあります。したがって、別の「内」でエンジンを開発する「間違った」方法ですRails app(ただし、これは、Railsエンジンへのアプリ)、したがって理論的には、含まれるアプリケーションへのすべてのリクエストでエンジンのコードをリロードする必要もありません。
「正しい」方法はこれのようです:エンジンを開発してテストします。まるでそれが完全なRailsアプリでdummy
アプリを使用しているかのようです! 「通常」で行うRailsアプリ。たとえば、エンジンが提供する機能を使用するコントローラー、モデル、ビューなどを作成します。通常、Rails s
を使用してサーバーを起動することもできます。 test/dummy
ディレクトリでlocalhost:3000
のダミーアプリにアクセスし、テストを実行すると、dummy
アプリが統合テストに自動的に使用されます。
物を置く場所に注意する必要があります:
my_engine/app
に入り、エンジンの機能をテストするためにのみ必要な機能はtest/dummy/app
に入ります。その後、次のようにメインアプリのGemfile
にエンジンを簡単にロードできます:gem 'my_engine', :path => 'path/to/my_engine'
またはGitHubにgemとして公開します。
(興味深いことに(このトピックの主題に戻って)ダミーのサーバーを起動すると、エンジンのすべての変更がサーバー内に反映されるようになります! Railsキャッシュせずにアプリ...?これがどのように起こるかわかりません。)
要約すると、エンジンは独自に完全に機能する機能を提供するため、独自に開発およびテストする必要があります。その後、安定状態に達すると、その機能を必要とする他のアプリに含めることができます。
ここに私が役に立つと思ういくつかのリソースがあります:
この回答がお役に立てば幸いです。私は一般的にまだエンジンが非常に新しいので、間違った情報があれば教えてください、そして私はそれを修正します。
追加 application_controller.rb
またはベースコントローラー:
before_filter :dev_reload if Rails.env.eql? 'development'
def dev_reload
# add lib files here
["rest_client.rb"].each do |lib_file|
ActiveSupport::Dependencies.load_file lib_file
end
end
私のために働いた。
また、application.rbの次の行を(@dishodのソリューションに加えて)コメントアウトし、モジュール名がファイル名と同じであることを確認してください(そうでない場合、Rails =見つけることができません)
#Dir.glob("./lib/*.{rb}").each { |file| require file } # require each file from lib directory
アプリのgem内でlibをリロードするためにRails 3.2.13で働きました:
require_dependency 'the_class'
そして
config.autoload_paths + =%W(#{config.root} /../ fantasy/lib)
in Rails 3 "load_once_paths"は "autoload_once_paths"になります。
また、明示的に何かを入れない限り空であるように見えます。