Luigi
Luigi

Reputation: 5603

Eloquent Ruby - Extracting values from hash

I'm receiving the following response from an API GET Request:

{"data" => [
  {"firstName"=>"Test", 
   "lastName"=>"LastName", 
   "dateOfBirth"=>"2003-01-17", 
   "details"=> [
     {"date"=>"2013-10-01T00:00:00", 
      "type"=>1, 
      "checkInTime"=>"07:00:00", 
      "checkOutTime"=>"08:00:00"},
     {"date"=>"2013-10-01T00:00:00", 
       "type"=>2, 
       "checkInTime"=>"15:30:00", 
       "checkOutTime"=>"16:00:00"}, 
     {"date"=>"2013-10-02T00:00:00", 
      "type"=>1, 
      "checkInTime"=>"07:00:00", 
      "checkOutTime"=>"08:00:00"}, 
     {"date"=>"2013-10-02T00:00:00", 
      "type"=>2, 
      "checkInTime"=>"15:30:00", 
      "checkOutTime"=>"16:00:00"}, 
     {"date"=>"2013-10-03T00:00:00", 
      "type"=>1, 
      "checkInTime"=>"07:00:00", 
      "checkOutTime"=>"08:00:00"}, 
     {"date"=>"2013-10-04T00:00:00", 
      "type"=>1, 
      "checkInTime"=>"07:00:00", 
      "checkOutTime"=>"08:00:00"}, 
     {"date"=>"2013-10-07T00:00:00", 
      "type"=>1,
      "checkInTime"=>"07:00:00", 
      "checkOutTime"=>"08:00:00"}, 
     {"date"=>"2013-10-07T00:00:00",
      "type"=>2,
      "checkInTime"=>"15:30:00",
      "checkOutTime"=>"16:40:00"}]}]}

I'm going to receive 100~ of these similar responses. I need to extract this information into rows within a table.

My current method is to dump each key/value into a separate array and transpose the arrays as columns, essentially creating rows. Regardless of whether that is right or not, how can I pull something like this with the above hash:

First Name | Date Of Birth | Date       | Check In Time| Date       | Check In Time| ...
Test       | 2003-01-07    | 2013-10-01 | 07:00        | 2013-10-01 | 15:30        | ...

As a side note, I will do some sort of loop and have around 100 rows with similar data.

EDIT:

To provide more information, I am using the Prawn gem to generate a table within a PDF. The code looks like this:

font("Times-Roman", :size => 8) do
  bounding_box([bounds.left, bounds.top - 165], :width  => bounds.width, :height => bounds.height - 200) do                 
