2012-05-18 3 views
0

Это описание того, как создать вспомогательный метод в Rspec, взятый из книги Rspec (стр. 149). В этом примере предполагается, что существует метод, называемый «set_status», который запускается при создании объекта «Thing».Как использовать yield self в Rspec

Оба набора кода создают новый объект «Thing», устанавливают статус, а затем «fancy_stuff». Первый набор кода для меня совершенно ясен. Одно из выражений «it», которое оно вызвало, которое затем вызывает метод «create_thing» с параметрами. Создается новый объект «Вещь», и в качестве параметра вызывается метод «set_status» с атрибутом «options».

Второй набор кодов аналогичен. Вызывается одно из операторов «it», которое затем вызывает метод «given_thing_with» при передаче хэш-присвоения «: status» в качестве параметра. В методе «given_thing_with» срабатывает «выход», беря значение «Thing.new» в качестве параметра. Здесь я испытываю проблемы. Когда я пытаюсь запустить этот код, я получаю сообщение об ошибке «block given to yield». Я понимаю, что любые атрибуты, которые передаются с помощью yield, будут возвращены в «вещь» в скобке труб из оператора «it», называемого методом «given_thing_with». Я могу получить новый

Я не понимаю, почему код кода не вызывается в методе 'given_thing_with' после команды 'yield'. Другими словами, я не могу закодировать этот блок для запуска.

Заранее за вашу помощь.

Остальная часть этого вопроса цитируется непосредственно из книги RSpec:

describe Thing do 
    def create_thing(options) 
    thing = Thing.new 
    thing.set_status(options[:status]) 
    thing 
    end 

    it "should do something when ok" do 
    thing = create_thing(:status => 'ok') 
    thing.do_fancy_stuff(1, true, :move => 'left', :obstacles => nil) 
    ... 
    end 

    it "should do something else when not so good" do 
    thing = create_thing(:status => 'not so good') 
    thing.do_fancy_stuff(1, true, :move => 'left', :obstacles => nil) 
    ... 
    end 
end 

Один идиома вы можете обратиться к приберёмся даже больше, чтобы дать себя от инициализаторах в ваших объектов. Если предположить, что метод вещь Initialize() делает это и set_status() не так, вы можете написать предыдущий, как это:

describe Thing do 
    def given_thing_with(options) 
    yield Thing.new do |thing| 
     thing.set_status(options[:status]) 
    end 
    end 

    it "should do something when ok" do 
    given_thing_with(:status => 'ok') do |thing| 
     thing.do_fancy_stuff(1, true, :move => 'left', :obstacles => nil) 
     ... 
    end 
    end 

    it "should do something else when not so good" do 
    given_thing_with(:status => 'not so good') do |thing| 
     thing.do_fancy_stuff(1, true, :move => 'left', :obstacles => nil) 
     ... 
    end 
    end 
end 
+0

'' Предполагая, что метод initialize() Thing делает это ... "'. Вы изменили реализацию инициализации Thing # так, чтобы она уступила? – zetetic

+0

Спасибо, что ответили. Эта конкретная фраза, вероятно, та, которую я не понимаю. Я интерпретировал это как означающий «def initialize \ n yield \ n end», но это явно неправильно. Я прочитал этот пост [http://stackoverflow.com/questions/1425055/is-yield-self-the-same-as-instance-eval], чтобы узнать больше о передаче блоков. – Scott

ответ

0

Есть 2 проблемы с кодом из книги.

1. Настройка инициализатора для получения себя

Когда объект Thing создан, он нуждается в инициализаторе и нужно давать себя.

class Thing 
    def initialize 
    yield self 
    end 
end 

Однако это само по себе по-прежнему вызывает ошибку, по крайней мере, на моей системе, которая является Ruby 1.9.3. В частности, ошибка - это блок, заданный для yield (SyntaxError) '. Это не имеет особого смысла, поскольку мы хотим, чтобы это было сделано. Регрессивно, это ошибка, которую я получаю.

2.Закрепление «блок предоставленный выход» ошибка

Это не так очевидно, и что-то делать либо с Ruby, или «выход» заявление, но создание блока с помощью «сделать ... конец», как это было написанное в книге и показано ниже, вызывает ошибку.

yield Thing.new do |thing| 
    thing.set_status(options[:status]) 
end 

Исправление этой ошибки simlpy вопрос создания блока с помощью фигурных скобок, «{...}», как показано ниже.

yield Thing.new { |thing| 
    thing.set_status(options[:status]) 
} 

Это не очень хорошая форма для многострочного кода Ruby, но она работает.

Дополнительная информация. Как работает серия доходностей для задания параметров объекта «Thing»

Проблема уже исправлена, но это объясняет, как это работает.

  • метод «блок вызывающего абонента» «given_thing_with» вызовов с помощью параметра
  • , что метод дает обратно к «блоку вызывающего абонента» новой «Вещь» и блок (я буду называть его «выход блока «)
  • для выполнения« блока результатов »класс Thing требует инициализации и« yield self », в противном случае метод« set_status »никогда не будет запущен, потому что блок будет проигнорирован
  • новый« Вещь » уже в «блоке вызывающего абонента» и имеет статус статуса, и теперь выполняется соответствующий метод.
0

пример в книге немного сбивает с толку, потому что реализация Thing не показана. Для того, чтобы сделать эту работу вам нужно написать Thing как так:

class Thing 
    def initialize 
    yield self 
    end 
end 

given_thing_with Когда называется она дает новый Thing, который даст себя, когда он построен. Это означает, что, когда выполняется внутренний кодовый блок (тот, который содержит thing.set_status), он будет иметь ссылку на недавно построенный Thing.

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