jbk
jbk

Reputation: 2200

What am i doing wrong in trying to set these instance variables?

I seem to be getting something elementary wrong when trying to set and or access these variables in my Quote instance when i call Quote#scrape_quote. I can see that the values are scraped and saved to the scraped_values hash just fine, I just can't access the variables, when I call quote.lives for e.g. I get nil.

What am i getting wrong here?

quote.rb

class Quote < ApplicationRecord 
  require 'watir'
  attr_accessor :lives, :benefit, :payment

  def scrape_quote
    rows = @browser.trs
    quote_rows = rows[1..8]
    scraped_values = {}

    quote_rows.each do |row|
      scraped_values[row.tds[0].text] = row.tds[1].text
    end

        @lives      = scraped_values[0]
        @benefit    = scraped_values[1]
        @payment    = scraped_values[2]

    puts scraped_values
  end
end

Upvotes: 0

Views: 61

Answers (4)

Leo
Leo

Reputation: 1773

Instead of scraped_values[0] you need something like this: scraped_values[scraped_values.keys[0]], because scraped_values isn't array and 0, 1, 2 is like any other missing key, so hash returns nil.

Upvotes: 0

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

The idiomatic way to build the hash would be to use map instead of each and do not use upfront declarations of local variables.

scraped_values = quote_rows.map do |row|
  [row.tds[0].text, row.tds[1].text]
end.to_h

Upvotes: 0

Segfault
Segfault

Reputation: 8290

The general case

If you just want the values of the hash sequentially assigned to member variables, you can use parallel assignment from the hash#values return value like this:

2.4.1 :001 > h = {}
 => {} 
2.4.1 :002 > h[:one] = 1
 => 1 
2.4.1 :003 > h[:two] = 2
 => 2 
2.4.1 :004 > h[:three] = 3
 => 3 
2.4.1 :005 > @one, @two, @three = h.values
 => [1, 2, 3] 
2.4.1 :006 > @one
 => 1 
2.4.1 :007 > @two
 => 2 
2.4.1 :008 > @three
 => 3 
2.4.1 :009 >

Specific application

The specific code in your case would turn into:

class Quote < ApplicationRecord 
  require 'watir'
  attr_accessor :lives, :benefit, :payment

  def scrape_quote
    rows = @browser.trs
    quote_rows = rows[1..8]
    scraped_values = {}

    quote_rows.each do |row|
      scraped_values[row.tds[0].text] = row.tds[1].text
    end

    @lives, @benefit, @payment = scraped_values.values

    puts scraped_values
  end
end

Upvotes: 2

seph
seph

Reputation: 6076

scraped_values is a hash not an array. You are trying to access it as if it were an array.

Use whatever is in row.tds[0].text to reference the hash:

h = {a:1,b:2}
h[:a]
=> 1 

Upvotes: 3

Related Questions