Szilard Magyar Szilard Magyar - 3 months ago 6
Ruby Question

Why does this RSpec example require "let!" instead of "let"?

I was able to make the test work with the following code, but it seems to be weird and I don't totally understand it.

Can somebody tell me if creating the objects this way is the optimal one?

Why do I have to only use

let!
for the 2nd
post_comment_reply
creation and why don't I for the rest of the objects?

post_comment.rb

belongs_to :post, touch: true
belongs_to :user
has_many :post_comment_replies, dependent: :destroy
has_many :users, through: :post_comment_replies

def send_post_comment_reply_creation_notification(reply)
post_repliers = ([user] + [post.user] + users).uniq - [ reply.user ]
post_repliers.each do |replier|
Notification.create(recipient_id: replier.id, sender_id: reply.user_id, notifiable: self.post, action: "commented")
end
end


post_comment_spec.rb

describe "instance methods" do
let(:post_user) { create(:user) }
let(:comment_user) { create(:user) }
let(:reply_user) { create(:user) }
let(:reply_user_2) { create(:user) }
let(:post_reader) { create(:user) }
let(:post) { create(:post, user: post_user) }
let(:post_comment) { create(:post_comment, user: comment_user) }
let(:post_comment_reply) { create(:post_comment_reply, post_comment: post_comment, user: reply_user) }
let!(:post_comment_reply_2) { create(:post_comment_reply, post_comment: post_comment, user: reply_user_2) }


it "send_post_comment_reply_creation_notification" do
expect{
post_comment.send_post_comment_reply_creation_notification(post_comment_reply)
}.to change{Notification.count}.by(3)
end

end

Answer

let is lazy. If you don't reference it, it doesn't get evaluated and, in your case, side effects don't happen (side effect being the creation of database entry).

let!, on the other hand, is always evaluated.

Comments