Rails 3의 lib 폴더에서 모듈 / 클래스를로드하는 가장 좋은 방법은?


273

최신 Rails 3 릴리스는 더 이상 lib에서 모듈 및 클래스를 자동로드하지 않으므로이를로드하는 가장 좋은 방법은 무엇입니까?

github에서 :

A few changes were done in this commit:

Do not autoload code in *lib* for applications (now you need to explicitly 
require them). This makes an application behave closer to an engine 
(code in lib is still autoloaded for plugins);

답변:


251

Rails 2.3.9 부터 config/application.rb자동로드하려는 파일이 포함 된 디렉토리를 지정할 수 있는 설정 이 있습니다.

application.rb에서 :

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)

7
@thankful의 대답은의 전체 하위 트리를 자동로드하려는 경우에도 마찬가지입니다 app/lib.
톰 해리슨

199
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

출처 : Rails 3 퀵팁 : 모든 하위 디렉토리를 포함한 lib 디렉토리 자동로드, 지연로드 방지

lib 폴더에 포함 된 파일은 서버가 시작될 때만로드됩니다. 편안하게 파일을 자동으로 다시로드하려면 Rails 3 빠른 팁 : 개발 폴더에서 lib 폴더 자동 다시로드를 읽으십시오 . 영구적 인 재로드로 인해 시스템 속도가 느려지므로 프로덕션 환경에는 적합하지 않습니다.


링크는 죽었다
Besi

84

자동 로딩 기능의 마법

자동 로딩 작업이 수행되는 폴더를 제어하는 ​​옵션은 다른 답변에서 충분히 다루어졌습니다. 그러나 필요에 따라 자동로드 경로를 수정했지만 다른 사람이 문제가있는 물건을로드하는 경우이 답변은이 자동로드의 마술이 무엇인지 설명하려고 시도합니다.

하위 디렉토리에서 물건을로드 할 때 알아야 할 규칙이나 규칙이 있습니다. 때때로 루비 / 레일 매직 (이번에는 대부분 레일)이 왜 무슨 일이 일어나고 있는지 이해하기 어렵게 만들 수 있습니다. 자동로드 경로에 선언 된 모든 모듈은 모듈 이름이 상위 디렉토리 이름과 일치하는 경우에만로드됩니다. 따라서 lib/my_stuff/bar.rb다음과 같은 것을 넣으려고하면 :

module Foo
  class Bar
  end
end

자동으로로드되지 않습니다. 그런 다음 부모 디렉토리의 이름을 바꾸면 foo경로에서 모듈을 호스팅합니다 lib/foo/bar.rb. 당신을 위해있을 것입니다. 다른 옵션은 모듈 이름으로 자동로드하려는 파일의 이름을 지정하는 것입니다. 분명히 그 이름으로 하나의 파일 만있을 수 있습니다. 물건을 여러 파일로 분할 해야하는 경우 물론 하나의 파일을 사용하여 다른 파일을 요구할 수는 있지만 개발 모드에서 다른 파일을 수정할 때 Rails가 자동으로 수행 할 수 없기 때문에 권장하지 않습니다 당신을 위해 그들을 다시로드하십시오. 그러나 정말로 원한다면 모듈 이름으로 하나의 파일을 가지고 모듈을 사용하는 데 필요한 실제 파일을 지정합니다. 따라서 두 개의 파일을 가질 수 있습니다 . 그것은 동일하게 작동합니다.lib/my_stuff/bar.rb 그리고lib/my_stuff/foo.rb 이상과 한 줄을 포함하는 후자와 같은 인 전 :require "bar"

추신 : 나는 한 가지 더 중요한 것을 추가해야한다고 생각합니다. 최근에 자동로드되어야하는 lib 디렉토리에 무언가를 갖고 싶을 때마다 이것이 실제로이 프로젝트를 위해 특별히 개발하고있는 것이라면 생각하기 시작합니다 (일반적으로 언젠가는 많은 프로젝트 또는 git 서브 모듈 등에 사용되는 "정적"코드 스 니펫으로 전환하십시오 (이 경우 반드시 lib 폴더에 있어야합니다). 그러면 아마도 그 위치는 lib 폴더에 전혀 없을 것입니다. 아마도 앱 폴더 아래의 하위 폴더에 있어야 할 것입니다. 이것이 새로운 방식의 일이라고 생각합니다. 분명히, 당신이 물건을 넣은 자동로드 경로에 관계없이 동일한 마술이 작동하므로 이러한 것들에 좋습니다. 어쨌든, 이것은 주제에 대한 나의 생각입니다. 당신은 동의하지 않습니다. :)


