DSL блок без аргументов в ruby - PullRequest
8 голосов
/ 10 февраля 2012

Я пишу простой dsl в ruby. Несколько недель назад я наткнулся на какое-то сообщение в блоге, которое показывает, как преобразовать код, например:

some_method argument do |book|
  book.some_method_on_book
  book.some_other_method_on_book :with => argument
end

в код уборщика:

some_method argument do
   some_method_on_book
   some_other_method_on_book :with => argument
end

Я не могу вспомнить, как это сделать, и я не уверен в недостатках, но чистый синтаксис заманчив У кого-нибудь есть подсказка об этой трансформации?

Ответы [ 3 ]

9 голосов
/ 10 февраля 2012
def some_method argument, &blk
  #...
  book.instance_eval &blk
  #...
end

ОБНОВЛЕНИЕ: Тем не менее, книга опущена, но не позволяет использовать аргумент. Чтобы использовать его прозрачно, вы должны каким-то образом его транспортировать. Предлагаю сделать это на самой книге:

class Book
  attr_accessor :argument
end

def some_method argument, &blk
  #...
  book.argument = argument
  book.instance_eval &blk
  #...
end

some_method 'argument' do
   some_method_on_book
   some_other_method_on_book argument
end
7 голосов
/ 10 февраля 2012

Взгляните на эту статью http://www.dan -manges.com / blog / ruby-dsls-instance-eval-with-Delegation - есть обзор метода (специально изложенный в контексте о его недостатках и возможных решениях), плюс есть несколько полезных ссылок для дальнейшего чтения.

По сути, речь идет об использовании instance_eval для выполнения блока в нужном контексте.

Говоря о недостатках этой техники:

Так в чем проблема? Ну, проблема в том, что блоки вообще замыкания. И вы ожидаете, что они на самом деле будут полным закрытием. И это не очевидно с той точки, где вы пишете блок, который этот блок не может быть полным закрытием. Вот что происходит, когда ты используйте instance_eval: вы сбрасываете себя этого блока во что-то иначе - это означает, что блок все еще является закрытием для всех локальных переменные вне блока, но НЕ для вызовов методов. Я даже не знать, изменен ли постоянный поиск или нет.

Использование instance_eval изменяет правила для языка таким образом, чтобы не является очевидным при чтении блока. Вам нужно подумать о дополнительном шаге чтобы выяснить, почему именно вызов метода, который вы можете увидеть лексически вокруг блока фактически нельзя вызвать изнутри блока.

0 голосов
/ 18 февраля 2013

Посмотрите на камень docile .Он заботится обо всех острых краях, что делает это очень легким для вас.

...