Ruby metaprogramming

I am trying to write a DSL that allows me to do

Policy.name do
 author "Foo"
 reviewed_by "Bar"
end

The following code can almost process it:

class Policy
  include Singleton
  def self.method_missing(name,&block)
      puts name
      puts "#{yield}"
  end
  def self.author(name)
   puts name
  end
  def self.reviewed_by(name)
   puts name
  end
end

By defining my method as class methods (self.method_name), I can access it using the following syntax:

Policy.name do
 Policy.author "Foo"
 Policy.reviewed_by "Bar"
end

If I remove the “I” from the method names and try to use my desired syntax, then I get the error “Method not found” in the main one, so it could not find my function before the module core. Ok, I understand the error. But how can I fix this? How can I fix my class so that it works with my desired syntax?

+3
source share
2 answers

, self ( author self.author), instance_eval.

class Policy
  def self.name(&block)
    PolicyNameScope.new(block)
  end

  class PolicyNameScope
    def initialize(block)
      instance_eval(&block)     
    end

    def author(author)
      @author = author
    end

    def reviewed_by(reviewed_by)
      @reviewed_by = reviewed_by
    end
  end
end

policy = Policy.name do
  author "Dawg"
  reviewed_by "Dude"
end

p policy
# => #<Policy::PolicyNameScope:0x7fb81ef9f910 @reviewed_by="Dude", @author="Dawg">

PolicyNameScope , name. , Policy , DSL .

, - .

+4

, , , , - , . , . , , .

class Policy

  def self.method_missing(name,&block)
    self.class_eval(&block)
  end
  def self.author(name)
    p name
  end
  def self.reviewed_by(name)
    p name
  end

end

Policy.name do
  author "Foo"
  reviewed_by "Bar"
end

, .

+1

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


All Articles