업데이트 : 마법의 유형에 대해 ..

세 버린이 그의 의견에서 지적했듯이 핵심 "모듈 메커니즘 자동로드"는 루비의 일부이지만 자동로드 경로는 그렇지 않습니다. Rails가 필요하지 않습니다autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar"). 그리고 Foo 모듈을 처음으로 참조하려고하면로드 될 것입니다. 그러나 Rails가하는 일은 등록 된 폴더에서 물건을 자동으로 불러 오거나로드 할 수있는 방법을 제공하며, 명명 규칙에 대해 무언가를 가정하는 방식으로 구현 된 것입니다. 그렇게 구현되지 않았다면 현재로드되지 않은 것을 참조 할 때마다 모든 자동로드 폴더의 모든 파일을 통과하고 참조하려는 항목이 포함되어 있는지 확인해야합니다. 이것은 자동 로딩과 자동 로딩의 아이디어를 잃게됩니다. 그러나 이러한 규칙을 준수하면 모듈 / 클래스에서 정의 된 위치로로드하려고 시도하고로드 할 수 있습니다.


1
이 루비가 왜 마법입니까? Ruby는 (정의되지 않은) 상수에 액세스 할 때로드되는 파일을 명령하는 데 사용할 수있는 Module # autoload 기능 만 제공합니다 ( ruby-doc.org/core-1.9.3/Module.html#method-i-autoload 참조 ). 모듈 / 클래스 이름과 디렉토리 / 파일의 일치는 Rails / ActiveSupport에서 수행됩니다 (예 : github.com/rails/rails/blob/… ). 내가 잘못?
Severin

네, 당신이 맞다고 믿습니다. Zabba가 "결함"을 지적했을 때 나는 원래의 대답을 "수정"하기에는 너무 성급했다. 이 문제를 명확히하기 위해 답변을 조금 더 업데이트하겠습니다.
Timo

1
나는 약 30 분 정도 시간을 보냈다. Sprockets :: JSRender :: Processor를 자동로드하는 데 필요했습니다. 레일 콘솔에 들어가서 "Sprockets :: JSRender :: Processor".underscore를 수행하고 그것이 "sprockets / js_render / processor"(. rb가 추가 된) HTH 누군가라는 것을 거부함으로써 그 경로를 찾을 수 있습니다.
pedz

방금 내 정신을 구했어 ~ 안심의 한숨 ~ 공유해 주셔서 감사합니다 :)
Brenden

가장 유용한 의견에 감사드립니다. 귀하의 의견을 읽을 때까지 일부 모듈이 동작하는 이유를 이해하지 못했습니다. 당신에게 축복이 있습니다!
mjnissim

41

경고 : 'lib'폴더에서 'monkey patch'또는 'open class'를 로드 하려면 'autoload'접근법을 사용하지 마십시오 !!!

  • " config.autoload_paths "접근 방식 : 한 곳에서만 정의 된 클래스를로드하는 경우에만 작동합니다. 어떤 클래스가 이미 다른 곳에 정의되어 있다면이 방법으로 다시로드 할 수 없습니다.

  • " config / initializer / load_rb_file.rb "접근 방식 : 항상 작동합니다! 대상 클래스가 새 클래스이거나 기존 클래스의 "공개 클래스"또는 "원숭이 패치"인 경우 항상 작동합니다!

자세한 내용은 https://stackoverflow.com/a/6797707/445908을 참조하십시오.


6
이것은 이해해야 할 중요한 차이점입니다. 고마워
Tyler Collier 2018 년

28

매우 비슷하지만 조금 더 우아하다고 생각합니다.

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]

18

내 경우에는 단순히 lib 디렉토리 아래에 파일을 직접로드하려고했습니다.

application.rb 내에서 ...

require '/lib/this_file.rb' 

콘솔에서도 작동하지 않고 시도했을 때

require './lib/this_file.rb' 

