doing if else in a loop with arrays rails - ruby-on-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

Related

Adding values to a hash within/over multiple each loops

I have a concept called snapshot which basically stores a snapshot of how data looked at a certain period of time. What I'm building is a method that loops through the snapshots for each events, and builds a small hash outlining the ownership over time for a given shareholder.
def fetch_ownership_over_time(shareholder, captable)
#shareholder = Shareholder.find(shareholder.id)
#captable = Captable.find(captable.id)
#company = #captable.company.id
#ownership_over_time = []
#captable.events.collect(&:snapshot).each do |snapshot|
parsed_snapshot = JSON.parse(snapshot)
#ownership_over_time.push(parsed_snapshot["event"]["name"])
#ownership_over_time.push(parsed_snapshot["event"]["date"])
parsed_snapshot["shareholders"].each do |shareholder|
if shareholder["id"] == #shareholder.id
#ownership_over_time.push(shareholder["ownership_percentage"])
end
end
end
return #ownership_over_time
end
I then call this method in my view which successfully retrieves the correct values however they are not structured in any way:
["Event 1 ", "2018-11-19", "0.666666666666667", "Event 2 ", "2018-11-19", "0.333333333333333", "4th event ", "2018-11-19", "0.315789473684211"]
What I'd like to do now though is construct my hash so that each separate snapshot event contains a name, date and ownership_percentage.
Perhaps something like this:
ownership_over_time = [
{
event_name = "Event 1" #parsed_snapshot["event"]["name"]
event_date = "20180202" #parsed_snapshot["event"]["date"]
ownership_percentage = 0.37 #shareholder["ownership_percentage"]
},
{
event_name = "Event 2" #parsed_snapshot["event"]["name"]
event_date = "20180501" #parsed_snapshot["event"]["date"]
ownership_percentage = 0.60 #shareholder["ownership_percentage"]
}
]
My challenge though is that the ["event"]["name"] an ["event"]["date"] attributes I need to fetch when looping over my snapshots i.e. the first loop (.each do |snapshot|) whereas I get my ownership_percentage when looping over shareholders - the second loop (.each do |shareholder|).
So my question is - how can I build this hash in "two" places so I can return the hash with the 3 attributes?
Appreciative of guidance/help - thank you!
You have to create a new hash for the object and append that hash to the array of objects you are creating.
def fetch_ownership_over_time(shareholder, captable)
#shareholder = Shareholder.find(shareholder.id)
#captable = Captable.find(captable.id)
#company = #captable.company.id
#ownership_over_time = []
#captable.events.collect(&:snapshot).each do |snapshot|
parsed_snapshot = JSON.parse(snapshot)
shareholder = parsed_snapshot['shareholders'].select { |s| s['id'] == #shareholder.id }.first
local_snapshot = {
'event_name' => parsed_snapshot['event']['name'],
'event_date' => parsed_snapshot['event']['date'],
'ownership_percentage' => shareholder.try(:[], "ownership_percentage") || 0
}
#ownership_over_time.push local_snapshot
end
return #ownership_over_time
end
Notice that I changed your second loop to a select. As you currently have it, you risk on pushing two percentages if the id is found twice.
EDIT:
Added functionality to use a default value if no shareholder is found.

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.

Data from a JSON API combined with local database in Rails

I would like to combine data retrieved from an API with local database data in a new JSON. But I think I'm doing this wrong. Here is my code :
#data = ActiveSupport::JSON.decode(#api_data)
#data.each do |key|
if key['state'] == "active"
user_id = key['id']
user_database = User.where(:user_id => user_id).take
#userlist = []
unless user_database.blank?
user_data = {
:user_id => key['id'],
:enrolement_start_date => key['start_at'],
:enrolement_end_date => key['end_at'],
:user_interest => user_database.interests,
:user_discipline_id => user_database.discipline_id,
}
#userlist.push(user_data)
end
end
end
#userlist = #userlist.to_json
Actually, it's working but I only receive the last user as result. I don't figure how to make it works :-/ Many thanks in advance !
#userlist = []
that line, each time through the loop
#data.each do |key|
is clearing out the previous data by re-initializing #userlist. Then you're returning the user you added last, since all the others were thrown away the last time you assigned an empty array to #userlist.
Just move
#userlist = []
above
#data.each do |key|
and you should be good.

Array only saves the last value in 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.

There has got to be a cleaner way to do this

I have this code here and it works but there has to be a better way.....i need two arrays that look like this
[
{
"Vector Arena - Auckland Central, New Zealand" => {
"2010-10-10" => [
"Enter Sandman",
"Unforgiven",
"And justice for all"
]
}
},
{
"Brisbane Entertainment Centre - Brisbane Qld, Austr..." => {
"2010-10-11" => [
"Enter Sandman"
]
}
}
]
one for the past and one for the upcoming...the problem i have is i am repeating myself and though it works i want to clean it up ...here is my data
..
Try this:
h = Hash.new {|h1, k1| h1[k1] = Hash.new{|h2, k2| h2[k2] = []}}
result, today = [ h, h.dup], Date.today
Request.find_all_by_artist("Metallica",
:select => "DISTINCT venue, showdate, LOWER(song) AS song"
).each do |req|
idx = req.showdate < today ? 0 : 1
result[idx][req.venue][req.showdate] << req.song.titlecase
end
Note 1
In the first line I am initializing an hash of hashes. The outer hash creates the inner hash when a non existent key is accessed. An excerpt from Ruby Hash documentation:
If this hash is subsequently accessed by a key that doesn‘t correspond to a hash
entry, the block will be called with the hash object and the key, and should
return the default value. It is the block‘s responsibility to store the value in
the hash if required.
The inner hash creates and empty array when the non existent date is accessed.
E.g: Construct an hash containing of content as values and date as keys:
Without a default block:
h = {}
list.each do |data|
h[data.date] = [] unless h[data.date]
h[data.date] << data.content
end
With a default block
h = Hash.new{|h, k| h[k] = []}
list.each do |data|
h[data.date] << data.content
end
Second line simply creates an array with two items to hold the past and future data. Since both past and the present stores the data as Hash of Hash of Array, I simply duplicate the value.
Second line can also be written as
result = [ h, h.dup]
today = Date.today

Resources