叉勺(Spork)不会重新加载代码。

11
我正在使用以下gem和ruby-1.9.3-p194:
  • rails 3.2.3

  • rspec-rails 2.9.0

  • spork 1.0.0rc2

  • guard-spork 0.6.1

使用的所有gem的完整列表可以在此 Gemfile.lock Gemfile 中找到。
我使用以下配置文件: 如果我修改任何模型(或app/validators中的自定义验证器等),重新加载代码将无法正常工作。我的意思是,当我运行specs(在guard控制台上按Enter)时,Spork包含“旧代码”,并且我会收到过时的错误消息。但是,当我手动重新启动Guard和Spork(CTRC-C CTRL-d guard)时,一切都正常工作。但是几次后会变得很累。
问题:
请有人查看我的配置文件,并修复阻止代码更新的错误。
或者也许这是最新Rails版本的问题?
PS:这个问题在一些项目中反复出现(在一些项目上没有)。但是我还没有弄清楚为什么会发生这种情况。

PS2 或许这个问题与 ActiveAdmin 有关?当我修改 app/admin 文件时,代码会重新加载。

7个回答

8

解决方法:

# config/environments/test.rb
config.cache_classes = false

但这是一个“双刃剑”。

现在规格运行时间大约增加了2.0倍。但仍然比一遍又一遍地重启Spork快。


更新日期:2013年6月28日

使用Zeus。它完全有效。基准测试结果在底部。

如果您正在使用1.9.3,请考虑安装特殊补丁来真正加快加载应用程序的速度。

RVM补丁集

rbenv说明

背景和基准测试:

我有一个相当大的1.9.3应用程序,我想加快应用程序的加载速度,但Spork不起作用,因此我开始寻找其他解决方案:

我写了一个空规格来查看加载我的应用程序需要多长时间

-/spec/empty_spec.rb

require 'spec_helper'

describe 'Empty' do

end

plain 1.9.3

时间 rspec spec/empty_spec.rb 64,65秒 用户 2,16秒 系统 98% cpu 1:07,55 总共

1.9.3 + rvm patchsets

时间 rspec spec/empty_spec.rb 17,34秒 用户 2,58秒 系统 99% cpu 20,047 总共

1.9.3 + rvm patchsets + zeus

时间 zeus test spec/empty_spec.rb 0,57秒 用户 0,02秒 系统 58% cpu 1,010 总共 [w00t w00t!]


是的但是。。这不是“纯粹”的基准测试。我只是用那个选项运行了几次规范,有时没有用。 - nothing-special-here
在我的项目中,不缓存类会导致FactoryGirl定义的间歇性错误,在一些Spork运行后消失。缓存类可以解决这个问题,但是又回到了最初的错误... - Martin T.
Zeus非常容易出现bug,特别是在虚拟机上。 - valk

7

此外,您可以为您的模型、控制器和其他代码添加守卫。这将使得在这些文件发生变化时,守卫重新加载spork。

guard 'spork',
      :rspec_env => {'RAILS_ENV' => 'test'} do
  watch(%r{^app/models/(.+)\.rb$})
  watch(%r{^lib/(.+)\.rb$})
end

2
是的。 :) 在我的电脑上,重新加载Spork大约需要20-30秒的时间。我通常在重构模型时只运行单个规格(当我进行更改等操作时)。 - nothing-special-here
你一定有一个很大的应用程序。或者是古董电脑 :) 我的 spork 要花费 5-7 秒来重新加载。 - Sergio Tulentsev
1
第二个选项。:D 这是一台2009年的笔记本电脑。 - nothing-special-here
这对于重新加载spec/support目录中的支持文件非常有用,谢谢。 - DazBaldwin
这种方法对我在使用RSpec和Sinatra时非常有效。Sinatra没有像Rails那样的自动加载功能,因此这是我发现的将修改后的类与Guard和Spork一起用于RSpec的最佳选择。 - Kyle Tolle
显示剩余3条评论

5

