开发者

How do you modify the scope passed to a block?

I've been working with Ruby for a little under a year, and I still don't fully understand "what makes blocks tick". In particular I'm curious how much control one has over the scope of a block. For example, say I have this code:

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

A bit of a contrived example there, obviously.

Now, one thing I've noticed while migrating from Rails 2 to Rails 3 is that a lot of their con开发者_如何学Pythonfiguration methods that take blocks no longer take a non-block argument.

For example, in routes.rb, it used to be ActionController::Routing::Routes.draw do |map| ... end, and now it's just ActionController::Routing::Routes.draw do ... end. But the methods that are called inside the block still have the appropriate context, without the need to repeat the name of the block's argument over and over.

In my example above, then, I want to be able to do:

blob.configure do
  viscosity 0.5
end

so that I can tell people how easy it is to write a DSL in Ruby. :)


This uses instance_eval to do the magic. See http://apidock.com/ruby/Object/instance_eval/ for some documentation. instance_eval evaluates a block (or a string) in the context of it's receiver.

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

You'd still have to use the accessor method viscosity= in your example block or you'd have to define

def viscosity(value)
  @viscosity = value
end

in your class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