레일은 파일을 완벽하게로드합니다.

나는 여전히 꽤 멍청하고 이것이 왜 작동하는지 잘 모르겠지만 작동합니다. 누군가 나에게 설명하고 싶다면 감사하겠습니다 : DI 희망이 누군가에게 도움이되기를 바랍니다.


2
이는 ./lib/this_file.rb가 현재 디렉토리 (Rails 콘솔에서 Rails 루트가 됨)에서 찾고 /lib/this_file.rb가이를 절대 경로로 찾기 때문입니다. 예 : ./lib/this_file.rb = /var/www/myrailsapp/lib/this_file.rb, /lib/this_file.rb = /lib/this_file.rb
Jason

7

나는 같은 문제가 있었다. 내가 해결 한 방법은 다음과 같습니다. 솔루션은 lib 디렉토리와 모든 서브 디렉토리 (직접뿐만 아니라)를로드합니다. 물론 모든 디렉토리에 사용할 수 있습니다.

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

5
이것은 완전히 혼란스러운 Rails 네임 스페이스 규칙에 따른 부작용입니다. 자동로드 검색에서 Foo를 정의하는 lib / foo.rb 앞에 Bar :: Foo를 정의하는 lib / bar / foo.rb가 표시 Expected lib/bar/foo.rb to define constant Foo되면 Foo를 참조하여 lib / foo.rb를로드하려고하면 혼란스러운 오류가 발생 합니다. 일정한.
Jacob

5

config.autoload_paths가 작동하지 않습니다. 다른 방법으로 해결

Ruby on rails 3은 / lib 폴더에서 코드를 자동으로 다시로드 (자동로드)하지 않습니다. 안에 넣어서 해결ApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 

4

특정 파일 만 lib의 모듈에 액세스해야하는 경우 필요한 파일에 require 문을 추가하십시오. 예를 들어, 한 모델이 하나의 모듈에 액세스해야하는 경우 다음을 추가하십시오.

require 'mymodule'

model.rb 파일의 맨 위에 있습니다.


50
requirerails 앱 내에서 사용 하면 ActiveSupport::Dependencies코드를 제대로로드 할 수 없으므로 사용할 수 없습니다 . 대신 config.autoload_paths위의 답변과 같이 사용 하고 필요에 따라 포함 / 확장해야합니다.
ben_h

13
@Mike에게 감사합니다. 나는 당신이 한 일을 할 것입니다. 왜 나쁜지에 대한 설명을 보는 것이 좋았습니다. 답을 제거하지 않아서 감사합니다.
pupeno

모듈을 하나만로드하려면 'mymodule'을 포함시키는 것은 어떻습니까?
Mike

1
@ben_h requireRails 앱 어디에서나 나와서는 안 됩니까? 갈퀴 작업에서 나는 현재하고있어 require-ing와 include에 살고 모듈을 -ing lib/. 내가 그렇게하지 말아야합니까?
Dennis

@ben_h 내 검색이 계시 것과 그것의 일반적인 require당신의 lib/코드 (예를 들어, 이 블로그 게시물 , 이 SO 응답 ). 나는 여전히 모든 것에 대해 확신하지 못한다. 사용하지 않는다는 주장 뒤에 더 많은 증거를 줄 수 있습니까 require?
Dennis

2

파일 이름을 정확하게 입력하십시오.

진심으로. 수업이 Governance :: ArchitectureBoard이고 파일이 lib / governance / architecture_baord.rb ( "board"에서 O와 A로 바 because)이므로 한 시간 동안 클래스와 싸웠습니다.

돌이켜 보면 명백한 것처럼 보이지만 악마는 그것을 추적했습니다. 레일즈가 클래스 이름을 뭉크로 만들 것으로 예상하는 파일에 클래스가 정의되어 있지 않으면 단순히 클래스 이름을 찾지 않습니다.


2

현재 Rails 5, 응용 프로그램 디렉토리 아래에있는 lib 폴더를 넣어 또는 그 대신 만들어 다른 의미있는 이름 공간을 같은 폴더에 대한 것이 좋습니다 services, presenters, features등 및 레일에 의해 자동 로딩 응용 프로그램 디렉토리에 넣어.

GitHub 토론 링크 도 확인하십시오 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.