我曾经遇到过同样的问题。当我更改model_spec.rb文件时,测试被重新加载并成功运行。但是当我更改model.rb文件时,测试似乎被缓存了,因此更改没有应用。

为了使事情正常工作,需要结合几个答案:

# /config/environments/test.rb
config.cache_classes = !(ENV['DRB'] == 'true')

# spec_helper.rb
Spork.each_run do
  .....
  ActiveSupport::Dependencies.clear
end

我还将spork更新到(1.0.0rc3),并用@23inhouse提到的spork-rails代替了spork gem。然而,我在gemfile中没有看到两者之间的任何区别,尽管升级spork可能会产生影响。
希望这能帮助其他人不再花费更多时间挣扎。

4

尽管Spork很棒,但似乎在每次Rails升级时都会出问题 :(

在Rails 3.2.3上,我已经在spec/spec_helper.rb中添加了以下片段,以强制重新加载应用程序目录中的所有ruby文件。

Spork.each_run do
  # This code will be run each time you run your specs.
  Dir[Rails.root + "app/**/*.rb"].each do |file|
    load file
  end
end

似乎现在唯一可靠的方法。确实会拖慢速度,但总体而言,仍然比没有 spork 更快。 - artemave
6
我收回之前的话。不要那样做。这个操作无法卸载类,会导致例如after_create被注册两次等问题。 - artemave

3

在我的情况下,问题是Draper。它不允许spork重新加载模型。

Spork.prefork do
  ENV['RAILS_ENV'] ||= 'test'

  # Routes and app/ classes reload
  require 'rails/application'
  Spork.trap_method(Rails::Application::RoutesReloader, :reload!)
  Spork.trap_method(Rails::Application, :eager_load!)

  # Draper preload of models
  require 'draper'
  Spork.trap_class_method(Draper::System, :load_app_local_decorators)

  # Load railties
  require File.expand_path('../../config/environment', __FILE__)
  Rails.application.railties.all { |r| r.eager_load! }
  ...

在加载环境之前,记得为Draper插入陷阱方法。


2

Spork进行了清理,并提取了一些功能。

https://github.com/sporkrb/spork-rails

将以下内容添加到您的Gemfile中:

gem 'spork-rails'


感谢提供代码库的URL,我会去查看一下。 - nothing-special-here

0

通过在spork.each_run方法中添加更多内容,解决了相同的问题。

Rails 3.2.2

此外,我建议一次只运行一个测试。这样更快,更安静,而且我们通常也是一次只处理一个测试。

rspec spec -e 'shows answer text'

我发现使用守卫(Guard)要比直接等待它完成更快、更容易。此外,当我进行更改时,守卫并不总是重新加载正确的文件并运行正确的测试。

spec_helper.rb 文件:

require 'spork'

Spork.prefork do
  ENV['RAILS_ENV'] ||= 'test'

  require File.expand_path('../../config/environment', __FILE__)
  require 'rspec/rails'
  require 'rspec/autorun'
  require 'capybara/rspec'
  require 'capybara/rails'

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
end

Spork.each_run do
  Dir[Rails.root.join('spec/support/**/*.rb')].each {|f| require f}

  RSpec.configure do |config|
    # config.mock_with :mocha
    # config.mock_with :flexmock
    # config.mock_with :rr
    config.mock_with :rspec

    # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
    config.fixture_path = "#{::Rails.root}/spec/fixtures"

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true

    # If true, the base class of anonymous controllers will be inferred
    # automatically. This will be the default behavior in future versions of
    # rspec-rails.
    config.infer_base_class_for_anonymous_controllers = false

    config.include RequestHelpers, :type => :request

    config.before :suite do
      DatabaseCleaner.strategy = :truncation
      DatabaseCleaner.clean_with :truncation
    end

    config.before :each do
      DatabaseCleaner.start
    end

    config.after :each do
      DatabaseCleaner.clean
    end

    config.include(MailerHelpers)
    config.before(:each) { reset_email }
  end
  # This code will be run each time you run your specs.
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接