-
Notifications
You must be signed in to change notification settings - Fork 115
/
Copy pathreload_json.rb
107 lines (91 loc) · 3 KB
/
reload_json.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# frozen_string_literal: true
require 'oj'
class ReloadJson
def initialize(file_name)
@file_name = file_name
@cities = {}
@buses = {}
@buses_services = []
end
def call
ActiveRecord::Base.transaction do
clear_tables
create_services
@connection = ActiveRecord::Base.connection.raw_connection
trips_command =
"copy trips (from_id, to_id, start_time, duration_minutes, price_cents, bus_id) from stdin with csv delimiter ';'"
@connection.copy_data trips_command do
File.open(file_name) do |ff|
nesting = 0
str = String.new
until ff.eof?
ch = ff.read(1) # читаем по одному символу
if ch == '{' # начинается объект, повышается вложенность
nesting += 1
str << ch
elsif ch == '}' # заканчивается объект, понижается вложенность
nesting -= 1
str << ch
if nesting.zero? # если закончился объкет уровня trip, парсим и импортируем его
trip = Oj.load(str)
copy_trip(trip)
str = String.new
end
elsif nesting >= 1
str << ch
end
end
end
end
Bus.import buses.values
City.import cities.values
BusesService.import buses_services
end
end
private
attr_reader :cities, :buses, :buses_services, :services, :file_name
def create_services
services = []
Service::SERVICES.each do |name|
services << Service.new(name: name)
end
Service.import services
@services = Service.all.to_h { |service| [service.name, service.id] }
end
def clear_tables
City.delete_all
Bus.delete_all
Service.delete_all
Trip.delete_all
BusesService.delete_all
end
def copy_trip(trip)
from_id = cities.dig(trip['from'], 'id')
to_id = cities.dig(trip['to'], 'id')
service_ids = services.values_at(*trip['bus']['services'])
bus_key = "#{trip['bus']['model']} #{trip['bus']['number']}"
bus_id = buses.dig(bus_key, 'id')
unless from_id
id = cities.size + 1
cities[trip['from']] = { 'id' => id, 'name' => trip['from'] }
from_id = id
end
unless to_id
if cities[trip['from']] == @cities[trip['to']]
to_id = from_id
else
id = cities.size + 1
@cities[trip['to']] = { 'id' => id, 'name' => trip['to'] }
to_id = id
end
end
unless bus_id
id = buses.size + 1
buses[bus_key] =
{ 'id' => id, 'number' => trip['bus']['number'], 'model' => trip['bus']['model'] }
service_ids.each { |service_id| buses_services << { 'service_id' => service_id, 'bus_id' => id } }
bus_id = id
end
@connection.put_copy_data("#{from_id};#{to_id};#{trip['start_time']};#{trip['duration_minutes']};#{trip['price_cents']};#{bus_id}\n")
end
end