Джесси
Это все равно пройдет, если вы закомментируете 2-ые две строки ранее (: каждая), которые не влияют на пример «следует создать новую ставку».
Ключевое слово lambda создает произвольный блок кода, который не выполняется при его определении, но фактически является объектом, который можно назначить переменной и выполнить позже:
the_post = lambda do
post 'bid', :bid => { :auction_id => 1, :user_id => @user.id, :point => 1 }
end
На данный момент этот код не выполняется, но мы можем ссылаться на него с помощью переменной 'the_post'. Теперь мы можем отправить его «следует», а затем «изменить ...», например:
the_post.should change(Bid, :count).by(1)
Когда эта строка выполняется, происходит несколько вещей. Материал справа от 'should' оценивается первым, инициализируя объект соответствия rspec с некоторыми инструкциями. Это совпадение является аргументом «следует» - эквивалент этого:
matcher = change(Bid, :count).by(1)
the_post.should(matcher)
Метод 'should' вызывается для the_post, который является блоком кода (который еще не был выполнен). Под капотом метод 'should' передает self (the_post) в matcher, поэтому matcher теперь имеет все необходимое для оценки примера.
Устройство сопоставления вызывает Bid.count и записывает значение. Затем он выполняет блок (the_post), а затем вызывает Bid.count во второй раз и сравнивает его со значением, записанным ранее. В этом случае, так как мы ищем, как Bid.count изменится на 1 (положительное здесь неявно - увеличено на 1), если это то, что происходит, средство сравнения молчит и пример пропускается.
Если значения одинаковы или отличаются на какое-либо значение, отличное от 1, пример завершится ошибкой. Вы можете увидеть эту работу, если вы измените ожидание на (2) вместо (1).
НТН,
David