Reputation: 1409
I've added a very simple counter to my post model. Whenever someone open a post, it updates the corresponding field :counter
by 1.
def show
@story = Story.find(params[:id])
@comment = @story.comments.build
@comments = @story.comments.arrange(order: :created_at)
@story.increment!(:counter) # ---Here---
respond_to do |format|
format.html # show.html.erb
format.json { render json: @story }
end
end
Actually, I checked the DB and this thing is working. But my test get fail:
it "raise the counter by one when visiting a page" do
story = FactoryGirl.create(:story)
expect {
visit story_url(story)
}.to change { story.counter }.by(1)
end
And it shows:
1) Stories raise the counter by one when visiting a page
Failure/Error: expect {
result should have been changed by 1, but was changed by 0
# ./spec/requests/stories_spec.rb:8:in `block (2 levels) in <top (required) >'
here is my test.log:
Started POST "/stories" for 127.0.0.1 at 2012-09-22 11:31:32 +0330
Processing by StoriesController#create as HTML
Parameters: {"utf8"=>"✓", "story"=>{"title"=>"sfomqd8s2r", "content"=>"Beatae voluptatibus quia cumque voluptate. Beatae sed aut sit. Fugiat deleniti et vitae accusantium blanditiis. Consequatur at itaque temporibus autem. Quo beatae delectus minus porro et.", "tag_names"=>""}, "commit"=>"submit"}
(0.1ms) SELECT MIN("tags"."stories_count") AS min_id FROM "tags"
(0.1ms) SELECT MAX("tags"."stories_count") AS max_id FROM "tags"
Tag Load (0.1ms) SELECT name, stories_count FROM "tags" ORDER BY name asc
(0.1ms) SAVEPOINT active_record_1
SQL (1.5ms) INSERT INTO "stories" ("comments_count", "content", "counter", "created_at", "publish_date", "slug", "title", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) [["comments_count", 0], ["content", "Beatae voluptatibus quia cumque voluptate. Beatae sed aut sit. Fugiat deleniti et vitae accusantium blanditiis. Consequatur at itaque temporibus autem. Quo beatae delectus minus porro et."], ["counter", 0], ["created_at", Sat, 22 Sep 2012 11:31:32 IRST +03:30], ["publish_date", nil], ["slug", nil], ["title", "sfomqd8s2r"], ["updated_at", Sat, 22 Sep 2012 11:31:32 IRST +03:30], ["user_id", nil]]
(0.1ms) RELEASE SAVEPOINT active_record_1
Redirected to http://www.example.com/stories/2
Completed 302 Found in 18ms (ActiveRecord: 1.9ms)
Started GET "/stories/2" for 127.0.0.1 at 2012-09-22 11:31:32 +0330
Processing by StoriesController#show as HTML
Parameters: {"id"=>"2"}
(0.1ms) SELECT MIN("tags"."stories_count") AS min_id FROM "tags"
(0.1ms) SELECT MAX("tags"."stories_count") AS max_id FROM "tags"
Tag Load (0.1ms) SELECT name, stories_count FROM "tags" ORDER BY name asc
Story Load (0.1ms) SELECT "stories".* FROM "stories" WHERE "stories"."id" = ? LIMIT 1 [["id", "2"]]
CACHE (0.0ms) SELECT "stories".* FROM "stories" WHERE "stories"."id" = ? LIMIT 1 [["id", "2"]]
Comment Load (0.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."story_id" = 2 ORDER BY (case when comments.ancestry is null then 0 else 1 end), comments.ancestry, created_at
SQL (0.3ms) UPDATE "stories" SET "counter" = 1 WHERE "stories"."id" = 2
Tag Load (0.2ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."story_id" = 2
Rendered stories/_story_operation.html.erb (3.5ms)
Rendered stories/_story.html.erb (5.4ms)
Rendered comments/_form.html.erb (7.1ms)
Completed 200 OK in 34ms (Views: 18.1ms | ActiveRecord: 1.1ms | Solr: 0.0ms)
(0.7ms) rollback transaction
I can't understand whats happening. Maybe it's something about Capybara or the way I've wrote the test.
Upvotes: 2
Views: 349
Reputation: 84142
As you know,
expect {
visit story_url(story)
}.to change { story.counter }.by(1)
compares the value of story.counter
before and after the block is executed. When your controller loads and modifies the story, that is a completely separate ruby object (that happens to refer to the same row in the database): the story
object in your spec code is unaware of the changes made to the database and holds the same (now stale) data.
To get your spec passing you could instead check whether story.reload.counter
is changing.
Upvotes: 2