From e6fdadf57f4251c82528cd5ab52d5dee206af234 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Tue, 10 Feb 2026 22:10:46 -0500 Subject: [PATCH 01/14] add motor vehicle collisions crashes --- ...create_motor_vehicle_collisions_crashes.rb | 22 +++++++++++++++++++ db/schema.rb | 21 +++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100755 db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb diff --git a/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb b/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb new file mode 100755 index 0000000..af91ba1 --- /dev/null +++ b/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb @@ -0,0 +1,22 @@ +class CreateMotorVehicleCollisionsCrashes < ActiveRecord::Migration[7.2] + def change + create_table :motor_vehicle_collisions_crashes do |t| + t.datetime :crash_date + t.datetime :crash_time + t.string :borough + t.string :zipcode + t.decimal :latitude + t.decimal :longitude + t.string :on_street_name + t.string :cross_street_name + t.string :off_street_name + t.integer :number_of_persons_injured + t.integer :number_of_persons_killed + t.integer :number_of_pedestrians_injured + t.integer :number_of_pedestrians_killed + t.integer :number_of_cyclist_injured + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index a26a2f0..27e2fdf 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2025_12_23_031248) do +ActiveRecord::Schema[7.2].define(version: 2026_02_11_012939) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -29,6 +29,25 @@ t.index ["original_id"], name: "index_bicycle_counters_on_original_id", unique: true end + create_table "motor_vehicle_collisions_crashes", force: :cascade do |t| + t.datetime "crash_date" + t.datetime "crash_time" + t.string "borough" + t.string "zipcode" + t.decimal "latitude" + t.decimal "longitude" + t.string "on_street_name" + t.string "cross_street_name" + t.string "off_street_name" + t.integer "number_of_persons_injured" + t.integer "number_of_persons_killed" + t.integer "number_of_pedestrians_injured" + t.integer "number_of_pedestrians_killed" + t.integer "number_of_cyclist_injured" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "nyc_permitted_event_information_historicals", force: :cascade do |t| t.integer "event_id" t.string "event_name" From b15f8aa9a39905fce88099263398db65d7b60545 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Tue, 10 Feb 2026 22:13:31 -0500 Subject: [PATCH 02/14] add model --- app/models/motor_vehicle_collisions_crash.rb | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 app/models/motor_vehicle_collisions_crash.rb diff --git a/app/models/motor_vehicle_collisions_crash.rb b/app/models/motor_vehicle_collisions_crash.rb new file mode 100644 index 0000000..cca82d6 --- /dev/null +++ b/app/models/motor_vehicle_collisions_crash.rb @@ -0,0 +1,2 @@ +class MotorVehicleCollisionsCrash < ApplicationRecord +end \ No newline at end of file From 94ac902ac0bbe1b772e9107b0bdf9dbc5e75b84a Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Tue, 10 Feb 2026 22:18:47 -0500 Subject: [PATCH 03/14] namespace model and add methods --- app/models/motor_vehicle_collisions_crash.rb | 2 -- .../motor_vehicle_collisions_crash.rb | 27 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) delete mode 100644 app/models/motor_vehicle_collisions_crash.rb create mode 100644 app/models/police_department/motor_vehicle_collisions_crash.rb diff --git a/app/models/motor_vehicle_collisions_crash.rb b/app/models/motor_vehicle_collisions_crash.rb deleted file mode 100644 index cca82d6..0000000 --- a/app/models/motor_vehicle_collisions_crash.rb +++ /dev/null @@ -1,2 +0,0 @@ -class MotorVehicleCollisionsCrash < ApplicationRecord -end \ No newline at end of file diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb new file mode 100644 index 0000000..19a4e80 --- /dev/null +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -0,0 +1,27 @@ +module PoliceDepartment + class MotorVehicleCollisionsCrash < ApplicationRecord + self.table_name = :motor_vehicle_collisions_crashes + + SODA2_API_ENDPOINT = "https://data.cityofnewyork.us/resource/h9gi-nx95.json" + SODA2_CSV_API_ENDPOINT = "https://data.cityofnewyork.us/resource/h9gi-nx95.csv" + + SODA3_API_ENDPOINT = "https://data.cityofnewyork.us/api/v3/views/h9gi-nx95/query.json" + SODA3_CSV_API_ENDPOINT = "https://data.cityofnewyork.us/api/v3/views/h9gi-nx95/query.csv" + + def self.url + "https://data.cityofnewyork.us/Public-Safety/Motor-Vehicle-Collisions-Crashes/h9gi-nx95/about_data" + end + + def self.name + "Motor Vehicle Collisions - Crashes" + end + + def self.description + "The Motor Vehicle Collisions crash table contains details on the crash event. Each row represents a crash event. The Motor Vehicle Collisions data tables contain information from all police reported motor vehicle collisions in NYC. The police report (MV104-AN) is required to be filled out for collisions where someone is injured or killed, or where there is at least $1000 worth of damage (https://www.nhtsa.gov/sites/nhtsa.dot.gov/files/documents/ny_overlay_mv-104an_rev05_2004.pdf). It should be noted that the data is preliminary and subject to change when the MV-104AN forms are amended based on revised crash details.For the most accurate, up to date statistics on traffic fatalities, please refer to the NYPD Motor Vehicle Collisions page (updated weekly) or Vision Zero View (updated monthly)." + end + + def self.data_provided_by + "Police Department (NYPD)" + end + end +end From ea374fe0ce7e15b9c8dac59daec45052402a0652 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Tue, 10 Feb 2026 22:22:30 -0500 Subject: [PATCH 04/14] add methods --- .../motor_vehicle_collisions_crash.rb | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index 19a4e80..0f8d20d 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -23,5 +23,32 @@ def self.description def self.data_provided_by "Police Department (NYPD)" end + + # Dataset Information + def self.agency + "Police Department (NYPD)" + end + + # Update + def self.update_frequency + "Daily" + end + + def self.automation + "Yes" + end + + def self.date_made_public + "5/7/2014" + end + + # Topics + def self.category + "Public Safety" + end + + def self.tags + "nypd, collisions, bigapps, big apps, visionzero, vision, zero, nycopendata, traffic data" + end end end From 5322fb986ed795ef580df45a146cf0adae6325e1 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Tue, 10 Feb 2026 22:42:21 -0500 Subject: [PATCH 05/14] add remaining fields and unique index --- .../motor_vehicle_collisions_crash.rb | 50 +++++++++++++++++++ ...create_motor_vehicle_collisions_crashes.rb | 20 +++++++- db/schema.rb | 18 ++++++- 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index 0f8d20d..f6fc100 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -50,5 +50,55 @@ def self.category def self.tags "nypd, collisions, bigapps, big apps, visionzero, vision, zero, nycopendata, traffic data" end + + # Import + def self.import(api_version: '2', content_type: 'json') + if api_version == '2' && content_type == 'json' + import_soda2 + end + + # if api_version == '2' && content_type == 'csv' + # import_soda2_csv + # end + + # if api_version == '3' && content_type == 'json' + # import_soda3 + # end + + # if api_version == '3' && content_type == 'csv' + # import_soda3_csv + # end + end + + def self.import_soda2 + data = RemoteDataset::Soda2::Json.new(remote_url: SODA2_API_ENDPOINT) + + # data.each do |row| + # original_id = row["id"] + # name = row["name"] + # domain = row["domain"] + # latitude = row["latitude"] + # longitude = row["longitude"] + # interval = row["interval"] + # timezone = row["timezone"] + # sens = row["sens"] + # counter = row["counter"] + + # next if BicycleCounter.find_by(original_id: original_id).present? + + # BicycleCounter.create!( + # original_id: original_id, + # name: name, + # domain: domain, + # latitude: latitude, + # longitude: longitude, + # interval: interval, + # timezone: timezone, + # sens: sens, + # counter: counter + # ) + # end + end + private_class_method :import_soda2 end end diff --git a/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb b/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb index af91ba1..70e02e7 100755 --- a/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb +++ b/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb @@ -4,19 +4,35 @@ def change t.datetime :crash_date t.datetime :crash_time t.string :borough - t.string :zipcode + t.string :zip_code t.decimal :latitude t.decimal :longitude t.string :on_street_name - t.string :cross_street_name t.string :off_street_name + # t.string :cross_street_name t.integer :number_of_persons_injured t.integer :number_of_persons_killed t.integer :number_of_pedestrians_injured t.integer :number_of_pedestrians_killed t.integer :number_of_cyclist_injured + t.integer :number_of_cyclist_killed + t.integer :number_of_motorist_injured + t.integer :number_of_motorist_killed + t.string :contributing_factor_vehicle_1 + t.string :contributing_factor_vehicle_2 + t.string :contributing_factor_vehicle_3 + t.string :contributing_factor_vehicle_4 + t.string :contributing_factor_vehicle_5 + t.bigint :collision_id + t.string :vehicle_type_code1 + t.string :vehicle_type_code2 + t.string :vehicle_type_code_3 + t.string :vehicle_type_code_4 + t.string :vehicle_type_code_5 t.timestamps end + + add_index :motor_vehicle_collisions_crashes, :collision_id, unique: true end end diff --git a/db/schema.rb b/db/schema.rb index 27e2fdf..543127a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -33,19 +33,33 @@ t.datetime "crash_date" t.datetime "crash_time" t.string "borough" - t.string "zipcode" + t.string "zip_code" t.decimal "latitude" t.decimal "longitude" t.string "on_street_name" - t.string "cross_street_name" t.string "off_street_name" t.integer "number_of_persons_injured" t.integer "number_of_persons_killed" t.integer "number_of_pedestrians_injured" t.integer "number_of_pedestrians_killed" t.integer "number_of_cyclist_injured" + t.integer "number_of_cyclist_killed" + t.integer "number_of_motorist_injured" + t.integer "number_of_motorist_killed" + t.string "contributing_factor_vehicle_1" + t.string "contributing_factor_vehicle_2" + t.string "contributing_factor_vehicle_3" + t.string "contributing_factor_vehicle_4" + t.string "contributing_factor_vehicle_5" + t.bigint "collision_id" + t.string "vehicle_type_code1" + t.string "vehicle_type_code2" + t.string "vehicle_type_code_3" + t.string "vehicle_type_code_4" + t.string "vehicle_type_code_5" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["collision_id"], name: "index_motor_vehicle_collisions_crashes_on_collision_id", unique: true end create_table "nyc_permitted_event_information_historicals", force: :cascade do |t| From 42ce42e45754da0ecf5fad52bbad2de3f01f20c9 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Tue, 10 Feb 2026 22:57:20 -0500 Subject: [PATCH 06/14] add import method --- .../motor_vehicle_collisions_crash.rb | 86 +++++++++++++------ 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index f6fc100..cee20cd 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -73,31 +73,67 @@ def self.import(api_version: '2', content_type: 'json') def self.import_soda2 data = RemoteDataset::Soda2::Json.new(remote_url: SODA2_API_ENDPOINT) - # data.each do |row| - # original_id = row["id"] - # name = row["name"] - # domain = row["domain"] - # latitude = row["latitude"] - # longitude = row["longitude"] - # interval = row["interval"] - # timezone = row["timezone"] - # sens = row["sens"] - # counter = row["counter"] - - # next if BicycleCounter.find_by(original_id: original_id).present? - - # BicycleCounter.create!( - # original_id: original_id, - # name: name, - # domain: domain, - # latitude: latitude, - # longitude: longitude, - # interval: interval, - # timezone: timezone, - # sens: sens, - # counter: counter - # ) - # end + data.each do |row| + crash_date = row["crash_date"] + crash_time = row["crash_time"] + borough = row["borough"] + zip_code = row["zip_code"] + latitude = row["latitude"] + longitude = row["longitude"] + on_street_name = row["on_street_name"] + off_street_name = row["off_street_name"] + number_of_persons_injured = row["number_of_persons_injured"] + number_of_persons_killed = row["number_of_persons_killed"] + number_of_pedestrians_injured = row["number_of_pedestrians_injured"] + number_of_pedestrians_killed = row["number_of_pedestrians_killed"] + number_of_cyclist_injured = row ["number_of_cyclist_injured"] + number_of_cyclist_killed = row["number_of_cyclist_killed"] + number_of_motorist_injured = row["number_of_motorist_injured"] + number_of_motorist_killed = row["number_of_motorist_killed"] + contributing_factor_vehicle_1 = row["contributing_factor_vehicle_1"] + contributing_factor_vehicle_2 = row["contributing_factor_vehicle_2"] + contributing_factor_vehicle_3 = row["contributing_factor_vehicle_3"] + contributing_factor_vehicle_4 = row["contributing_factor_vehicle_4"] + contributing_factor_vehicle_5 = row["contributing_factor_vehicle_5"] + collision_id = row["collision_id"] + vehicle_type_code1 = row["vehicle_type_code1"] + vehicle_type_code2 = row["vehicle_type_code2"] + vehicle_type_code_3 = row["vehicle_type_code_3"] + vehicle_type_code_4 = row["vehicle_type_code_4"] + vehicle_type_code_5 = row["vehicle_type_code_5"] + + next if MotorVehicleCollisionsCrash.find_by(collision_id: collision_id).present? + + MotorVehicleCollisionsCrash.create!( + crash_date: crash_date, + crash_time: crash_time, + borough: borough, + zip_code: zip_code, + latitude: latitude, + longitude: longitude, + on_street_name: on_street_name, + off_street_name: off_street_name, + number_of_persons_injured: number_of_persons_injured, + number_of_persons_killed: number_of_persons_killed, + number_of_pedestrians_injured: number_of_pedestrians_injured, + number_of_pedestrians_killed: number_of_pedestrians_killed, + number_of_cyclist_injured: number_of_cyclist_injured, + number_of_cyclist_killed: number_of_cyclist_killed, + number_of_motorist_injured: number_of_motorist_injured, + number_of_motorist_killed: number_of_motorist_killed, + contributing_factor_vehicle_1: contributing_factor_vehicle_1, + contributing_factor_vehicle_2: contributing_factor_vehicle_2, + contributing_factor_vehicle_3: contributing_factor_vehicle_3, + contributing_factor_vehicle_4: contributing_factor_vehicle_4, + contributing_factor_vehicle_5: contributing_factor_vehicle_5, + collision_id: collision_id, + vehicle_type_code1: vehicle_type_code1, + vehicle_type_code2: vehicle_type_code2, + vehicle_type_code_3: vehicle_type_code_3, + vehicle_type_code_4: vehicle_type_code_4, + vehicle_type_code_5: vehicle_type_code_5 + ) + end end private_class_method :import_soda2 end From 75194047907917c38b80ee8a75d42b1a021f2fb1 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Wed, 11 Feb 2026 07:36:22 -0500 Subject: [PATCH 07/14] add import_soda2_csv --- .../motor_vehicle_collisions_crash.rb | 75 ++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index cee20cd..f3ef781 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -57,9 +57,9 @@ def self.import(api_version: '2', content_type: 'json') import_soda2 end - # if api_version == '2' && content_type == 'csv' - # import_soda2_csv - # end + if api_version == '2' && content_type == 'csv' + import_soda2_csv + end # if api_version == '3' && content_type == 'json' # import_soda3 @@ -136,5 +136,74 @@ def self.import_soda2 end end private_class_method :import_soda2 + + def self.import_soda2_csv + csv = RemoteDataset::Soda2::Csv.new(remote_url: SODA2_CSV_API_ENDPOINT) + + csv.each do |row| + crash_date = row[0] + crash_time = row[1] + borough = row[2] + zip_code = row[3] + latitude = row[4] + longitude = row[5] + _location = row[6] + on_street_name = row[7] + off_street_name = row[8] + _cross_street_name = row[9] + number_of_persons_injured = row[10] + number_of_persons_killed = row[11] + number_of_pedestrians_injured = row[12] + number_of_pedestrians_killed = row[13] + number_of_cyclist_injured = row [14] + number_of_cyclist_killed = row[15] + number_of_motorist_injured = row[16] + number_of_motorist_killed = row[17] + contributing_factor_vehicle_1 = row[18] + contributing_factor_vehicle_2 = row[19] + contributing_factor_vehicle_3 = row[20] + contributing_factor_vehicle_4 = row[21] + contributing_factor_vehicle_5 = row[22] + collision_id = row[23] + vehicle_type_code1 = row[24] + vehicle_type_code2 = row[25] + vehicle_type_code_3 = row[26] + vehicle_type_code_4 = row[27] + vehicle_type_code_5 = row[28] + + next if MotorVehicleCollisionsCrash.find_by(original_id: original_id).present? + + MotorVehicleCollisionsCrash.create!( + crash_date: crash_date, + crash_time: crash_time, + borough: borough, + zip_code: zip_code, + latitude: latitude, + longitude: longitude, + on_street_name: on_street_name, + off_street_name: off_street_name, + number_of_persons_injured: number_of_persons_injured, + number_of_persons_killed: number_of_persons_killed, + number_of_pedestrians_injured: number_of_pedestrians_injured, + number_of_pedestrians_killed: number_of_pedestrians_killed, + number_of_cyclist_injured: number_of_cyclist_injured, + number_of_cyclist_killed: number_of_cyclist_killed, + number_of_motorist_injured: number_of_motorist_injured, + number_of_motorist_killed: number_of_motorist_killed, + contributing_factor_vehicle_1: contributing_factor_vehicle_1, + contributing_factor_vehicle_2: contributing_factor_vehicle_2, + contributing_factor_vehicle_3: contributing_factor_vehicle_3, + contributing_factor_vehicle_4: contributing_factor_vehicle_4, + contributing_factor_vehicle_5: contributing_factor_vehicle_5, + collision_id: collision_id, + vehicle_type_code1: vehicle_type_code1, + vehicle_type_code2: vehicle_type_code2, + vehicle_type_code_3: vehicle_type_code_3, + vehicle_type_code_4: vehicle_type_code_4, + vehicle_type_code_5: vehicle_type_code_5 + ) + end + end + private_class_method :import_soda2_csv end end From 99da0ecfe3ba2d8fe2bd1373fbbc7953436d36b1 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Wed, 11 Feb 2026 07:39:03 -0500 Subject: [PATCH 08/14] fix --- app/models/police_department/motor_vehicle_collisions_crash.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index f3ef781..952d2d4 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -171,7 +171,7 @@ def self.import_soda2_csv vehicle_type_code_4 = row[27] vehicle_type_code_5 = row[28] - next if MotorVehicleCollisionsCrash.find_by(original_id: original_id).present? + next if MotorVehicleCollisionsCrash.find_by(collision_id: collision_id).present? MotorVehicleCollisionsCrash.create!( crash_date: crash_date, From f1b39334423e5464137cafd238d656b4d3efc1f6 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Wed, 11 Feb 2026 07:41:45 -0500 Subject: [PATCH 09/14] capture cross street name --- app/models/police_department/motor_vehicle_collisions_crash.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index 952d2d4..e1f95c9 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -80,8 +80,10 @@ def self.import_soda2 zip_code = row["zip_code"] latitude = row["latitude"] longitude = row["longitude"] + _location = row["location"] on_street_name = row["on_street_name"] off_street_name = row["off_street_name"] + _cross_street_name = row["cross_street_name"] number_of_persons_injured = row["number_of_persons_injured"] number_of_persons_killed = row["number_of_persons_killed"] number_of_pedestrians_injured = row["number_of_pedestrians_injured"] From 9d87ec33c32642f0aebbe0028899aebcfc00318d Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Wed, 11 Feb 2026 08:50:35 -0500 Subject: [PATCH 10/14] add import method --- .../motor_vehicle_collisions_crash.rb | 75 ++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index e1f95c9..a5bfe0e 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -61,9 +61,9 @@ def self.import(api_version: '2', content_type: 'json') import_soda2_csv end - # if api_version == '3' && content_type == 'json' - # import_soda3 - # end + if api_version == '3' && content_type == 'json' + import_soda3 + end # if api_version == '3' && content_type == 'csv' # import_soda3_csv @@ -207,5 +207,74 @@ def self.import_soda2_csv end end private_class_method :import_soda2_csv + + def self.import_soda3 + data = RemoteDataset::Soda3::Json.new(remote_url: SODA3_API_ENDPOINT) + + data.each do |row| + crash_date = row["crash_date"] + crash_time = row["crash_time"] + borough = row["borough"] + zip_code = row["zip_code"] + latitude = row["latitude"] + longitude = row["longitude"] + _location = row["location"] + on_street_name = row["on_street_name"] + off_street_name = row["off_street_name"] + _cross_street_name = row["cross_street_name"] + number_of_persons_injured = row["number_of_persons_injured"] + number_of_persons_killed = row["number_of_persons_killed"] + number_of_pedestrians_injured = row["number_of_pedestrians_injured"] + number_of_pedestrians_killed = row["number_of_pedestrians_killed"] + number_of_cyclist_injured = row ["number_of_cyclist_injured"] + number_of_cyclist_killed = row["number_of_cyclist_killed"] + number_of_motorist_injured = row["number_of_motorist_injured"] + number_of_motorist_killed = row["number_of_motorist_killed"] + contributing_factor_vehicle_1 = row["contributing_factor_vehicle_1"] + contributing_factor_vehicle_2 = row["contributing_factor_vehicle_2"] + contributing_factor_vehicle_3 = row["contributing_factor_vehicle_3"] + contributing_factor_vehicle_4 = row["contributing_factor_vehicle_4"] + contributing_factor_vehicle_5 = row["contributing_factor_vehicle_5"] + collision_id = row["collision_id"] + vehicle_type_code1 = row["vehicle_type_code1"] + vehicle_type_code2 = row["vehicle_type_code2"] + vehicle_type_code_3 = row["vehicle_type_code_3"] + vehicle_type_code_4 = row["vehicle_type_code_4"] + vehicle_type_code_5 = row["vehicle_type_code_5"] + + next if MotorVehicleCollisionsCrash.find_by(collision_id: collision_id).present? + + MotorVehicleCollisionsCrash.create!( + crash_date: crash_date, + crash_time: crash_time, + borough: borough, + zip_code: zip_code, + latitude: latitude, + longitude: longitude, + on_street_name: on_street_name, + off_street_name: off_street_name, + number_of_persons_injured: number_of_persons_injured, + number_of_persons_killed: number_of_persons_killed, + number_of_pedestrians_injured: number_of_pedestrians_injured, + number_of_pedestrians_killed: number_of_pedestrians_killed, + number_of_cyclist_injured: number_of_cyclist_injured, + number_of_cyclist_killed: number_of_cyclist_killed, + number_of_motorist_injured: number_of_motorist_injured, + number_of_motorist_killed: number_of_motorist_killed, + contributing_factor_vehicle_1: contributing_factor_vehicle_1, + contributing_factor_vehicle_2: contributing_factor_vehicle_2, + contributing_factor_vehicle_3: contributing_factor_vehicle_3, + contributing_factor_vehicle_4: contributing_factor_vehicle_4, + contributing_factor_vehicle_5: contributing_factor_vehicle_5, + collision_id: collision_id, + vehicle_type_code1: vehicle_type_code1, + vehicle_type_code2: vehicle_type_code2, + vehicle_type_code_3: vehicle_type_code_3, + vehicle_type_code_4: vehicle_type_code_4, + vehicle_type_code_5: vehicle_type_code_5 + ) + end + end + private_class_method :import_soda3 end end From d1c4c79e6437c7cd8168dfcaac955599d2317aff Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Wed, 11 Feb 2026 09:01:11 -0500 Subject: [PATCH 11/14] add import for csv --- .../motor_vehicle_collisions_crash.rb | 75 ++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index a5bfe0e..0da885e 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -65,9 +65,9 @@ def self.import(api_version: '2', content_type: 'json') import_soda3 end - # if api_version == '3' && content_type == 'csv' - # import_soda3_csv - # end + if api_version == '3' && content_type == 'csv' + import_soda3_csv + end end def self.import_soda2 @@ -276,5 +276,74 @@ def self.import_soda3 end end private_class_method :import_soda3 + + def self.import_soda3_csv + csv = RemoteDataset::Soda3::Csv.new(remote_url: SODA3_CSV_API_ENDPOINT) + + csv.each do |row| + crash_date = row[0] + crash_time = row[1] + borough = row[2] + zip_code = row[3] + latitude = row[4] + longitude = row[5] + _location = row[6] + on_street_name = row[7] + off_street_name = row[8] + _cross_street_name = row[9] + number_of_persons_injured = row[10] + number_of_persons_killed = row[11] + number_of_pedestrians_injured = row[12] + number_of_pedestrians_killed = row[13] + number_of_cyclist_injured = row [14] + number_of_cyclist_killed = row[15] + number_of_motorist_injured = row[16] + number_of_motorist_killed = row[17] + contributing_factor_vehicle_1 = row[18] + contributing_factor_vehicle_2 = row[19] + contributing_factor_vehicle_3 = row[20] + contributing_factor_vehicle_4 = row[21] + contributing_factor_vehicle_5 = row[22] + collision_id = row[23] + vehicle_type_code1 = row[24] + vehicle_type_code2 = row[25] + vehicle_type_code_3 = row[26] + vehicle_type_code_4 = row[27] + vehicle_type_code_5 = row[28] + + next if MotorVehicleCollisionsCrash.find_by(collision_id: collision_id).present? + + MotorVehicleCollisionsCrash.create!( + crash_date: crash_date, + crash_time: crash_time, + borough: borough, + zip_code: zip_code, + latitude: latitude, + longitude: longitude, + on_street_name: on_street_name, + off_street_name: off_street_name, + number_of_persons_injured: number_of_persons_injured, + number_of_persons_killed: number_of_persons_killed, + number_of_pedestrians_injured: number_of_pedestrians_injured, + number_of_pedestrians_killed: number_of_pedestrians_killed, + number_of_cyclist_injured: number_of_cyclist_injured, + number_of_cyclist_killed: number_of_cyclist_killed, + number_of_motorist_injured: number_of_motorist_injured, + number_of_motorist_killed: number_of_motorist_killed, + contributing_factor_vehicle_1: contributing_factor_vehicle_1, + contributing_factor_vehicle_2: contributing_factor_vehicle_2, + contributing_factor_vehicle_3: contributing_factor_vehicle_3, + contributing_factor_vehicle_4: contributing_factor_vehicle_4, + contributing_factor_vehicle_5: contributing_factor_vehicle_5, + collision_id: collision_id, + vehicle_type_code1: vehicle_type_code1, + vehicle_type_code2: vehicle_type_code2, + vehicle_type_code_3: vehicle_type_code_3, + vehicle_type_code_4: vehicle_type_code_4, + vehicle_type_code_5: vehicle_type_code_5 + ) + end + end + private_class_method :import_soda3_csv end end From eb10e70827f33c28fc999f6eaac37735af77a9e2 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Wed, 11 Feb 2026 16:38:07 -0500 Subject: [PATCH 12/14] add cross_street_name to schema --- .../20260211012939_create_motor_vehicle_collisions_crashes.rb | 2 +- db/schema.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb b/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb index 70e02e7..09adfc7 100755 --- a/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb +++ b/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb @@ -9,7 +9,7 @@ def change t.decimal :longitude t.string :on_street_name t.string :off_street_name - # t.string :cross_street_name + t.string :cross_street_name t.integer :number_of_persons_injured t.integer :number_of_persons_killed t.integer :number_of_pedestrians_injured diff --git a/db/schema.rb b/db/schema.rb index 543127a..04e56de 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -38,6 +38,7 @@ t.decimal "longitude" t.string "on_street_name" t.string "off_street_name" + t.string "cross_street_name" t.integer "number_of_persons_injured" t.integer "number_of_persons_killed" t.integer "number_of_pedestrians_injured" From ff05cf88f3ea7f09954c006b1d41f9ba9fde7a78 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Wed, 11 Feb 2026 16:43:24 -0500 Subject: [PATCH 13/14] add location to schema --- .../20260211012939_create_motor_vehicle_collisions_crashes.rb | 1 + db/schema.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb b/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb index 09adfc7..6ffff5a 100755 --- a/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb +++ b/db/migrate/20260211012939_create_motor_vehicle_collisions_crashes.rb @@ -7,6 +7,7 @@ def change t.string :zip_code t.decimal :latitude t.decimal :longitude + t.jsonb :location t.string :on_street_name t.string :off_street_name t.string :cross_street_name diff --git a/db/schema.rb b/db/schema.rb index 04e56de..4043dd1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -36,6 +36,7 @@ t.string "zip_code" t.decimal "latitude" t.decimal "longitude" + t.jsonb "location" t.string "on_street_name" t.string "off_street_name" t.string "cross_street_name" From e0be1926b62398de6aff8b7078953b5c4b5e7226 Mon Sep 17 00:00:00 2001 From: dgonzdev Date: Wed, 11 Feb 2026 16:57:45 -0500 Subject: [PATCH 14/14] store location and cross street name --- .../motor_vehicle_collisions_crash.rb | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/app/models/police_department/motor_vehicle_collisions_crash.rb b/app/models/police_department/motor_vehicle_collisions_crash.rb index 0da885e..59e34b7 100644 --- a/app/models/police_department/motor_vehicle_collisions_crash.rb +++ b/app/models/police_department/motor_vehicle_collisions_crash.rb @@ -80,10 +80,10 @@ def self.import_soda2 zip_code = row["zip_code"] latitude = row["latitude"] longitude = row["longitude"] - _location = row["location"] + location = row["location"] on_street_name = row["on_street_name"] off_street_name = row["off_street_name"] - _cross_street_name = row["cross_street_name"] + cross_street_name = row["cross_street_name"] number_of_persons_injured = row["number_of_persons_injured"] number_of_persons_killed = row["number_of_persons_killed"] number_of_pedestrians_injured = row["number_of_pedestrians_injured"] @@ -113,8 +113,10 @@ def self.import_soda2 zip_code: zip_code, latitude: latitude, longitude: longitude, + location: location, on_street_name: on_street_name, off_street_name: off_street_name, + cross_street_name: cross_street_name, number_of_persons_injured: number_of_persons_injured, number_of_persons_killed: number_of_persons_killed, number_of_pedestrians_injured: number_of_pedestrians_injured, @@ -149,10 +151,10 @@ def self.import_soda2_csv zip_code = row[3] latitude = row[4] longitude = row[5] - _location = row[6] + location = row[6] on_street_name = row[7] off_street_name = row[8] - _cross_street_name = row[9] + cross_street_name = row[9] number_of_persons_injured = row[10] number_of_persons_killed = row[11] number_of_pedestrians_injured = row[12] @@ -182,8 +184,10 @@ def self.import_soda2_csv zip_code: zip_code, latitude: latitude, longitude: longitude, + location: location, on_street_name: on_street_name, off_street_name: off_street_name, + cross_street_name: cross_street_name, number_of_persons_injured: number_of_persons_injured, number_of_persons_killed: number_of_persons_killed, number_of_pedestrians_injured: number_of_pedestrians_injured, @@ -218,10 +222,10 @@ def self.import_soda3 zip_code = row["zip_code"] latitude = row["latitude"] longitude = row["longitude"] - _location = row["location"] + location = row["location"] on_street_name = row["on_street_name"] off_street_name = row["off_street_name"] - _cross_street_name = row["cross_street_name"] + cross_street_name = row["cross_street_name"] number_of_persons_injured = row["number_of_persons_injured"] number_of_persons_killed = row["number_of_persons_killed"] number_of_pedestrians_injured = row["number_of_pedestrians_injured"] @@ -251,8 +255,10 @@ def self.import_soda3 zip_code: zip_code, latitude: latitude, longitude: longitude, + location: location, on_street_name: on_street_name, off_street_name: off_street_name, + cross_street_name: cross_street_name, number_of_persons_injured: number_of_persons_injured, number_of_persons_killed: number_of_persons_killed, number_of_pedestrians_injured: number_of_pedestrians_injured, @@ -287,10 +293,10 @@ def self.import_soda3_csv zip_code = row[3] latitude = row[4] longitude = row[5] - _location = row[6] + location = row[6] on_street_name = row[7] off_street_name = row[8] - _cross_street_name = row[9] + cross_street_name = row[9] number_of_persons_injured = row[10] number_of_persons_killed = row[11] number_of_pedestrians_injured = row[12] @@ -320,8 +326,10 @@ def self.import_soda3_csv zip_code: zip_code, latitude: latitude, longitude: longitude, + location: location, on_street_name: on_street_name, off_street_name: off_street_name, + cross_street_name: cross_street_name, number_of_persons_injured: number_of_persons_injured, number_of_persons_killed: number_of_persons_killed, number_of_pedestrians_injured: number_of_pedestrians_injured,