Sco*_*vey 2 ruby ruby-on-rails
在观看了Corey 的Fasts Rails Tests讲话和Avdi阅读Object on Rails后,我正在设置我的新Rails 3.2应用程序以利用这些概念.
为了让一切正常,我开始使用这个示例spec文件.
# spec_no_rails/projects/financials_spec.rb
require_relative '../spec_no_rails_helper'
class DummyProject
include Modules::Projects::Financials
end
describe Modules::Projects::Financials do
it 'should have some method' do
DummyProject.new.foo.should == 'bar'
end
end
Run Code Online (Sandbox Code Playgroud)
这是用于要求模块的初始spec_no_rails_helper.rb文件
# spec_no_rails/spec_no_rails_helper.rb
Dir["#{Dir.pwd}/app/pimms/**/*.rb"].each { |file| require file }
Run Code Online (Sandbox Code Playgroud)
然后我开始创建新的示例模块.
# app/pimms/modules/projects/financials.rb
module Modules::Projects::Financials
def foo
'bar'
end
end
Run Code Online (Sandbox Code Playgroud)
为了看到当我将新的独立模块包含在我的一个ActiveRecord类中时,一切都将起作用,我将以下行添加到我的一个模型中.
# app/models/project.rb
class Project < ActiveRecord::Base
include Modules::Projects::Financials
end
Run Code Online (Sandbox Code Playgroud)
这让我可以打开控制台,看到一切都按预期工作.
> Project.first.foo
=> "bar"
Run Code Online (Sandbox Code Playgroud)
所以在这个阶段我定义了一个在app/pimms/modules/projects/financials.rb下定义的命名空间独立模块,我可以将其包含在Rails模型中,一切都按预期工作.
我遇到的问题是当我尝试运行规范时,我得到以下内容.
> bundle exec rspec spec_no_rails/
/Users/scott/Code/pimms/spec_no_rails/projects/financials_spec.rb:5:in `<class:DummyProject>': uninitialized constant DummyProject::Modules (NameError)
from /Users/scott/Code/pimms/spec_no_rails/projects/financials_spec.rb:4:in `<top (required)>'
from /Users/scott/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `load'
from /Users/scott/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `block in load_spec_files'
from /Users/scott/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `map'
from /Users/scott/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `load_spec_files'
from /Users/scott/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/command_line.rb:22:in `run'
from /Users/scott/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:80:in `run_in_process'
from /Users/scott/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:69:in `run'
from /Users/scott/.rvm/gems/ruby-1.9.3-p125/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:10:in `block in autorun'
Run Code Online (Sandbox Code Playgroud)
因此发生这种情况的原因是因为在运行测试时尚未定义Modules :: Projects命名空间.我猜测当我将模块与Rails应用程序一起使用时,我没有必要定义Modules :: Projects命名空间,因为Rails为我处理了这个问题.
为了让测试按预期运行,我必须在spec_no_rails_helper.rb文件中定义命名空间,就像这样.
# spec_no_rails/spec_no_rails_helper.rb
module Modules
module Projects
end
end
Dir["#{Dir.pwd}/app/pimms/**/*.rb"].each { |file| require file }
Run Code Online (Sandbox Code Playgroud)
这显然不太理想,因为我必须手动为任何独立的模块或类创建所有命名空间,而我不在Rails之外测试.
有没有更好的方法来设置我的Rails应用程序,以便我可以轻松运行测试套件而不依赖于Rails?
我认为这是因为您已经定义了模块.你试图像这样定义它:
module Modules::Projects::Financials
def foo
'bar'
end
end
Run Code Online (Sandbox Code Playgroud)
但Ruby会通过先尝试找到Modules
模块,然后是Projects
模块然后最终定义Financials
模块来解释这一点,但只有它能找到前两个模块.
在你的情况下,无法找到的第一个二等弹出这样的.
继续,启动irb
并将上面的代码示例复制并粘贴到其中.您将看到在运行规范时获得的完全相同的错误.
解决这个问题的方法是在每个文件中定义/重新打开模块:
module Modules
module Projects
module Financials
def foo
'bar'
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
现在,每次加载这些文件中的每一个时,它都将定义或重新打开模块,为它们添加功能.关于这一点最好的部分是,无论是否Modules
先定义都无关紧要,它无论如何都只是定义它.
现在要解决这一点:为什么它在Rails中有效?
哦,男人,Rails完全做了一些很棒的东西!
我实际上介绍了Rails如何在我的"错误参数类型"截屏视频中处理模块的自动定义.好吧,我并没有完全涵盖模块是如何自动加载的,但是(扰流警报)它是那里出错的罪魁祸首.
我不打算强迫你看.问题在于内部的这些线activesupport/lib/active_support/dependencies.rb
.
load_missing_constant
当Rails无法找到常量时,该方法将被使用.那是当Rails的神奇自动装载工具开始发挥作用的时候.它调用此方法,并尝试查找定义此模块的文件.
如果它不能这样做,它会这样做:
mod = Module.new
into.const_set const_name, mod
autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path)
return mod
Run Code Online (Sandbox Code Playgroud)
这是在该文件中的autoload_module!
方法内dependencies.rb
.
这段代码的作用很简单:创建一个新模块,将其常量名称设置为缺少的名称,将其添加qualified_name
到autoloaded_constants
并返回该模块.
这就是为什么Rails定义你的模块,即使它们确实不存在.你完全绕过了你的规范(有充分的理由,你不想要所有那些令人讨厌的Rails垃圾),所以它不会自动加载模块.
归档时间: |
|
查看次数: |
504 次 |
最近记录: |