如何在Ruby中生成文本代码

use*_*702 3 ruby dsl static-methods metaprogramming block

有没有办法可以像这样:

SomeModule.some_method do
  choos_one_from 1..10
  then_multiply_it_by 2
  then_multiply_it_by 5
  then_divide_it_by :picked_number
  then_subtract 7
  did_you_get 3
end
Run Code Online (Sandbox Code Playgroud)

进入这个:

(1..10).all? do |number|
  ((number * 2 * 5) / number) - 7 == 3
end
Run Code Online (Sandbox Code Playgroud)

我试图为每一种可能的方法定义方法(choose_one_from,then_multiply_it_by ......),它们接受一个参数并用它做一些事情,但是当产生块时它产生了值,但我真的不知道如何组合它们所以我可以得到第二段代码.

编辑:我觉得我必须做像DSL一样的东西

Gre*_*rdt 5

你会想要这样的东西:

module Mathisizer

  def when_i
    Mathisizer::Builder.new
  end

  class Builder
    attr_accessor :range, :choosen_number

    def new
      @operations = []
    end

    def choose_one_from(range)
      self.range = range

      # Randomly determine the number from the range
      # self.choosen_number = ...

      self
    end

    def then_multiply_it_by(n)
      @operations << MultiplicationOperation.new(n)
      self
    end

    def then_add(n)
      @operations << AdditionOperation.new(n)
      self
    end

    def did_you_get?(n)
      x = self.result

      x == n
    end

    def result
      x = choosen_number;

      @operations.each do |operation|
        x = operation.invoke(x)
      end

      x
    end
  end

  class BaseOperation
    def new(n)
      @number = n
    end

    def invoke(n)
      raise 'Base classes must implement invoke(n) -> number'
    end
  end

  class MultiplicationOperation < BaseOperation
    def invoke(x)
      return @number * x
    end
  end

  class AdditionOperation < BaseOperation
    def invoke(x)
      return @number + x
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

你可以在哪里使用它:

Mathisizer.when_i
  .choose_one_from(1..10)
  .then_multiply_it_by(5)
  .did_you_get?(3)
Run Code Online (Sandbox Code Playgroud)

基本上,您将创建一个"构建器"对象,该对象提供用于创建数学运算对象的流畅API.