Array only saves the last value in ruby on rails - ruby-on-rails

I have a loop which outputs information I grabbed from a website. To make the information display in an readable fashion, I insert it into an array that will be displayed on my view page. However, The array does not store all the values retrieved and instead only saves the last value appended to it. In the end I can only get the last value inserted into the array to be displayed.
My controller file...
def home
scrape()
end
private
def scrape
require 'rubygems'
require 'nokogiri'
require 'open-uri'
time = Time.new
month = I18n.t("date.abbr_month_names")[time.month]
day = time.day
#strings = []
#United States
cities = [
"sfbay", "losangeles", "athensga", "phoenix", "santabarbara", "denver",
"panamacity", "miami", "austin", "bakersfield", "keys", "newyork"
]
cities.map do |city|
#Search Terms
search_terms = ["mechanic", "car", "tech"]
search_terms.map do |term|
escaped_term = CGI.escape(term)
url = "http://#{city}.craigslist.org/search/jjj?query=#{escaped_term}&catAbb=jjj&
srchType=A"
doc = Nokogiri::HTML(open(url))
doc.css(".row").map do |row|
date = row.css(".itemdate").text
a_tag = row.css("a")[0]
text = a_tag.text
link = a_tag[:href]
#strings == []
if date = "#{month} #{day}"
#strings << "#{date} #{text} #{link}"
end
end
end
end
end
In the view home.html.erb file...
<%= raw(#strings.join('<br />')) %>
So when I go to the home page, I'm only display the last value inserted into the array. What is wrong and how do I fix it?

For one thing you create a new array for every row for every city. (But don't, actually; the assignment is a compare, ==, at the moment.)
For another you set date equal to "#{month} #{day}" instead of doing a comparison.

Related

Extract Substring from String / Ruby

I get the datas from a variable called "apps".
And I have this datastructure:
{"id"=>001,
"name"=>"test01",
"users"=>
[{"id"=>01,
"name"=>"test02"},
{"id"=>02,
"name"=>"test03"}]}
How can I extract the namevalues from the users substring?
I have tried
apps.each do |test|
data = Hash.new
data['id'] = test['id']
data['name'] = test['name']
data['username'] = test['users.name']
userdata = data
userdata.each do |row|
File.write('test.yaml', row.to_yaml)
end
end
But that doesn't work.
desired output would be:
{"id"=>"01", "name"=>"test02","id"=>"02", "name"=>"test03"}
you just need to require 'yaml' in order to use it on Hash/Array classes, you don't need to iterate over array or hash, to_yaml already handles this for you.
require 'yaml'
data = {"id"=>001,
"name"=>"test01",
"users"=>
[{"id"=>01,
"name"=>"test02"},
{"id"=>02,
"name"=>"test03"}]}
File.write('test.yml', data["users"].to_yaml)

Updating Ruby Hash Values with Array Values

I've created the following hash keys with values parsed from PDF into array:
columns = ["Sen", "P-Hire#", "Emp#", "DOH", "Last", "First"]
h = Hash[columns.map.with_index.to_h]
=> {"Sen"=>0, "P-Hire#"=>1, "Emp#"=>2, "DOH"=>3, "Last"=>4, "First"=>5}
Now I want to update the value of each key with 6 equivalent values from another parsed data array:
rows = list.text.scan(/^.+/)
row = rows[0].tr(',', '')
#data = row.split
=> ["2", "6", "239", "05/05/67", "Harp", "Erin"]
I can iterate over #data in the view and it will list each of the 6 values. When I try to do the same in the controller it sets the same value to each key:
data.each do |e|
h.update(h){|key,v1| (e) }
end
=>
{"Sen"=>"Harper", "P-Hire#"=>"Harper", "Emp#"=>"Harper", "DOH"=>"Harper", "Last"=>"Harper", "First"=>"Harper"
So it's setting the value of each key to the last value of the looped array...
I would just do:
h.keys.zip(#data).to_h
If the only purpose of h is as an interim step getting to the result, you can dispense with it and do:
columns.zip(#data).to_h
There are several ways to solve this problem but a more direct and straight forward way would be:
columns = ["Sen", "P-Hire#", "Emp#", "DOH", "Last", "First"]
...
#data = row.split
h = Hash.new
columns.each_with_index do |column, index|
h[column] = #data[index]
end
Another way:
h.each do |key, index|
h[key] = #data[index]
end
Like I said, there are several ways of solving the issue and the best is always going to depend on what you're trying to achieve.

doing if else in a loop with arrays rails

currently am getting bunch of records from database and wrapping those records in an array but i want to set an if condition within it
#reports = SnapshotReport.includes(camera: [:user]).where(report_date: date)
records = []
#reports.each do |report|
next if report.camera.cloud_recording.blank?
records[records.length] = [
report.camera["name"],
report.camera["exid"],
report.camera.user["firstname"],
report.camera.cloud_recording["storage_duration"],
report.camera["is_online"],
report["snapshot_count"],
report.camera["id"],
report.camera.user["id"],
report.camera.user["lastname"],
]
end
right now what am doing is , using next if to skip such values where
next if report.camera.cloud_recording.blank?
is null, but i want to do this thing array making portion but like that
if report.camera.cloud_recording is null then it saves an "" empty string but if report.camera.cloud_recording is present then get the value of report.camera.cloud_recording["storage_duration"]
Use
#reports = SnapshotReport.includes(camera: [:user]).where(report_date: date)
records = []
#reports.each do |report|
records[records.length] = [
report.camera["name"],
report.camera["exid"],
report.camera.user["firstname"],
report.camera.cloud_recording || {"storage_duration" => ""} ["storage_duration"],
report.camera["is_online"],
report["snapshot_count"],
report.camera["id"],
report.camera.user["id"],
report.camera.user["lastname"],
]
end

Display Json in view

Im having problems trying to display in my view information comming from a json file. I have already parse it.
Here is my error:
When assigning attributes, you must pass a hash as an argument.
Extracted source (around line #23):
21 # #new_member.constructors = [driver['Constructors'][0]['name']]
22 # #new_member.points = [driver['points']]
23 #new_member.from_json(json)
#members << #new_member
end
# #new_member.constructors = [driver['Constructors'][0]['name']]
# #new_member.points = [driver['points']]
#new_member.from_json(json)
#members << #new_member
end
This is my controller:
require 'open-uri'
require 'json'
url = "http://ergast.com/api/f1/2014/driverStandings.json"
data = JSON.parse(open(url).read)
standings = data['MRData']['StandingsTable']['StandingsLists'][0]['DriverStandings']
#members = Array.new
standings.each do |driver|
json = standings.to_json
#new_member = Member.new
# #new_member.position = [driver['position']]
# #new_member.givenName = [driver['Driver']['givenName']]
# #new_member.familyName = [driver['Driver']['familyName']]
# #new_member.constructors = [driver['Constructors'][0]['name']]
# #new_member.points = [driver['points']]
#new_member.from_json(json)
#members << #new_member
If I uncommented the lines in the controller and delete these lines
#new_member.from_json(json)
json = standings.to_json
I get the following in the view
Name: ["Lewis"]
Name: ["Nico"]
That view is really close but is not what i need, I need the data without [" "],
so the view that I need is something like:
1 Lewis Hamilton Mercedes 384
Thanks in advance.
Alternative 1
Change the line:
#new_member.givenName = [driver['Driver']['givenName']]
into:
#new_member.givenName = driver['Driver']['givenName']
removing the external [ and ], so that the field #new_member.givenName that you're populating becomes a string rather than an array containing one string.
Alternative 2
Is it possible that, when looping through the standings hash, the driver temp variable is a Hash?
In this case it may be sufficient to do:
#members = Array.new
standings.each do |driver|
#members << Member.new(driver)
end
Bonus: you probably don't need to assign an instance variable #new_member, that gets overwritten at each iteration of the loop

Using Column headers to parse excel sheets using roo - Ruby

Can we use column headers to specify the column number from which we are parsing the excel sheet using roo gem? My current code is like this now:
oo = Openoffice.new("simple_spreadsheet.ods")
oo.default_sheet = oo.sheets.first
(2..oo.last_row).each do |line|
date = oo.cell(line,'A')
start_time = oo.cell(line,'B')
end_time = oo.cell(line,'C')
pause = oo.cell(line,'D')
...
end
I would like to parse from column headers instead of specifying columns as 'A' 'B' 'C' ... Can I acheive this using Roo?
You can grab the entire header row as an array and hash the entire row key'd on the header row.
oo = Openoffice.new("simple_spreadsheet.ods")
oo.default_sheet = oo.sheets.first
header = oo.row(1)
2.upto(oo.last_row) do |line|
row_data = Hash[header.zip oo.row(line)]
...
end
You could also use row_data[line] to nest the hashes for later use.
A cleaner/clearer version of the above is
oo = Openoffice.new("simple_spreadsheet.ods")
oo.default_sheet = file.sheets.first
header = oo.first_row
2.upto(oo.last_row) do |line|
row_data = Hash[*header.zip(row).flatten]
...
end
the original took me a bit to understand because especially as i thought hash was a local variable named hash instead of the class Hash
This will use the header row as the keys. The helpful parts are transpose and strip.
def self.excel_to_hash(folder_name, file_name, tab_name)
# Takes an excel file name and a tab name, and returns an array of stripped, transposed rows
# Sample call: my_data = excel_to_hash File.join(Rails.root,'db/data/data_to_import.xlsx'), 'models'
rows = []
file = File.open(File.join(folder_name, file_name), mode = 'r')
excel = Excelx.new(file.path, nil, :ignore)
excel.default_sheet = excel.sheets.index(tab_name) + 1
header = excel.row(1)
(2..excel.last_row).each do |i|
next unless excel.row(i)[0]
row = Hash[[header, excel.row(i)].transpose]
row.each_key{|x| row[x] = row[x].to_s.strip if row[x]}
rows << row
end
return rows
end
valid through Roo gem 1.10.2
This works for me
require 'roo'
# open excel file
excel_file = Roo::Spreadsheet.open(file_path)
# iterate on each sheet
excel_file.each_with_pagename do |name, sheet|
# iterate on each sheet
sheet.parse(headers: true, pad_cells: true) do |row|
# data should be access by column header if we have column header Name we can access like this
row['Name']
end
end
end

Resources