Ruby on Rails: tentativo di ottenere dati JSON dall'API e salvarli nel database Postgres - rake interrotto! TypeError: nessuna conversione implicita di String in Integer

Oct 19 2020

Sto usando Ruby on Rails e provo a ottenere dati JSON da un'API pubblica e salvarli in un database Postgres.

Quando eseguo rake db: seed, ricevo il seguente errore:

rake aborted!
TypeError: no implicit conversion of String into Integer
/db/seeds.rb:21:in `[]'
/db/seeds.rb:21:in `properties'
/db/seeds.rb:48:in `<top (required)>'
Tasks: TOP => db:seed
(See full trace by running task with --trace)

Per riferimento, la riga 21 è:

json["data"].map do |property|

La riga 48 è dove viene chiamato il metodo:

properties

Ecco il primo elemento nell'array JSON per darti un'idea di cosa sto cercando di mappare.

[
  {
    "PublicationDate": "26/10/2018",
    "PropertyNumber": 2195606,
    "County": "LAOIS",
    "LocalAuthority": "LAOIS COUNTY COUNCIL",
    "Valuation": 70600.0,
    "Category": "RETAIL (SHOPS)",
    "Uses": "SUPERMARKET 2 [500-2500 SQ. M.], -",
    "Address1": "36-42A/1 POUND STREET",
    "Address2": "RATHDOWNEY",
    "Address3": "CO. LAOIS",
    "Address4": "",
    "Address5": "",
    "CarPark": 0,
    "Xitm": 628016.65,
    "Yitm": 678231.8,
    "ValuationReport": [
      {
        "Level": "0      ",
        "FloorUse": "SUPERMARKET",
        "Area": 964.62,
        "NavPerM2": 60.0000,
        "Nav": 57877.200000
      },
      {
        "Level": "0",
        "FloorUse": "OFF LICENCE",
        "Area": 1.00,
        "NavPerM2": 8681.5800,
        "Nav": 8681.580000
      },
      {
        "Level": "0",
        "FloorUse": "FIT-OUT ALLOWANCE",
        "Area": 1.00,
        "NavPerM2": 4051.4000,
        "Nav": 4051.400000
      }
    ]
  },

Lo schema del mio database segue la struttura JSON ma non esattamente (non sono sicuro che questo stia causando un problema):

create_table "properties", force: :cascade do |t|
    t.bigint "user_id"
    t.string "publication_date"
    t.string "property_number"
    t.string "county"
    t.string "local_authority"
    t.string "valuation"
    t.string "category"
    t.string "uses"
    t.string "address_1"
    t.string "address_2"
    t.string "address_3"
    t.string "address_4"
    t.string "address_5"
    t.string "car_park"
    t.string "xitm"
    t.string "yitm"
    t.string "valuation_report"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["user_id"], name: "index_properties_on_user_id"
  end 

Ecco il mio file seeds.rb:

require 'rest-client'

# Define Method
def properties

    response = RestClient.get('https://api.valoff.ie/api/Property/GetProperties?Fields=*&LocalAuthority=LAOIS%20COUNTY%20COUNCIL&CategorySelected=RETAIL%20(SHOPS)&Format=csv&Download=false')

    json = JSON.parse response
    
    if !json.nil?
        json["data"].map do |property|
            Property.create(
                publication_date: "#{PublicationDate}",
                property_number: "#{PropertyNumber}",
                county: "#{County}",
                local_authority: "#{LocalAuthority}",
                valuation: "#{Valuation}",
                category: "#{Category}",
                uses: "#{Uses}",
                address_1: "#{Address1}",
                address_2: "#{Address2}",
                address_3: "#{Address3}",
                address_4: "#{Address4}",
                address_5: "#{Address5}",
                car_park: "#{CarPark}",
                xitm: "#{Xitm}",
                yitm: "#{Yitm}",
                valuation_report: "#{ValuationReport}"
            )
        end
    else
        puts "Error seeding properties."
    end

end

# Call Method
properties

Quando eseguo rake db: seed, ricevo il seguente errore:

rake aborted!
TypeError: no implicit conversion of String into Integer
/db/seeds.rb:21:in `[]'
/db/seeds.rb:21:in `properties'
/db/seeds.rb:48:in `<top (required)>'
Tasks: TOP => db:seed
(See full trace by running task with --trace)

Per riferimento, la riga 21 è:

json["data"].map do |property|

La riga 48 è dove viene chiamato il metodo:

properties

Qualsiasi aiuto sarebbe apprezzato, grazie

Risposte

1 rmlockerd Oct 20 2020 at 05:06

Per riassumere le raccomandazioni nei vari commenti, jsonè un Arraydopo che il JSON viene analizzato. Gli indici di matrice sono numeri interi, quindi json["data"]risulta in un file TypeError. In secondo luogo, non è presente alcun datacampo per i record JSON restituiti. Puoi semplicemente iterare sull'array dei risultati e creare i tuoi record in questo modo:

def properties
  response = RestClient.get('https://api.valoff.ie/api/Property/GetProperties?Fields=*&LocalAuthority=LAOIS%20COUNTY%20COUNCIL&CategorySelected=RETAIL%20(SHOPS)&Format=csv&Download=false')

  json = JSON.parse(response)

  json.each do |property|
    puts "Creating property #{property['PropertyNumber']}"
    Property.create!(
      publication_date: property['PublicationDate'],
      property_number: property['PropertyNumber'],
      county: property['County'],
      local_authority: property['LocalAuthority'],
      valuation_report: property['ValuationReport']
      # ... remaining fields omitted for brevity
    )
  end
end

Non hai davvero bisogno del .nil?controllo nell'originale, poiché RestClientgenera un errore per qualsiasi codice di risposta HTTP diverso da 200-2007. Allo stesso modo, JSON.parsegenererà un errore se la risposta non è JSON valido.

Risultato:

$ rails db:seed
Creating property 1555903
Creating property 1556133
Creating property 1556998
Creating property 1556516
Creating property 1557007
...