Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@

# Ignore master key for decrypting credentials and more.
/config/master.key
/config/skylight.yml
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ gem 'rails', '~> 5.2.3'
gem 'pg', '>= 0.18', '< 2.0'
gem 'puma', '~> 3.11'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'pghero'
gem 'pg_query', '>= 0.9.0'
gem 'skylight'
gem 'activerecord-import'
gem 'strong_migrations'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
Expand Down
22 changes: 19 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ GEM
activemodel (= 5.2.3)
activesupport (= 5.2.3)
arel (>= 9.0)
activerecord-import (1.0.1)
activerecord (>= 3.2)
activestorage (5.2.3)
actionpack (= 5.2.3)
activerecord (= 5.2.3)
Expand All @@ -43,8 +45,8 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
arel (9.0.0)
bindex (0.6.0)
bootsnap (1.4.2)
bindex (0.7.0)
bootsnap (1.4.3)
msgpack (~> 1.0)
builder (3.2.3)
byebug (11.0.1)
Expand Down Expand Up @@ -77,8 +79,11 @@ GEM
nokogiri (1.10.2)
mini_portile2 (~> 2.4.0)
pg (1.1.4)
pg_query (1.1.0)
pghero (2.2.0)
activerecord
puma (3.12.1)
rack (2.0.6)
rack (2.0.7)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.3)
Expand Down Expand Up @@ -110,13 +115,19 @@ GEM
rb-inotify (0.10.0)
ffi (~> 1.0)
ruby_dep (1.5.0)
skylight (3.1.5)
skylight-core (= 3.1.5)
skylight-core (3.1.5)
activesupport (>= 4.2.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
strong_migrations (0.3.1)
activerecord (>= 3.2.0)
thor (0.20.3)
thread_safe (0.3.6)
tzinfo (1.2.5)
Expand All @@ -134,12 +145,17 @@ PLATFORMS
ruby

DEPENDENCIES
activerecord-import
bootsnap (>= 1.1.0)
byebug
listen (>= 3.0.5, < 3.2)
pg (>= 0.18, < 2.0)
pg_query (>= 0.9.0)
pghero
puma (~> 3.11)
rails (~> 5.2.3)
skylight
strong_migrations
tzinfo-data
web-console (>= 3.3.0)

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/trips_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ class TripsController < ApplicationController
def index
@from = City.find_by_name!(params[:from])
@to = City.find_by_name!(params[:to])
@trips = Trip.where(from: @from, to: @to).order(:start_time)
@trips = Trip.includes(:bus, bus: :services).where(from: @from, to: @to).order(:start_time)
end
end
2 changes: 1 addition & 1 deletion app/models/bus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Bus < ApplicationRecord
].freeze

has_many :trips
has_and_belongs_to_many :services, join_table: :buses_services
has_and_belongs_to_many :services, join_table: :buses_services, autosave: true

validates :number, presence: true, uniqueness: true
validates :model, inclusion: { in: MODELS }
Expand Down
2 changes: 1 addition & 1 deletion app/models/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Service < ApplicationRecord
'Можно не печатать билет',
].freeze

has_and_belongs_to_many :buses, join_table: :buses_services
has_and_belongs_to_many :buses, join_table: :buses_services, autosave: true

validates :name, presence: true
validates :name, inclusion: { in: SERVICES }
Expand Down
1 change: 0 additions & 1 deletion app/views/trips/_delimiter.html.erb

This file was deleted.

1 change: 0 additions & 1 deletion app/views/trips/_service.html.erb

This file was deleted.

6 changes: 0 additions & 6 deletions app/views/trips/_services.html.erb

This file was deleted.

5 changes: 0 additions & 5 deletions app/views/trips/_trip.html.erb

This file was deleted.

22 changes: 16 additions & 6 deletions app/views/trips/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,23 @@
<h2>
<%= "В расписании #{@trips.count} рейсов" %>
</h2>

<% @trips.each do |trip| %>
<% @trips.each do |trip|%>
<ul>
<%= render "trip", trip: trip %>
<% if trip.bus.services.present? %>
<%= render "services", services: trip.bus.services %>
<li><%= "Отправление: #{trip.start_time}" %></li>
<li><%= "Прибытие: #{(Time.parse(trip.start_time) + trip.duration_minutes.minutes).strftime('%H:%M')}" %></li>
<li><%= "В пути: #{trip.duration_minutes / 60}ч. #{trip.duration_minutes % 60}мин." %></li>
<li><%= "Цена: #{trip.price_cents / 100}р. #{trip.price_cents % 100}коп." %></li>
<li><%= "Автобус: #{trip.bus.model} №#{trip.bus.number}" %></li>

<% services = trip.bus.services %>
<% if services.any? %>
<li>Сервисы в автобусе:</li>
<ul>
<% services.each do |service|%>
<li><%= "#{service.name}" %></li>
<%end%>
</ul>
<% end %>
</ul>
<%= render "delimiter" %>
====================================================
<% end %>
5 changes: 1 addition & 4 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.2

# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
config.skylight.environments += ["development"]
end
end
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
# mount PgHero::Engine, at: 'pghero'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get "/" => "statistics#index"
get "автобусы/:from/:to" => "trips#index"
Expand Down
7 changes: 7 additions & 0 deletions db/migrate/20190412192616_add_trip_indices.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddTripIndices < ActiveRecord::Migration[5.2]
disable_ddl_transaction!

def change
add_index :trips, [:from_id, :to_id], algorithm: :concurrently
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Плюсик за concurrently

end
end
7 changes: 7 additions & 0 deletions db/migrate/20190412195139_add_bus_index.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddBusIndex < ActiveRecord::Migration[5.2]
disable_ddl_transaction!

def change
add_index :buses, :number, algorithm: :concurrently
end
end
7 changes: 7 additions & 0 deletions db/migrate/20190412203601_add_bus_service_indices.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddBusServiceIndices < ActiveRecord::Migration[5.2]
disable_ddl_transaction!

def change
add_index :buses_services, [:bus_id, :service_id], algorithm: :concurrently
end
end
6 changes: 5 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,26 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2019_03_30_193044) do
ActiveRecord::Schema.define(version: 2019_04_12_211708) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

create_table "buses", force: :cascade do |t|
t.string "number"
t.string "model"
t.index ["number"], name: "index_buses_on_number"
end

create_table "buses_services", force: :cascade do |t|
t.integer "bus_id"
t.integer "service_id"
t.index ["bus_id", "service_id"], name: "index_buses_services_on_bus_id_and_service_id"
end

create_table "cities", force: :cascade do |t|
t.string "name"
t.index ["name"], name: "index_cities_on_name"
end

create_table "services", force: :cascade do |t|
Expand All @@ -40,6 +43,7 @@
t.integer "duration_minutes"
t.integer "price_cents"
t.integer "bus_id"
t.index ["from_id", "to_id"], name: "index_trips_on_from_id_and_to_id"
end

end
97 changes: 70 additions & 27 deletions lib/tasks/utils.rake
Original file line number Diff line number Diff line change
@@ -1,34 +1,77 @@
# Наивная загрузка данных из json-файла в БД
# rake reload_json[fixtures/small.json]
require 'benchmark'

def create_services
new_services = []
all_services = Service.const_get('SERVICES').each_with_object({}) do |name, result|
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Service::SERVICES?

new_services << result[name] = Service.new(name: name)
end
Service.import(new_services)
all_services
end

def create_cities(data)
uniq_cities = data.each_with_object([]) do |trip, result|
result << trip['from']
result << trip['to']
end.uniq
new_cities = []
all_cities = uniq_cities.each_with_object({}) do |name, result|
new_cities << result[name] = City.new(name: name)
end
City.import(new_cities)
all_cities
end

def create_buses(data, all_services)
new_buses = []
all_buses = data.each_with_object({}) do |trip, result|
next if result[trip['bus']['number']]

services = trip['bus']['services'].map {|service| all_services[service] }
new_buses << result[trip['bus']['number']] = Bus.new(
number: trip['bus']['number'],
model: trip['bus']['model'],
services: services
)
end
#Bus.import(new_buses)
new_buses.each(&:save!)
all_buses
end

task :reload_json, [:file_name] => :environment do |_task, args|
json = JSON.parse(File.read(args.file_name))

ActiveRecord::Base.transaction do
City.delete_all
Bus.delete_all
Service.delete_all
Trip.delete_all
ActiveRecord::Base.connection.execute('delete from buses_services;')

json.each do |trip|
from = City.find_or_create_by(name: trip['from'])
to = City.find_or_create_by(name: trip['to'])
services = []
trip['bus']['services'].each do |service|
s = Service.find_or_create_by(name: service)
services << s
time = Benchmark.realtime do
json = JSON.parse(File.read(args.file_name))

ActiveRecord::Base.transaction do
City.delete_all
Bus.delete_all
Service.delete_all
Trip.delete_all
ActiveRecord::Base.connection.execute('delete from buses_services;')

all_services = create_services
all_cities = create_cities(json)
all_buses = create_buses(json, all_services)

new_records = json.map do |trip|
from = all_cities[trip['from']]
to = all_cities[trip['to']]
bus = all_buses[trip['bus']['number']]

Trip.new(
from: from,
to: to,
bus: bus,
start_time: trip['start_time'],
duration_minutes: trip['duration_minutes'],
price_cents: trip['price_cents'],
)
end
bus = Bus.find_or_create_by(number: trip['bus']['number'])
bus.update(model: trip['bus']['model'], services: services)

Trip.create!(
from: from,
to: to,
bus: bus,
start_time: trip['start_time'],
duration_minutes: trip['duration_minutes'],
price_cents: trip['price_cents'],
)
Trip.import(new_records)
end
end
puts "Finish in #{time.round(2)}"
end