我遇到counter_cache
的问题。说我有三个型号。用户和文章有很多ArticleUpvotes。用户可以为文章创建ArticleUpvote。
# models/user.rb
class User < ActiveRecord::Base
has_many :upvotes, class_name: 'ArticleUpvote'
def upvote(article)
article.upvotes.create(user: self)
end
end
# models/article.rb
class Article < ActiveRecord::Base
has_many :upvotes, class_name: 'ArticleUpvote'
end
# models/article_upvote.rb
class ArticleUpvote < ActiveRecord::Base
include ArticleVote
belongs_to :article, dependent: :destroy, counter_cache: :upvotes_count
end
# models/concerns/article_vote
module ArticleVote
extend ActiveSupport::Concern
included do
belongs_to :user
validates :user, presence: true
end
end
context 'voting' do
let(:user) { FactoryGirl.create(:user) }
let(:article) { FactoryGirl.create(:article) }
context '#upvote' do
it 'adds upvote to article' do
user.upvote(article)
expect(article.upvotes.size).to eq 1
end
end
end
1) User voting #upvote adds upvote to article
Failure/Error: expect(article.upvotes.size).to eq 1
expected: 1
got: 0
(compared using ==)
只需将我的测试体更改为:
user.upvote(article)
article.upvotes.size # Added this line compared to failing version
expect(article.upvotes.size).to eq 1
或者这样做:
expect{ user.upvote(article) }.to change{ article.upvotes.size }.by 1
使测试通过。为什么会这样?
答案 0 :(得分:1)
更改您的示例如下:
it 'adds upvote to article' do
user.upvote(article)
expect(article.reload.upvotes.size).to eq 1
end
您的给定示例失败的原因是规范持有使用article
通过FactoryGirl
创建的FactoryGirl.create(:article)
对象,并且它不知道发生了更改数据库。您需要reload
文章,以便反映变化。
在其他通过测试中,即
expect{ user.upvote(article) }.to change{ article.upvotes.size }.by 1
您的示例已通过,因为change
方法会发生隐式重新加载。