如何在Ruby中的define_singleton_method块中访问类方法

时间:2016-10-31 14:30:50

标签: ruby

我正在尝试访问define_singleton_method块中的类方法,但它似乎不起作用。

这是一个例子。

class Test
  attr_accessor :tags

  def initialize
    @tags = []
    @tags.define_singleton_method(:<<) do |val|
      val = tosymbol(val)
      push(val)
    end
  end

  def tosymbol(value)
    value = value.to_s
    value = value.gsub!(/\s+/,'_') || value
    value = value.downcase! || value

    return value.to_sym
  end
end

但是当我使用它时,我收到了一个错误。

test = Test.new
test.tags<<"Hello World"
NoMethodError: undefined method `tosymbol' for []:Array
  from /home/joebloggs/GitHub/repo/file.rb:183:in `block in initialize'
  from (irb):9
  from /home/joebloggs/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>'

我尝试将val = tosymbol(val)更改为val = Test::tosymbol(val),但这也无效,我得undefined method 'tosymbol' for Test:Class

我可以重写tosymbol正在做的事情,但它不会很干。我哪里错了?感谢。

1 个答案:

答案 0 :(得分:2)

  

我哪里错了?

您(重新)为<<类的实例定义Array方法,而不是Test类。

在执行此操作时,您尝试访问的tosymbol方法未在Array类中定义,但在Test类中定义。

你想要的是什么,可能是(读取通过代码示例判断),是为<<类的实例定义Test方法:

def initialize
  @tags = []
end

def <<(val)
  tags << tosymbol(val)
end

test = Test.new
test << "Hello World"
#=> [:hello_world]

修改

要使您的示例正常工作,您只需将实例分配给变量并使用正确的接收器调用tosymbol方法:

def initialize
  @tags = []
  test = self # <============
  @tags.define_singleton_method(:<<) do |val|
    val = test.tosymbol(val)
    push(val)
  end
end

现在:

test.tags << 'Hello World'
#=> [:hello_world]