为给定的类定义method_missing时,如何解决“ NoMethodError”问题?

时间:2019-05-03 14:13:50

标签: ruby

我有一个名为RubyCsvRow的类,该类在哈希中保存一行CSV文件。我正在使用method_missing允许将任何列用作返回该列的行值的函数。但是,我在尝试运行它时遇到method_missing错误。

我不确定到底是怎么回事,所以我用一个上课的电话代替了对一个人的电话。

m = RubyCsv.new
m.each{|row| puts row.class}

我编辑了RubyCsvRow中缺少的方法,以便可以看到打印时会发生什么,并看到缺少​​的方法的名称:

def self.method_missing(name, *args, &block)
      puts "Called Method Missing"
      puts name.to_s
end

退货让我更加困惑。

Called Method Missing
to_ary
RubyCsvRow
Called Method Missing
to_ary
RubyCsvRow

它调用方法丢失。我不知道为什么它将名称打印为to_ary,当我搜索时发现this,但是我不确定何时对其进行隐式转换,或者为什么。

我到处搜索并查看了这些链接。我认为它们不合适的标签。

I have my private variable defined as a :attr_accesssor

Mine is a method of a class and I am using it like one

I am calling my method after defining it

I am not sure about this one. I am already converting my symbol to_s, but I had trouble determining if this fit

Why I decided to format my each method in RubyCsv the way I did

class RubyCsvRow
    attr_accessor :values

    def initialize(start)
      @values = start
    end 

    def self.method_missing(name, *args, &block)
      if @values.key?(name.to_s)
        @values[name.to_s]
      else
        puts "No Column with name: ", name.to_s, " found!"
      end
    end

    def to_s
      self.inspect
    end
end

r = RubyCsvRow.new({"one" => "dog", "two" => "cat" })
puts r.one 

每个RubyCsv中都使用RubyCsvRow,但是仅此代码我得到相同的错误。我可以发布RubyCsv代码,但这是重现该错误的最低代码。

我得到一个NoMethodError而不是打印狗。

1 个答案:

答案 0 :(得分:0)

尝试使用def method_missing代替自己。您在实例上调用方法,而不是对其进行自我分类。

如果使用self定义方法,则将方法定义为类而不是实例。在您的代码中,创建 RubyCsvRow 类的新实例,并且需要将method_missing定义为instace方法。

在此处修改代码:

class RubyCsvRow
  attr_accessor :values

  def initialize(start)
    @values = start
  end

  # Define method missing on instance
  def method_missing(name, *args, &block)
    return @values[name.to_s] if @values[name.to_s]
    # return my error message
    "No Column with name: #{name} found!"
  end

  def to_s
    inspect
  end
end

r = RubyCsvRow.new({ "one" => "dog", "two" => "cat" })
puts r.one
# => dog
puts r.test
# => "No Column with name: test found!"

顺便说一句:如果您需要原始错误消息,请在super方法中使用method_missing

def method_missing(name, *args, &block)
  return @values[name.to_s] if @values[name.to_s]
  # call original method
  super
end
相关问题