Как изменить область, переданную в блок? - PullRequest
2 голосов
/ 07 марта 2011

Я работаю с Ruby чуть меньше года, и я до сих пор не до конца понимаю, «что заставляет блоки тикать». В частности, мне любопытно, насколько сильно человек контролирует объем блока. Например, скажем, у меня есть этот код:

class Blob
  attr_accessor :viscosity
  def configure(&:block)
    block.call self
  end
end

blob = Blob.new
blob.configure do |b|
  b.viscosity 0.5
end

Очевидно, это немного надуманный пример.

Теперь, одна вещь, которую я заметил при переходе с Rails 2 на Rails 3, это то, что многие из их методов конфигурации, которые принимают блоки, больше не принимают неблокированный аргумент.

Например, в rout.rb это было ActionController::Routing::Routes.draw do |map| ... end, а теперь просто ActionController::Routing::Routes.draw do ... end. Но методы, вызываемые внутри блока, по-прежнему имеют соответствующий контекст, без необходимости повторять имя аргумента блока снова и снова.

В моем примере выше я хочу иметь возможность:

blob.configure do
  viscosity 0.5
end

чтобы я мог рассказать людям, как легко написать DSL на Ruby. :)

1 Ответ

4 голосов
/ 07 марта 2011

Используется instance_eval для создания магии. См. http://apidock.com/ruby/Object/instance_eval/ для некоторой документации. instance_eval оценивает блок (или строку) в контексте его получателя.

def configure(&block)
  self.instance_eval &block
end

Вам все равно придется использовать метод доступа viscosity= в вашем примере блока, или вам придется определить

def viscosity(value)
  @viscosity = value
end

в вашем классе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...