2011-08-16 2 views
24

로드 오류와 관련된 일련의 두통을 일으킨 새로운 파일을 'lib'에 방금 만들었습니다.'lib'네임 스페이스/자동 로딩과 일치하지 않는 "LoadError"동작이 발생했습니다.

/lib/response_set.rb : 그것은 처음에 도달 할 때

module MyCompany 
    class ResponseSet < Array 
    ... 
    end 
end 

/spec/lib/response_set_spec.rb

require 'spec_helper' 

describe MyCompany::ResponseSet do 
    describe "..." do 
    ... 
    end 
end 

은 RSpec에이 스펙을 실행하면 '우리에게 다음과 같은 오류를 제공합니다 설명 : '

/Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:492:in `load_missing_constant': Expected /Users/my_stuff/projects/my_project/lib/response_set.rb to define ResponseSet (LoadError) 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:183:in `block in const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `each' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/backward_compatibility.rb:20:in `const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-expectations-2.5.0/lib/rspec/expectations/backward_compatibility.rb:6:in `const_missing' 
    from /Users/my_stuff/projects/my_project/spec/lib/response_set_spec.rb:4:in `<top (required)>' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in `load' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in `block in load_spec_files' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in `map' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in `load_spec_files' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/command_line.rb:18:in `run' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:55:in `run_in_process' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:46:in `run' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:10:in `block in autorun' 

우리는 동일한 구조를 가진 오랜 시간 동안 많은 다른 파일을 사용 해왔다.

/lib/smart_set.rb

module MyCompany 
    class SmartSet < Array 
    ... 
    end 
end 

그리고이

require 'spec_helper' 

describe MyCompany::SmartSet do 
    describe "..." do 
    ... 
    end 
end 

이를 /spec/lib/smart_set_spec.rb 예를 들어, 여기이 생성 된 이후 잘 작동 된 또 다른 하나 파일은 구조가 동일하지만 전혀 문제가 없습니다.

ResponseSet (문제 클래스)은 식별 할 수없는 이유로로드 문제가있는 것 같습니다. response_set_spec의 상단에

require 'response_set' 

를 추가, 또한

Loading development environment (Rails 3.0.4) 
ruby-1.9.2-p136 :001 > rs = MyCompany::ResponseSet.new 
LoadError: Expected /Users/my_stuff/projects/my_project/lib/response_set.rb to define ResponseSet 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:492:in `load_missing_constant' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:183:in `block in const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `each' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:503:in `load_missing_constant' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:183:in `block in const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `each' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `const_missing' 
    from (irb):1 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/railties-3.0.4/lib/rails/commands/console.rb:44:in `start' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/railties-3.0.4/lib/rails/commands/console.rb:8:in `start' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/railties-3.0.4/lib/rails/commands.rb:23:in `<top (required)>' 
    from script/rails:6:in `require' 
    from script/rails:6:in `<main>' 
ruby-1.9.2-p136 :002 > rs = MyCompany::ResponseSet.new 
=> [] 

을 : 레일 콘솔에서 처음 난 오류가 하나를 만들려고하지만, 나는 나중에 만들 수 있습니다. rb를 사용하면 해당 테스트를 실행할 수 있습니다. 그러나 smart_set_spec.rb에는 그런 것이 필요하지 않습니다. 나는 레일이 파일 구조 사물의 이러한 종류의 네임 스페이스 구조와 일치하는 방법에 대한 의견의 어떤 종류가 있는지 이해, 이제

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

을, 우리는 구조 조정 한 다음

application.rb에 자리에 우리의 모듈과 파일을 그것은 문제를 해결 한 것으로 보입니다. (우리가 전체 테스트를 실행할 때 이상한로드 오류를 잠시 보았지만, 이것들은 신비하게 사라졌습니다.) 그럼에도 불구하고 여기있는 모든 사람들은 당혹스러워하며 Rails가 너무 모순되어서 왜 우리가 그 이유를 알고 싶어하는지 조금도 짜증을 내지 않습니다. 보시다시피 네임 스페이스와 파일 구조가 완전히 다른 방식으로 처리되는 한 동일한 두 개의 파일이 있습니다. 실제로 우리는 전혀 문제를 일으키지 않은 유사한 네임 스페이스를 가진 'lib'의 최상위 레벨에 약 12 ​​개의 다른 파일을 가지고 있습니다. 아무도 여기 무슨 일이 일어 났는지 설명 할 수 있니?

답변

4

I는 레일 소스에 보면서 load_missing_constant 방법에

if file_path && ! loaded.include?(File.expand_path(file_path)) # We found a matching file to load 
    require_or_load file_path 
    raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless local_const_defined?(from_mod, const_name) 
    return from_mod.const_get(const_name) 
elsif ... 

절있다. 나는 이 raise 전에 호출되었다고 생각할 수 있습니다. 이것은 예에서 두 번째 호출에서 오류가 없다고 생각할 수 있습니다 ...

동일한 구조의 두 파일 다르게 행동하십시오. 일관성이없는 동작이있는 동안 응용 프로그램의 복사본을 만들고 일관성이없는 예를보기 위해 파트를 계속 제거합니다.

P. 나는 비슷한 질문을 여기에 제출했다 : http://www.ruby-forum.com/topic/2376956

+0

감사합니다. 의심스러워. Exception을 높이는 것이 날씨에 의존해야한다고 생각합니다. 'require_or_load'가 성공했습니다. 그러나 그때 다시 레일스 배짱이있는 미궁에 익숙하지 않습니다. –

+0

@Nick, 파일을로드 한 후 상수가 아직 정의되지 않은 경우 예외가 발생합니다. 귀하의 경우에는 파일이'MyCompany :: ResponseSet'을 정의하는 동안 파일이'ResponseSet'을 정의하는 것으로 보입니다 (이것은 나에게 보이는 방식이지만 전문가는 아닙니다). 불일치는 가장 이상한 것입니다. 원래의 문제를 단순화하지 않았습니까? 어쩌면'MyCompany :: SmartSet'은'/ lib/smart_set.rb'뿐 아니라'/ lib/my_company/smart_set.rb'에 있을까요? 비슷한 문제에 대해 [GitHub의 버그 보고서] (https://github.com/rails/rails/issues/2572)를 제출했습니다. – Alexey

+0

Nope. 파일 구조는 동일했습니다. 우리는 생각할 수있는 모든 가능한 차이를 확인하는 데 두 시간을 보냈습니다. 유일한 차이점은 각 클래스 (즉, 속성 및 메서드)의 실제 구현이지만 파일로드 방식에 영향을주지 않는 것은 아닙니다! –

27

우리는 파기 후에 Rails 3.x와 autoload_paths의 변경으로 인한 것으로 밝혀졌다.

이 사례는 테스트 (RAILS_ENV=test)에서만 나타났습니다. Rails가 컨트롤러를 로딩 할 때, 각 컨트롤러의 매칭 모델을 찾는데 주력했다. (이니셜 라이저에 ActionController :: Base.wrap_parameters가 설정 되었기 때문이다.) 결국 그것은 위에서 언급 한 방법 (load_missing_constant)으로 감습니다. autoload_paths에 lib와 lib/**가 모두 포함되어 있기 때문에 Rails는 lib 아래의 모든 하위 디렉토리에서 모든 파일을 가져 왔습니다. 불행히도 하위 디렉토리에서로드 할 때 암시 된 네임 스페이스를 무시하는 것으로 보입니다. foo/base.rb가 BaseFoo::Base을 정의 할 것으로 예상했습니다. 그게 핵심 결함 인 것 같습니다 : load_missing_constantsearch_for_file을 호출합니다.이 파일은 이름이 일치하는 파일을 반환합니다 (예 : 내 예제에서는 foo/base.rb가 base.rb와 일치하여 반환되었습니다).

Ruby에서 가정 한 네임 스페이스 - 디렉토리 매핑을 위반하거나, autoload_paths의 오용으로 인해 Rails에서 오류가 발생했는지 말하는 것은 어렵습니다.

우리는 autoload_paths에서 lib/**을 제거하고 application.rb에 필요한 require 문을 추가하여이 문제를 해결했습니다.

+2

나는 똑같은 것을해야했다. 나는 근본 문제에 대해 당신이 올바른 길을 가고 있다고 생각합니다. 아무도 이것에 대해 불평하지 않습니다. –

+8

레일이 저를 괴롭히기 시작했습니다. – Zabba

+0

@Zabba : 예, 곧은 재킷으로 변하는 것 같습니다. –

4

Brendan이 올바른 방향을 가리켰다면 autoload_paths를 확인하십시오. 나는 비슷한 오류를했고,이 application.rb에 나를 위해 범인했다 : 나는 하위 디렉토리를 가지고와 함께 모델에 대한 모듈을 사용하기 시작하면

config.autoload_paths += Dir["#{Rails.root}/app/models/[a-z]*"] 

내 애플은 행복하지 않았다. 내가 네임 스페이스 클래스가 잘못 자동으로 적재되는과 똑같은 문제로 고생 한

config.autoload_paths += Dir["#{Rails.root}/app/models/aaaaaaaaa"] 
config.autoload_paths += Dir["#{Rails.root}/app/models/bbbbbbbbb"] 
1

: 나는 자동로드에 바로 비 모듈 디렉토리를 내 변경되었습니다. 이것은 (브렌든의 대답에서) 그것을 해결하는 단서이다 :

우리 autoload_paths는 lib 디렉토리 및/**, 레일 lib 디렉토리 아래의 모든 하위 디렉토리의 모든 파일에 뽑아 lib에 모두 포함되어 있기 때문에. 불행히도 하위 디렉토리에서로드 할 때 암시 된 네임 스페이스를 무시하는 것으로 보입니다. 그것은 foo/base.rb가 Base vs. Foo :: Base를 정의 할 것으로 예상했습니다. 그게 핵심 결함 인 것 같습니다. load_missing_constant는 이름이 일치하는 파일을 반환하는 search_for_file을 호출합니다 (예 : foo/base.rb가 base.rb와 일치하여 반환되었습니다). ,

%w(file1 file2 ...).each do |file| 
    require "events/#{file}" 
end 

을 그리고이 조금 매뉴얼 동안 :

은 내가 app/components/events/*Events::Something라는 내 모든 네임 스페이스 클래스를 이동하고 다음과 같은 내용으로 파일 app/components/events.rb을 만들어 그것을 해결했습니다 응용 프로그램, 콘솔 및 테스트 모드 모두에서 작동합니다.

0

주목해야 할 또 다른 포인트는 서비스 폴더에 올바른 경로가 있는지 여부입니다.

는 올바른 경로에 의해, 내 말은

ENGINE_NAME/응용 프로그램/서비스/ENGINE_NAME/your_service.rb

실수로 서비스 내부 ENGINE_NAME 폴더를 잊고,이 이상한 행동을 가지고있다.

관련 문제