【问题标题】:Rails 3 and Rspec: counter cache column being updated to 2 when expected 1Rails 3 和 Rspec:计数器缓存列在预期 1 时更新为 2
【发布时间】:2011-11-23 19:47:34
【问题描述】:

我正在使用 Rspec 测试一个名为 Solutions 的模型,它有很多赞。解决方案存储它有多少喜欢(counter_cache)。它有一个“likes_count”属性(以及相应的 db 字段)。

当我创建与解决方案关联的 Like 记录时,我希望解决方案属性“likes_count”应该从 nil 更新为 1。当我在控制台中执行此操作时,它可以工作。

但是当我运行规范时,在控制台中执行与我相同的操作时,它会更新两次“likes_count”字段,将其设置为 2。

看看(在控制台中)WORKING

irb(main):001:0> solution = Factory(:solution)
irb(main):004:0> solution.likes_count 
=> nil
irb(main):006:0> like = Factory(:like, :likeable => solution)
=> #<Like id: 1, user_id: 2, likeable_id: 1, likeable_type: "Solution", 
   created_at: "2011-11-23 19:31:23", updated_at: "2011-11-23 19:31:23">
irb(main):007:0> solution.reload.likes_count
=> 1

查看规范结果不工作

 1) Solution counter cache should be increased when a like is created
 Failure/Error: subject.reload.likes_count.should be 1

   expected #<Fixnum:3> => 1
        got #<Fixnum:5> => 2

   Compared using equal?, which compares object identity,
   but expected and actual are not the same object. Use
   'actual.should == expected' if you don't care about
   object identity in this example.
 # ./spec/models/solution_spec.rb:45:in `block (3 levels) in <top (required)>'

这是规格:

describe "counter cache" do
  let(:solution) { Factory(:solution) }

  it "should be increased when a like is created" do
    Factory(:like, :likeable => solution)
    solution.reload.likes_count.should be 1
  end
end  

我查看了 test.log,发现更新计数器缓存列的 db 查询在测试中被调用了两次。

  SQL (0.5ms)  INSERT INTO "likes" ("created_at", "likeable_id", "likeable_type", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?)  [["created_at", Wed, 23 Nov 2011 19:38:31 UTC +00:00], ["likeable_id", 121], ["likeable_type", "Solution"], ["updated_at", Wed, 23 Nov 2011 19:38:31 UTC +00:00], ["user_id", 204]]
  SQL (0.3ms)  UPDATE "solutions" SET "likes_count" = COALESCE("likes_count", 0) + 1 WHERE "solutions"."id" IN (SELECT "solutions"."id" FROM "solutions" WHERE "solutions"."id" = 121 ORDER BY id DESC)
  SQL (0.1ms)  UPDATE "solutions" SET "likes_count" = COALESCE("likes_count", 0) + 1 WHERE "solutions"."id" IN (SELECT "solutions"."id" FROM "solutions" WHERE "solutions"."id" = 121 ORDER BY id DESC)
  Solution Load (0.3ms)  SELECT "solutions".* FROM "solutions" WHERE "solutions"."id" = ? LIMIT 1  [["id", 121]]

【问题讨论】:

    标签: ruby-on-rails activerecord rspec counter-cache


    【解决方案1】:

    我遇到了同样的问题。事实证明,我的spec_helper.rb 正在第二次加载模型,因此创建了第二次回调来更新计数器。确保您的解决方案模型没有被其他进程重新加载。

    上面的答案也是正确的:您需要使用== 而不是be 来进行比较,但这不会修复您在日志文件中看到的多个更新。

    【讨论】:

    • 是的,这就是问题所在。非常感谢,jkronz!这个 sn-p 导致了 Spork.each_run 块上的问题:Dir["#{Rails.root}/app/**/*.rb"].each { |f| load f }
    • 我也有同样的问题,但是我找不到它在哪里加载了两次。关于如何调试这个的任何建议?我正在使用导轨 4.1。谢谢。
    【解决方案2】:

    您的日志中有答案:

    • 当您使用be 时,它会比较object_id,这对于true1 等几个对象总是相同的。 1id 似乎是 2。在控制台尝试:1.object_id #=&gt; 2

    • 因此,将您的测试替换为:solution.reload.likes_count.should eql 1 甚至 solution.reload.likes_count.should == 1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-16
      • 2017-10-26
      相关资源
      最近更新 更多