Can Ruby DSL be evaluated in a non-global context?

I use Blockenspiel to create DSL with Ruby. It works great and solves a lot of my problems, but I ran into the following problem, which is not strictly related to the Blockenspiel.

Suppose I have a DSL that looks like this:

dish do
  name = 'Pizza'
  ingredients = ...
  nutrition_facts = ...
end

dish do
  name = 'Doner'
  ingredients = ...
  nutrition_facts = ...
end

Now I have a menu compiler that takes dishes and compiles them into a menu. Now the compiler should compile several menu files, so it set and cleared the global context. This preferably occurs in parallel.

I found out that Sinatra uses class variables, but this has the consequence that it can do sequential processing and that you have to clear class variables when you want to compile a new menu. An alternative would be to use global variables.

I would prefer to evaluate DSL methods within an object so that there is no global context, and I could compile the menu in parallel, but the last time I tried it, I ran into some problems when declaring (helper-) methods in a menu file.

What methods are possible? What is the recommended way to do this?

+3
source share
2 answers

What are the few libraries that I have seen is to use instance_evalfor this kind of thing.

, , :

class Menu
  def initialize file
    instance_eval File.read(file),file,1
  end

  def dish &block
    Dish.new &block
  end
  #....
end

class Dish
  def name(n=nil)
    @name = n if n
    @name
  end
  def ingredients(igrd=nil)
    @ingredients= igrd if igrd
    @ingredients
  end
end
#....

.new 'menu/pizza_joint'

/pizza _joint

dish do
  name 'Cheese Pizza'
  ingredients ['Cheese','Dough','Sauce']
end

DSL, , #name #ingredients, . dslify

+2

, .

a: setter-:

Dish = Struct.new(:name, :ingredients, :nutrition_facts)
def dish
  d = Dish.new
  yield d
  d
end

dish do |d|
  d.name = 'Pizza'
  d.ingredients = ...
  d.nutrition_facts = ...
end

b: instance_eval

class Dish
  attr_accessor :name, :ingredients, :nutrition_facts
end
def dish(&blk)
  d = Dish.new
  d.instance_eval(&blk)
  d
end

dish do
  @name = 'Doner'
  @ingredients = ...
  @nutrition_facts = ...
end

Dish, , . name, , ( ). , instance_eval Dish .

+2

Source: https://habr.com/ru/post/1733895/


All Articles