table([
          [{content: "Child's Name",borders: [:left, :top]},{:content => "Sunday", :align => :center, :colspan => 2},{:content => "Monday", :align => :center, :colspan => 2},{:content => "Tuesday", :align => :center, :colspan => 2},{:content => "Wednesday", :align => :center, :colspan => 2},{:content => "Thursday", :align => :center, :colspan => 2},{:content => "Friday", :align => :center, :colspan => 2},{:content => "Saturday", :align => :center, :colspan => 2},{content: 'Signature of Parent or Designated Person to Verify Accuracy of Attendance for the week', rowspan: 3}],
          [{content: '', :height => 20,borders: [:left]},'Time In', 'Time Out', 'Time In', 'Time Out', 'Time In', 'Time Out', 'Time In', 'Time Out', 'Time In', 'Time Out', 'Time In', 'Time Out', 'Time In', 'Time Out'],
          [{content: '(as it appears on PBF)', :height => 26,borders: [:left, :bottom], align: :center, inline_format: true }, 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials', 'Initials']
        ],
          #Set column widths
        :column_widths => {0 => 60,1 => 42,2 => 42,3 => 42,4 => 42,5 => 42,6 => 42,7 => 42,8 => 42,9 => 42,10 => 42,11 => 42,12 => 42,13 => 42,14 => 42}) do
        #Color every other column grey --------------
        column(1).style :background_color => 'C0C0C0'
        column(2).style :background_color => 'C0C0C0'
        column(5).style :background_color => 'C0C0C0'
        column(6).style :background_color => 'C0C0C0'
        column(9).style :background_color => 'C0C0C0'
        column(10).style :background_color => 'C0C0C0'
        column(13).style :background_color => 'C0C0C0'
        column(14).style :background_color => 'C0C0C0'
      end #End Column Style
    end #End Boundind Box
  end #End Font

The Table generates correctly, but it only contains headers. The response I am receiving back from the GET Request should fit into this table. Each data element should be a separate row within the table, and each details object should be a separate column on that row.

Upvotes: 0

Views: 163

Answers (3)

Ajedi32
Ajedi32

Reputation: 48418

I'm still not 100% sure exactly what you're looking for, but if all you want is to extract an array of data representing a row from each entry in data, I'd probably do something like this:

data = your_hash["data"]
result = data.map do |entry|
  [entry["firstName"], entry["lastName"], entry["dateOfBirth"]] + entry["details"].flat_map do |details|
    [details["checkInTime"], details["checkOutTime"]]
  end
end

Which in your case yields:

[
  ["Test", "LastName", "2003-01-17", "07:00:00", "08:00:00", "15:30:00", "16:00:00", "07:00:00", "08:00:00", "15:30:00", "16:00:00", "07:00:00", "08:00:00", "07:00:00", "08:00:00", "07:00:00", "08:00:00", "15:30:00", "16:40:00"]
]

Upvotes: 0

CDub
CDub

Reputation: 13354

A quick run through IRB for me shows this does (I think) what you want it to...

hash = {"data" => [
      {"firstName"=>"Test", 
       "lastName"=>"LastName", 
       "dateOfBirth"=>"2003-01-17", 
       "details"=> [
         {"date"=>"2013-10-01T00:00:00", 
          "type"=>1, 
          "checkInTime"=>"07:00:00", 
          "checkOutTime"=>"08:00:00"},
         {"date"=>"2013-10-01T00:00:00", 
           "type"=>2, 
           "checkInTime"=>"15:30:00", 
           "checkOutTime"=>"16:00:00"}, 
         {"date"=>"2013-10-02T00:00:00", 
          "type"=>1, 
          "checkInTime"=>"07:00:00", 
          "checkOutTime"=>"08:00:00"}, 
         {"date"=>"2013-10-02T00:00:00", 
          "type"=>2, 
          "checkInTime"=>"15:30:00", 
          "checkOutTime"=>"16:00:00"}, 
         {"date"=>"2013-10-03T00:00:00", 
          "type"=>1, 
          "checkInTime"=>"07:00:00", 
          "checkOutTime"=>"08:00:00"}, 
         {"date"=>"2013-10-04T00:00:00", 
          "type"=>1, 
          "checkInTime"=>"07:00:00", 
          "checkOutTime"=>"08:00:00"}, 
         {"date"=>"2013-10-07T00:00:00", 
          "type"=>1,
          "checkInTime"=>"07:00:00", 
          "checkOutTime"=>"08:00:00"}, 
         {"date"=>"2013-10-07T00:00:00",
          "type"=>2,
          "checkInTime"=>"15:30:00",
          "checkOutTime"=>"16:40:00"}]}]}


@results_set = hash["data"]

@results_set.each do |results_hash|
  header_row = ["firstName", "dateOfBirth"]
  results_row = [results_hash["firstName"], results_hash["lastName"]]

  results_hash["details"].each do |details_hash|
    header_row << ["date", "checkInTime"]
    results_row << [details_hash["date"], details_hash["checkInTime"]]
  end

  puts header_row.flatten.join("   |   ")
  puts results_row.flatten.join("   |   ")
end;nil

firstName | dateOfBirth | date | checkInTime | date
| checkInTime | date | checkInTime | date |
checkInTime | date | checkInTime | date | checkInTime | date | checkInTime | date | checkInTime Test |
LastName | 2013-10-01T00:00:00 | 07:00:00 |
2013-10-01T00:00:00 | 15:30:00 | 2013-10-02T00:00:00 |
07:00:00 | 2013-10-02T00:00:00 | 15:30:00 |
2013-10-03T00:00:00 | 07:00:00 | 2013-10-04T00:00:00 |
07:00:00 | 2013-10-07T00:00:00 | 07:00:00 |
2013-10-07T00:00:00 | 15:30:00

Upvotes: 0

Joey
Joey

Reputation: 343

I think this would work:

first_name = your_hash[:data][0]['firstName']
date = your_hash[:data][0]['details'][0]['date']

Upvotes: 0

Related Questions