简体   繁体   中英

How do I access class methods in a define_singleton_method block in Ruby

I am trying to access class methods within a define_singleton_method block, but it doesn't seem to be working.

Here is an example.

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

But when I use it I get an error.

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>'

I tried changing val = tosymbol(val) to val = Test::tosymbol(val) but that didn't work either, I get undefined method 'tosymbol' for Test:Class

I could re-write what tosymbol is doing, but it wouldn't be very DRY. Where am I going wrong? Thanks.

Where am I going wrong?

You're ( re )defining a << method for instance of Array class, not Test class.

While doing so you are trying to access tosymbol method, that is not defined in Array class, but in Test class.

What you want, probably (read judging by your code sample ), is to define << method for instances of Test class:

def initialize
  @tags = []
end

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

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

EDIT

To make your example to work you just need to assign the instance to a variable and call the tosymbol method with correct receiver:

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

Now:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM