A Domain Specific Language (DSL) is a computer language targeted to a particular kind of problem or application domain. There are various ways to implement a DSL in Ruby: classic blocks, instance_eval or mixins and extend. Most often instance_eval is used. How does it work? First one has to define the DSL itself, for example in a class like the this:
class MyDsl def initialize @local_var = 1 end def method_1 puts "#{@local_var}+1=#{@local_var += 1}" end def method_2 puts "says your DSL method" end end
then one can apply the dsl to an object:
MyClass.apply_dsl(MyDSL) do |obj| obj.method_1() obj.method_2() end
We only need the define an “apply_dsl” method. The first option is to use simple Ruby blocks to apply the DSL:
class MyClass def self.apply_dsl(a_class, &block) yield a_class.new if block_given? end end
The second option is to use instance_eval to apply the DSL:
class MyClass def self.apply_dsl(a_class, &block) dsl = a_class.new dsl.instance_eval &block if block_given? end end
Or one can use mixins and extend..
class MyClass def self.apply_dsl(a_module) obj = MyClass.new obj.extend(a_module) obj.init yield obj if block_given? end end
but then one would use modules instead of classes:
module MyDSL def init @i = 1 end def method_1 puts "#{@i}+1=#{@i += 1}" end def method_2 puts "says your DSL method" end end
Another option would be to use the Docile gem: https://github.com/ms-ati/docile