如何在Rails模型的Rspec测试中禁用belongs_to:touch选项?

dgi*_*rez 2 rspec metaprogramming ruby-on-rails associations belongs-to

拥有大型模型堆栈并广泛使用玩偶缓存技术,最终会在模型更新后"触摸"许多父模型.

在测试时,除非您尝试专门测试该功能,否则这似乎是浪费时间.

有没有办法阻止模型与测试环境或测试级别touchbelongs_to关联?

更新1:

我对案件的第一次尝试是

# /config/initializers/extensions.rb
#
class ActiveRecord::Base
  def self.without_touch_for_association(association_name, &block)
    association_name = association_name.to_sym
    association = self.reflect_on_all_associations(:belongs_to).select { |reflection| reflection.name == association_name }.first
    options = association.options
    association.instance_variable_set :@options, options.except(:touch)

    yield

    association.instance_variable_set :@options, options
  end
end

Post.without_touch_for_association(:user) do
  Post.last.save
end
Run Code Online (Sandbox Code Playgroud)

当然,没有成功和拯救Post.last仍然触及它User.

更新理由:

我理解并同意这种方法可能是错误的根源,而且根本不是一个好的做法.问题是我有一个巨大的套件,有很多集成和单元测试.玩偶缓存也深入到模型树中.每当我查看日志时,我都会看到大量与触摸相关的查询.我知道最好的方法是优化单元测试以增加更多的模拟和存根以及更少的持久性.在集成测试中解决问题更加困难.

无论如何,我是为了学习和研究而提出这个问题.我有兴趣探索这种技术的潜在速度改进.

解决方案:请参阅下面的工作代码答案.

DNN*_*NNX 10

假设您使用的是Rails 4.1.4或更高版本:

User.no_touching do
  Post.last.save
end
Run Code Online (Sandbox Code Playgroud)

甚至

ActiveRecord::Base.no_touching do
  Post.last.save
end
Run Code Online (Sandbox Code Playgroud)

请参阅ActiveRecord :: NoTouching.