DSL block without arguments in ruby

I am writing a simple dsl in ruby. A few weeks ago, I came across some blog posts that showed how to convert code, for example:

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

in clean code:

 some_method argument do some_method_on_book some_other_method_on_book :with => argument end 

I don’t remember how to do this, and I'm not sure about the flaws, but the cleaner syntax is tempting. Does anyone know about this conversion?

+8
ruby block dsl
source share
3 answers
 def some_method argument, &blk #... book.instance_eval &blk #... end 

UPDATE: However, this omits the book, but does not allow the use of an argument. To use it transparently, you must somehow transport it. I suggest doing this from the book itself:

 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 
+9
source share

Take a look at this article http://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation - there is an overview of the method (in particular, in the context of its shortcomings and possible solutions for them), plus there is some useful links for further reading.

Basically, about using instance_eval to execute a block in the desired context.

Speaking about the lack of this technique:

So what's the problem? Well, the problem is that blocks are usually closing. And you expect that in fact they will be completely closed. And this is not obvious from the moment you write a block, which this block may not be a complete closure. What happens when you use instance_eval: you reset this block to something else - this means that the block is still closing all local variables outside the block, but NOT for method calls. I don’t even know if the constant search is changing or not.

Using instance_eval changes the rules for the language in a way that is not obvious when reading a block. You need to think about an additional step to find out exactly why the method call can be seen lexically around the block, you can actually not call it from inside the block.

+7
source share

Take a look at the docile gem. He takes care of all sharp edges, making it very easy for you.

0
source share

All Articles