Ruby on Rails 3-각 요청에 대해 lib 디렉토리 다시로드
Rails 3 애플리케이션을위한 새 엔진을 만들고 있습니다. 짐작할 수 있듯이이 엔진은 내 애플리케이션의 lib 디렉토리에 있습니다.
그러나 나는 그것을 개발하는 데 몇 가지 문제가 있습니다. 실제로 엔진에서 무언가를 변경할 때마다 서버를 다시 시작해야합니다.
이것을 피할 수있는 방법이 있습니까?
레일이 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
완료되면 이동하는 것과 관련이 있음을 발견했습니다 . 우리는 더 잘할 수 있습니다.
내 솔루션은 다음에 대해 테스트됩니다.
- 레일즈 3.0.20
- 레일스 3.1.12
- 레일스 3.2.13
- Rails 4.0.0.rc1
이것을 당신의 config/application.rb
:
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
그게 다야! ™
예를 들어 에 넣으면 작동하지 않으므로 여기에 넣으십시오 config/environments/development.rb
.
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 파일을 '요구'하는 것 입니다. 컨트롤러 / 도우미 / 등 (app / 아래의 .rb 파일)이 재 로딩 작업을 요구하는 대신에 require_dependency를 사용하는 한, 펑키 한 작업을 수행 할 필요가 없습니다.
내가 그 길을 밟기 전에 작동했던 유일한 해결책은 hemju.com 에있는 것이 었지만 , 실제로는 Dev 속도를 위해 ApplicationController를 해킹하고 싶지 않았습니다.
추가해야합니다
config.autoload_paths += %W(#{config.root}/lib)
config / application.rb의 애플리케이션 클래스에
https://rails.lighthouseapp.com/projects/8994/tickets/5218-rails-3-rc-does-not-autoload-from-lib
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
다음은 해당 파일이 변경 될 때 rails / lib 디렉토리의 모든 루비 파일을 다시로드하는 @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
업데이트 된 답변
I sum up all my findings on my blog, you better look there:
- http://lsd4coders.muheimwebdesign.ch/2012/09/how-to-develop-rails-3-1-engines-with-ease-part-i-the-engine/
- http://lsd4coders.muheimwebdesign.ch/2012/09/how-to-develop-rails-3-1-engines-with-ease-part-ii-the-gem/
Old answer
I looked around for a solution for this too, and (for completeness' sake and also to point others into this direction) here is what I found.
As of Rails3.1, engines can easily be generated through the command rails plugin new my_plugin --full
. This generates the skeleton for an engine.
--full
means that the engine will be "merged" right into the including application, so that for example controllers should be directly accessible as if they were defined in the including app. This lets you e.g. have a helper file in my_engine/app/helpers/my_helper.rb
that will be merged right into your including app's app/helpers/my_helper.rb helper
.
There's another option --mountable
which creates a namespace for the engine so that its controllers etc. will never collide with the including application's ones. This results in e.g. a helper being in my_engine/app/helpers/my_engine/my_helper.rb
which won't collide with a helper app/helpers/my_helper.rb
in your including app.
Now the more interesting part:
Within the generated engine's test
folder, there's a dummy
folder which holds a complete Rails application! What's it for?
When you develop an engine, its functionalities are meant to work completely on their own, and it should also be tested completely on its own. So it's the "wrong" way to develop an engine "within" another Rails app (though this intuitively often will feel right when extracting existing functionalities from a Rails app into an engine), and so theoretically it is also not needed to reload an engine's code with every request to the including application.
The "right" way seems to be this: develop and test your engine, as if it were a full Rails app using the dummy
app! Therein you can do everything you can do in any "normal" Rails app, e.g. create controllers, models, views, etc. which use the functionalities the engine should provide. You also can normally start a server using rails s
in your test/dummy
directory and access the dummy app on localhost:3000
, and when running your tests, the dummy
app is automatically used for integration tests. Quite nice! :-)
You have to be careful where to put your stuff:
- Any functionality that is meant to be used within another Rails app goes into
my_engine/app
, while any functionality that is only needed to test the engine's functionality goes intotest/dummy/app
.
Then afterwards you can easily load your engine in your main app's Gemfile
like this: gem 'my_engine', :path => 'path/to/my_engine'
or publish it to GitHub as a gem.
(One interesting thing (and to come back to this topic's subject) is that when I start the dummy's server, then all changes in the engine seem to be reflected within it! So somehow it seems to be possible to include an engine within a Rails app without caching it...? I don't know how this happens.)
So to sum up: an engine provides functionality that can stand completely on its own, so it should also be developed and tested on its own. Then, when it has reached a stable state, it can be included by any other app that needs its functionality.
Here's some resources I find useful:
I hope you find this answer useful. I'm still very new to engines in general, so if there's any wrong information, please tell me, and I'll correct it.
Add to application_controller.rb
or your base controller:
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
Worked for me.
note that in Rails 3 "load_once_paths" becomes "autoload_once_paths."
Also, it appears that it should be empty unless you explicitly put something in it.
Also, make sure that you comment out the following line in application.rb (in addition to @dishod's solution), and make sure that your module name is the same as your file name (otherwise, rails won't be able to find it)
#Dir.glob("./lib/*.{rb}").each { |file| require file } # require each file from lib directory
Worked for Rails 3.2.13 for reloading lib inside of gem of an app:
require_dependency 'the_class'
AND
config.autoload_paths += %W(#{config.root}/../fantasy/lib)
참고URL : https://stackoverflow.com/questions/3282655/ruby-on-rails-3-reload-lib-directory-for-each-request
'developer tip' 카테고리의 다른 글
파이썬 클래스 메서드 꾸미기-인스턴스를 데코레이터에 어떻게 전달합니까? (0) | 2020.12.11 |
---|---|
작동하는 JSLint Eclipse 플러그인이 있습니까? (0) | 2020.12.11 |
java.sql.Connection에서 데이터베이스 URL을 얻는 방법은 무엇입니까? (0) | 2020.12.11 |
변경 불가능한 구조체에 대해 공용 읽기 전용 필드를 사용합니까? (0) | 2020.12.11 |
존재와 정의의 차이점은 무엇입니까? (0) | 2020.12.11 |