Ruby DSL变量初始化

时间:2012-02-29 02:08:57

标签: ruby sinatra 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

2 个答案:

答案 0 :(得分:1)

您永远不会将@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

答案 1 :(得分:0)

经过一夜好眠和一些谷歌搜索后,我想出了答案。 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