2015-06-05 3 views
0

Я читаю книгу The Rails 4 Way, и я узнаю о Rspec. Я знаю, что ленивая оценка - это когда выражение не оценивается до тех пор, пока оно не будет использовано, тогда как нетерпеливая оценка - это то, где выражение оценивается немедленно. let использует ленивую оценку, где выражение в блоке не будет выполняться до тех пор, пока не будет использована переменная let. И let! использует нетерпеливую оценку.ленивая оценка и метод rspec let

Однако я все еще немного смущен насчет let и let! в rspec. Давайте рассмотрим пример ниже, из книги:

describe BlogPost do 
    let(:blog_post) { BlogPost.create title: 'Hello' } 
    let!(:comment) { blog_post.comments.create text: 'first post' } 

    describe "#comment" do 
    before do  
     blog_post.comment("finally got a first post") 
    end 

    it "adds the comment" do 
     expect(blog_post.comments.count).to eq(2) 
    end 
    end 
end 

Автор говорит следующее:

Поскольку комментарий блок никогда не был выполнен первым утверждения, если вы использовали определение LET, только один комментарий добавит в эту спецификацию , хотя реализация может работать. Используя let! мы гарантируем, что исходный комментарий будет создан, и спецификация теперь пройдет.

Я думал, что с let, будет создано два комментария и с let !, будет создано три комментария. Зачем? Поскольку с let, блок не будет выполнен, поэтому никаких комментариев не создаются. Тем не менее, комментарий будет лениться в предыдущем блоке, так что теперь у нас есть один комментарий. Затем блок комментариев будет снова оцениваться в блоке «добавляет комментарий», поэтому будут созданы два комментария. Так как пусть! немедленно оценивается, поэтому создается 3 комментария, а не только два.

Что я не понимаю здесь?

ответ

0

Вы видите вызовы ленивого метода comment, где их нет.

Однако, комментарий будет ленивым оценена в блоке перед тем

Нет, до того блока, который вы имеете показать нам не имеет ничего общего с let(:comment).

Использование blog_post.comment не связано с Rspec, или let. Он использует метод, comment, определенный на вашей модели BlogPost.

Затем комментарий блок будет оцениваться снова в «добавляет комментарий» блок

Опять же, нет, нет никакого вызова вообще из comment внутри этого блока. Единственное, что даже близко, это blog_post.comments, комментарий s множественное число, а не комментарий, и это доступ к отношениям has_many на вашей модели.

Единственный способ вызвать comment определенный let(:comment) является с слово comment. Методы, имеющие одинаковые имена, но относящиеся к разным объектам, не имеют отношения к делу.

+0

Если вы не указали метод комментариев, как вы сказали выше, то почему автор говорит: «Если бы вы использовали определение let, только один комментарий был бы добавлен в эту спецификацию, даже если реализация может работать. let! мы гарантируем, что начальный комментарий будет создан, и спецификация теперь пройдет (есть 2 комментария) » – Donato

+0

@Donato Поскольку вы все еще создаете комментарий, вы просто не создаете его с помощью ленивого метода' comment'. Блок 'before' ** создает ** комментарий, но он не имеет ничего общего с« ... комментарий будет лениться ». Ни в коем случае нигде в показанном коде не будет «оцениваться» лениво; это точка зрения автора. Вот почему вам нужно 'let!' – meagar

+0

@meager, где еще создается комментарий? Я вижу только создание в блоке метода let. Нигде более. – Donato

Смежные вопросы