Bagaimana saya bisa menyatukan atribut nama dan deskripsi dan membuat objek pulau untuk setiap pulau? Saya sudah mencoba semua yang saya bisa untuk menyatukan kedua atribut untuk membuat objek tetapi hanya bisa mendapatkannya secara terpisah. Saya butuh bantuan karena saya harus menyerahkan ini dalam dua hari. Inilah yang saya miliki:

class MostBeautifulIslands::Islands
  attr_accessor :name, :description

  @@all = []

  def initialize(name)
     @name = name
     @description = description
     @@all << self
  end

  def self.scrape_world_best_islands
    doc = Nokogiri::HTML(open("http://www.planetware.com/world/most-beautiful-islands-in-the-world-sey-1-2.htm"))
    islands_names = doc.search("div h2.sitename")
    names = islands_names.collect{|island_name| new(island_name.text.strip)} 
    island_description = doc.search("div.site_desc > p")
    descriptions = island_description.collect{|d| d.first.text.strip}

    new_island = self.new(names)
    new_island

    binding.pry
    #end
  end
end
1
J.Taiwo 11 Maret 2017, 17:18

2 jawaban

Jawaban Terbaik

Pertama-tama, di initialize Anda menggunakan description param yang tidak pernah didapat. Harus:

def initialize(name, description)
  @name = name
  @description = description
  @@all << self
end

Sekunder, Anda harus mengumpulkan nama, deskripsi, dan kemudian menggunakan nilai-nilai ini (zip) untuk menghasilkan instance baru:

islands_names = doc.search("div h2.sitename").map(&:text)
islands_descs = doc.search("div.site_desc > p").map(&:text)

islands_names.zip(islands_descs).map { |(name, desc)| new(name, desc) }
#⇒ Array of 15 newly created objects
1
Aleksei Matiushkin 11 Maret 2017, 17:19

Saya akan memisahkan ini menjadi dua kelas terpisah. Satu untuk menangani penguraian Nokogiri dan yang lainnya untuk menangani objek MostBeutifulIslands::Islands. Ini memberi Anda sedikit lebih banyak fleksibilitas dalam menangani data.

require 'open-uri'
require 'nokogiri' 

module MostBeutifulIslands
  class Islands
    attr_reader :name, :description

    def initialize(name, description)
      @name = name
      @description = description
    end

    def valid?
      !name.nil? && !description.nil? 
    end

    def save
      # if using rails could save to Islands object
      island =  Island.new(name: name, description: description)

      if island.save
        puts island.save
      else
        puts island.errors
      end
    end
  end
end

module MostBeutifulIslands
  class ParseIslands
    attr_reader :url, :islands

    def initialize(url)
      @url = url
    end

    def html
      Nokogiri::HTML(open(url))
    end

    def scrap_world_best_islands
      # maybe no need to us each_with_object could do everything you need inside the block
      html.css("div .article_block").css('.site').each_with_object([]).map do |node, array|
        name = node.css('.sitename').text.strip
        description = node.css('.site_desc').text.strip
        @islands = array.push MostBeutifulIslands::Islands.new(name, description)
      end 
    end

    # just an example 
    def save_islands
      @islands.each do |island|
        if island.valid?
          island.save 
        end
      end
    end

    islands = MostBeutifulIslands::ParseIslands.new("http://www.planetware.com/world/most-beautiful-islands-in-the-world-sey-1-2.htm")
    islands.scrap_world_best_islands
    islands.save_islands
  end
end
1
David Gross 11 Maret 2017, 17:51