Ruby on Rails: intentando obtener datos JSON de la API y guardarlos en la base de datos de Postgres - ¡rake abortado! TypeError: sin conversión implícita de String en Integer

Oct 19 2020

Estoy usando Ruby on Rails e intento obtener datos JSON de una API pública y guardarlos en una base de datos de Postgres.

Cuando ejecuto rake db: seed, aparece el siguiente error:

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)

Como referencia, la línea 21 es:

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

La línea 48 es donde se llama al método:

properties

Aquí está el primer elemento en la matriz JSON para darle una idea de lo que estoy tratando de trazar.

[
  {
    "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
      }
    ]
  },

El esquema de mi base de datos sigue la estructura JSON pero no exactamente (no estoy seguro de si esto está 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 

Aquí está mi archivo 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

Cuando ejecuto rake db: seed, aparece el siguiente error:

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)

Como referencia, la línea 21 es:

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

La línea 48 es donde se llama al método:

properties

Cualquier ayuda será apreciada, gracias

Respuestas

1 rmlockerd Oct 20 2020 at 05:06

Para resumir las recomendaciones en los diversos comentarios, jsones una Arrayvez analizado el JSON. Los índices de matriz son números enteros, por lo que los json["data"]resultados en a TypeError. En segundo lugar, no hay ningún datacampo para los registros JSON devueltos. Simplemente puede iterar sobre la matriz de resultados y crear sus registros así:

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

Realmente no necesita la .nil?verificación en su original, ya que RestClientgenera un error para cualquier código de respuesta HTTP que no sea 200-2007. Asimismo, JSON.parsegenerará un error si la respuesta no es JSON válido.

Resultado:

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