迭代Ruby中的实例方法?

时间:2014-10-07 04:23:34

标签: ruby

我正在从网页中检索数据。有多次出现类似结构的important块,我将通过迭代使用更多方法。有没有办法让像下面的东西一样?

require 'open-uri'
require 'nokogiri'

class Scraper      
  def initialize(url)
    @url = url
  end

  def name
    @name ||= doc.at_css(".currentverylong").text
  end

  def important
    @important = doc.css(".main_entry")
  end

  important.each do |item|
    define_method(:artist) do
      @artist ||= item.at_css(".list_artist").text
    end

    define_method(:title) do
      @title ||= item.at_css(".list_album").text
    end
  end

  private
  attr_reader :url

  def doc
    @doc ||= Nokogiri::HTML(open(url))
  end
end

scraper = Scraper.new( #url
puts scraper.name
puts "#{scraper.artist} \"#{scraper.title}\" "

现在的方式,错误是important未定义。取消important并将其替换为doc.css(."main_entry").each do |item|也存在同样的问题。这也引出了另一个问题。为什么下面这样的方法接受doc就好了?

def name
  @name ||= doc.at_css(".currentverylong").text
end

更新 正如有人在这里提到的那样以及对SO的另一个相关问题的回应,important被反复覆盖的事实就是这里的问题。有人可以解释一下这个过程中究竟发生了什么,以及导致undefined local variable or method important的原因是什么?

1 个答案:

答案 0 :(得分:1)

如果您不希望重要的是返回nil,您可以使用important方法的默认空数组值。

def important
  @important ||= doc.css(".main-entry") || []
end

如果可能doc将为零(不确定您是如何加载该网址),则可以使用try来获取该空数组语句。

def important
  @important ||= doc.try(:css, ".main-entry") || []
end

这将保证important产生一个数组对象。