How to create this little DSL in Ruby?

My functions:

def hello(str) puts "hello #{str}" end def hello_scope(scope, &block) # ??? end 

I would like to temporarily increase the function inside the block of my method.

In hello_scope I just want to add the scope string to str before passing it to the original hello method. Here is an example:

 hello 'world' #=> hello world hello_scope "welcome!" do hello 'bob' #=> welcome!hello bob hello 'alice' #=> welcome!hello alice end 

I'm kind of a noob when it comes to this kind of thing in Ruby. Can someone help me solve this in an elegant way?


Edit:

If this simplifies the work, it is normal if we pass the method as an argument to a block, for example:

 hello_scope "welcome!" do |h| h "bob" #=> welcome!hello bob h "alice" #=> welcome!hello alice end 
+4
source share
2 answers

One way is to create an “evaluation context object” on which the block will have an instance-eval'd. This object should provide all block specific methods. In the example below, I did not use the same name as I do not remember how to explicitly refer to the global hello method (to avoid infinite recursion). In the corresponding library, “hello” will be defined as a class method somewhere, so this is not a problem.

for instance

 def hello(str) puts "hello #{str}" end class HelloScope def h(str) print scope hello(str) end end def hello_scope(scope, &block) HelloScope.new(scope).instance_eval(&block) end 
+4
source

Just change your hello method to take into account the current scope:

 class Greeter def initialize @scope = nil end def hello(str) puts "#{@scope}hello #{str}" end def with_scope(scope) @scope = scope yield @scope = nil end end Greeter.new.instance_eval do hello 'world' #=> hello world with_scope "welcome!" do hello 'bob' #=> welcome!hello bob hello 'alice' #=> welcome!hello alice end end 
0
source

All Articles