Ruby DSL变量初始化



我正在尝试复制Sinatra的功能。特别是类似DSL的部分,您可以在类的定义中定义路由。当我尝试运行我的个人DSL版本时,我在第11行收到错误undefined method '<<' for nil:NilClass

class Persons
  class << self
    def reset!
      @persons = []
    end
    def add_person title, name
      @persons << {
        title: title,
        name: name
      }
    end
  end
  reset!
end
class MyPersons < Persons
  add_person 'Dr.', 'Bob'
  add_person 'Mr.', 'Jones'
end

您从未将@persons初始化为nil以外的任何值。一个简单的解决方案是

class MyPersons < Persons
  reset!
  add_person 'Dr.', 'Bob'
  add_person 'Mr.', 'Jones'
end

reset!的调用不起作用的原因是MyPersonsPersons不共享同一个@persons变量。

您可以使用@@persons来共享变量。你的例子看起来是这样的:

class Persons
  @@persons = []
  class << self
    def reset!
      @@persons = []
    end
    def add_person title, name
      @@persons << { title: title, name: name }
    end
  end
end
class MyPersons < Persons
  add_person 'Dr.', 'Bob'
  add_person 'Mr.', 'Jones'
end

经过一个晚上的良好睡眠和更多的谷歌搜索,我找到了答案。Ruby中似乎有一个#inherited方法;当类被继承时调用(duh)。

实际上,这就是Sinatra在Sinatra::Base中实现实例变量的方式。

class Persons
  class << self
    def reset!
      @persons = []
    end
    def add_person title, name
      @persons << {
        title: title,
        name: name
      }
    end
    def inherited child
      child.reset!
    end
  end
end
class MyPersons < Persons
  add_person 'Dr.', 'Bob'
  add_person 'Mr.', 'Jones'
end

最新更新