Stanislav Pankevich Stanislav Pankevich - 25 days ago 13
Ruby Question

#with(object) &block trick

There is a common idiom of using substitutions like:

def with clazz, &block
yield clazz
clazz
end

with Hash.new |hash|
hash.merge!{:a => 1}
end


Is there a way to go further and define #with to have a possibility of doing:

with Hash.new |hash|
merge!{:a => 1}
end


or even:

with Hash.new do
merge!{:a => 1}
end


?




UPDATE

Later accidentally I found exactly what I was looking for (solution similar to the accepted one):
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/19153

UPDATE 2

It was added to sugar-high/dsl in https://github.com/kristianmandrup/sugar-high

UPDATE 3

docille project on Github exploits this idea very nicely.

Answer

If you are referring to the way in which Rails does routing then I think you need to do something like this

def with(instance, &block)
  instance.instance_eval(&block)
  instance
end

with(Hash.new) do
  merge!({:a => 1})
  merge!({:b => 1})
end

This is how I can see it being done in the Rails source anyway start by looking at the draw method in action_pack/lib/action_dispatch/routing/route_set

Comments