Ruby on Rails - RSpec: paranoid2 - 无法修改冻结的哈希



我正在为我的模型进行RSpec测试,该模型使用paranoid2 gem。这是某种偏执狂或acts_as_paranoid - 用它自己的版本覆盖 .delete 和 .destroy 以及其他一些版本,它将数据标记为已删除而不是删除它,直到您使用(forced: true)参数强制它。

我的应用程序运行良好,我只在 rspec 方面遇到问题。

规格/型号/slide_spec.rb:

describe Slide do
 let (:slide) { build(:slide) }
  describe "after .destroy(force: true)" do
   before do      
      slide.save
      slide.destroy(force: false)      
   end
    it "is invisible" do
      expect{slide.destroy(force: true)}.to_not change(Slide, :count)
    end
    it "visible if .only_deleted" do
      expect{slide.destroy(force: true)}.to change(Slide.only_deleted, :count).by(-1)
    end    
    it "visible if .with_deleted" do
      expect{slide.destroy(force: true)}.to change(Slide.with_deleted, :count).by(-1)
    end
  end
 end

rspec 输出:

  after .destroy(force: true)
    visible if .with_deleted (FAILED - 1)
    visible if .only_deleted (FAILED - 2)
    is invisible (FAILED - 3)
Failures:
  1) Slide after .destroy(force: true) visible if .with_deleted
     Failure/Error: expect{slide.destroy(force: true)}.to change(Slide.with_deleted, :count).by(-1)
     RuntimeError:
       can't modify frozen Hash
     # ./spec/models/slide_spec.rb:52:in `block (4 levels) in <top (required)>'
     # ./spec/models/slide_spec.rb:52:in `block (3 levels) in <top (required)>'
  2) same as above
  3) same sa above
/

app/model/slide.rb:

class Slide < ActiveRecord::Base
    paranoid
    ...

发生这种情况是因为 Rails 在对模型调用 destroy 后用 freeze 标记内部属性哈希。这个冻结的哈希禁止对象进一步更改:后来的destroy(force: true)想要删除idreload想要用数据库中的新值覆盖一些属性 - 两者都会失败。

避免此问题的唯一方法是手动重新加载对象:

describe "after .destroy(force: true)" do
  before do
    slide.save
    slide.destroy(force: false)
    @slide = Slide.with_deleted.find(slide.id)  # manual reload
  end
  it "is invisible" do
    expect{@slide.destroy(force: true)}.to_not change(Slide, :count)
  end
  it "visible if .only_deleted" do
    expect{@slide.destroy(force: true)}.to change(Slide.only_deleted, :count).by(-1)
  end
  it "visible if .with_deleted" do
    expect{@slide.destroy(force: true)}.to change(Slide.with_deleted, :count).by(-1)
  end
end

相关内容

  • 没有找到相关文章

最新更新