How to access the value that is rendered after decoding in rails? - ruby-on-rails

How can i access the year from the json shown below which i fetch from a url and decode using
obj = ActiveSupport::JSON.decode(response.body)
The folloowing is the response i get after decode
{
"educations"=>{"_total"=>1,
"values"=>[
{"id"=>18234534505,
"schoolName"=>"Test",
"startDate"=>{"year"=>2013}
}
]
}
}
How can i access the year? I can able to access the values as
obj['educations']['values']
and it responds as
{"id"=>18234534505, "schoolName"=>"Test", "startDate"=>{"year"=>2013}}
but how can i get the year? please help me.
UPDATE:
how can i add if condition here?
obj["educations"]["values"].each do |value|
#user_education = Education.new("start_date" =>
value['startDate']['year'], "education_id" => value['id'],
"school_name" => value['schoolName'])
end
so here if there is no year then how can i check as you said? and there may also be endDate similar to the startDate so how can i check this?

Just access the key as
obj["educations"]["values"].first["startDate"]["year"]
# above is answer if there is always one array inside `obj["educations"]["values"]`
For multiple arrays's
year = []
obj["educations"]["values"].each do |object|
year << object["startDate"]["year"] if !object["startDate"].blank? and !object["startDate"]["year"].blank?
end
update :
If you want to add attributes to the
#user_education = Education.new
#user_education.start_date = value['startDate']['year'] if !value['startDate'].blank? and !value['startDate']['year'].blank?
#user_education.education_id = value['id'] if !value['id'].blank?
#user_education.school_name = value['schoolName'] if !value['schoolName'].blank?
Similarly for any other attribute..
obj["educations"]["values"].each do |value|
#user_education = Education.new("education_id" => value['id'], "school_name" => value['schoolName'])
#user_education.start_date = value["startDate"]["year"] if !value["startDate"].blank? and !object["startDate"]["year"].blank?
#user_education.save! #To save the object
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.

How to format data Rails

I need to retrieve data from database column and put them to
[{1442507641,1},{1442507642,2},{1442507643,3},{1442507644,4}...]
format as the plot format requires.
I'm trying to do this by :
#data = TableName.where(:id => requiredid)
.map {|r| { r.received_date.to_i => r.value } }
but this returns format
data=[{1442507641=>6}, {1442507641=>7}, {1442507641=>5}, {1442507641=>6}, {1442507641=>5}, {1442507695=>9}, {1442507695=>9}, {1442507695=>7}, {1442507695=>8}]
How can I make the bracket as plot requires and remove the strange =&gt ?
It seems like this ought to do what you're asking for:
parts = TableName.where(:id => requiredid).map do |r|
sprintf("{%d,%d}", r.received_date, r.value)
end
#data = "[#{parts.join(",")}]"
It's only for your options to manipulate your data:
#data = []
#data = User.where(:id => requiredid).map {|r| #data << "{#{r. received_date}, #{r.value}}"}
First you make #data as array. Than collect the string into array.

Adding to and deleting hashes

I am trying to create the back-end for a calendar system. The calendar is just a list of Events. I am trying to organise this in to a reasonable JSON response. The structure I am looking to replicate would be something like this
eventsList = [
{ 'year' => 2014,
'events' => [{event data hash 1},
{event data hash 2}]
},
{ 'year' => 2015,
'events' => [{event data hash 1},
{event data hash 2}]
}
]
I am having trouble trying to add events to the right array. Below I have Event.all and I am trying to sort the list.
events = Event.all
eventList = []
events.each do |event|
#Creates a hash of the current event info
eventInfo = {'description' => event.description, 'startdate' => event.startdate}
eventMonthNumber = event.startdate.strftime('%m').to_i
eventMonthName = event.startdate.strftime('%B')
eventYearNumber = event.startdate.strftime('%Y').to_i
# Adds year to eventList if it isn't present
unless eventList.include?(eventYearNumber)
eventList << {'year' => eventYearNumber, 'events' => []}
end
# Tries to find current year hash in array and add to event key
currentYear = eventList.select {|event| event['year'] == eventYearNumber}
currentYear['events'] << eventInfo
end
I get the error no implicit conversion of String into Integer. I am not entirely sure whether the eventList.select is the correct way to go about this
Although I have moved away from this current structure the change that made it work was swapping out
eventList.select
For
eventList.detect
Select returns an array (?) And detect returns one item.

how to get the key value from the nested hash inside the array?

I have a array which is inside a hash. I want know the result of the student (pass/fail) using the following array. First I have to match them with particular standard and compare their marks with the hash pass and fails. And I want to get the key pass or fail based on their mark. How to achieve this using Ruby?
array = [
{
:standard =>1
:pass=>{:tamil=>30,:eng=>25,:math=>35},
:fail=>{:tamil=>10,:eng=>15,:maths=>20}
},
{
:standard =>2,
:pass=>{:tamil=>40,:eng=>35,:math=>45},
:fail=>{:tamil=>20,:eng=>25,:maths=>30}
}
]
#student is assumed to be defined
standard = array.select {|standard| standard[:standard] == #student.standard}
eng_pass = #student.eng_mark >= standard[:pass][:eng]
eng_fail = #student.eng_mark <= standard[:fail][:eng]
return [eng_pass, eng_fail, whatever_else_you_want]
So on and forth for various topics.
The syntax in reading values from this structure is something like:
array[0][:pass][:eng]
and accordingly you can do the comparison as usual in batch:
for i in 0..#students_array.length
num = # student's score
standard = # something like array[0][:pass][:eng]
if num > standard
# something like 'put "You passed!"'
end
end

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.

Resources