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
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
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
...