Skip to content

Task 3 solution #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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 @@ -2,3 +2,4 @@
/tmp
/log
/public
.byebug_history
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
15 changes: 15 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require:
- rubocop-rails
- rubocop-rspec
- rubocop-performance

AllCops:
NewCops: enable
Exclude:
- db/schema.rb
- db/migrate/**/*
- config/**/*
- bin/**/*

Style/Documentation:
Enabled: false
27 changes: 17 additions & 10 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
# frozen_string_literal: true

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.3'

gem 'rails', '~> 5.2.3'
gem 'activerecord-import', require: false
gem 'bootsnap', '>= 1.1.0', require: false
gem 'mimemagic', github: 'mimemagicrb/mimemagic', ref: '01f92d86d15d85cfd0f20dabd025dcbd36a8a60f'
gem 'pg', '>= 0.18', '< 2.0'
gem 'puma', '~> 3.11'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'rails', '~> 5.2.3'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'byebug', platforms: %i[mri mingw x64_mingw]
gem 'rack-mini-profiler'
end

group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0'
gem 'bullet'
gem 'listen', '>= 3.0.5', '< 3.2'
end

group :test do
gem 'meta_request'
gem 'rspec-rails'
gem 'rubocop', require: false
gem 'rubocop-performance', require: false
gem 'rubocop-rails', require: false
gem 'rubocop-rspec', require: false
gem 'web-console', '>= 3.3.0'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
78 changes: 77 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
GIT
remote: https://github.com/mimemagicrb/mimemagic.git
revision: 01f92d86d15d85cfd0f20dabd025dcbd36a8a60f
ref: 01f92d86d15d85cfd0f20dabd025dcbd36a8a60f
specs:
mimemagic (0.3.5)

GEM
remote: https://rubygems.org/
specs:
Expand Down Expand Up @@ -33,6 +40,8 @@ GEM
activemodel (= 5.2.3)
activesupport (= 5.2.3)
arel (>= 9.0)
activerecord-import (1.2.0)
activerecord (>= 3.2)
activestorage (5.2.3)
actionpack (= 5.2.3)
activerecord (= 5.2.3)
Expand All @@ -43,13 +52,18 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
arel (9.0.0)
ast (2.4.2)
bindex (0.6.0)
bootsnap (1.4.2)
msgpack (~> 1.0)
builder (3.2.3)
bullet (6.1.5)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.0.1)
concurrent-ruby (1.1.5)
crass (1.0.4)
diff-lcs (1.4.4)
erubi (1.8.0)
ffi (1.10.0)
globalid (0.4.2)
Expand All @@ -67,18 +81,27 @@ GEM
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
meta_request (0.7.3)
rack-contrib (>= 1.1, < 3)
railties (>= 3.0.0, < 7)
method_source (0.9.2)
mimemagic (0.3.3)
mini_mime (1.0.1)
mini_portile2 (2.4.0)
minitest (5.11.3)
msgpack (1.2.9)
nio4r (2.3.1)
nokogiri (1.10.2)
mini_portile2 (~> 2.4.0)
parallel (1.21.0)
parser (3.0.2.0)
ast (~> 2.4.1)
pg (1.1.4)
puma (3.12.1)
rack (2.0.6)
rack-contrib (2.3.0)
rack (~> 2.0)
rack-mini-profiler (2.3.3)
rack (>= 1.2.0)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.3)
Expand All @@ -105,10 +128,51 @@ GEM
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
rainbow (3.0.0)
rake (12.3.2)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
regexp_parser (2.1.1)
rexml (3.1.9)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-rails (5.0.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
railties (>= 5.2)
rspec-core (~> 3.10)
rspec-expectations (~> 3.10)
rspec-mocks (~> 3.10)
rspec-support (~> 3.10)
rspec-support (3.10.2)
rubocop (1.22.1)
parallel (~> 1.10)
parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.12.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.12.0)
parser (>= 3.0.1.1)
rubocop-performance (1.11.5)
rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.12.4)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.7.0, < 2.0)
rubocop-rspec (2.5.0)
rubocop (~> 1.19)
ruby-progressbar (1.11.0)
ruby_dep (1.5.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
Expand All @@ -121,6 +185,8 @@ GEM
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
unicode-display_width (2.1.0)
uniform_notifier (1.14.2)
web-console (3.7.0)
actionview (>= 5.0)
activemodel (>= 5.0)
Expand All @@ -134,12 +200,22 @@ PLATFORMS
ruby

DEPENDENCIES
activerecord-import
bootsnap (>= 1.1.0)
bullet
byebug
listen (>= 3.0.5, < 3.2)
meta_request
mimemagic!
pg (>= 0.18, < 2.0)
puma (~> 3.11)
rack-mini-profiler
rails (~> 5.2.3)
rspec-rails
rubocop
rubocop-performance
rubocop-rails
rubocop-rspec
tzinfo-data
web-console (>= 3.3.0)

Expand Down
22 changes: 17 additions & 5 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,31 @@
В этом задании вам предлагается оптимизировать учебное `rails`-приложение.

Для запуска потребуется:

- `ruby 2.6.3`
- `postgres`

Запуск и использование:

- `bundle install`
- `bin/setup`
- `rails s`
- `open http://localhost:3000/автобусы/Самара/Москва`

## Описание учебного приложения

Зайдя на страницу `автобусы/Самара/Москва` вы увидите расписание автобусов по этому направлению.

## Что оптимизировать

### A. Импорт данных

При выполнении `bin/setup` в базу данных загружаются данные о рейсах из файла `fixtures/small.json`

Сама загрузка данных из файла делается очень наивно (и не эффективно).

В комплекте с заданием поставляются файлы

- `example.json`
- `small.json` (1K трипов)
- `medium.json` (10K трипов)
Expand All @@ -33,25 +38,30 @@
`rake reload_json[fixtures/large.json]`

Для импорта этого объёма данных

- вам может помочь гем https://github.com/zdennis/activerecord-import
- избегайте создания лишних транзакций
- профилируйте скрипт импорта изученными инструментами и оптимизируйте его!

### Б. Отображение расписаний

Сами страницы расписаний тоже формируются не эффективно и при росте объёмов начинают сильно тормозить.

Нужно найти и устранить проблемы, замедляющие формирование этих страниц.

Попробуйте воспользоваться
- [ ] `rack-mini-profiler`
- [ ] `rails panel`
- [ ] `bullet`
- [ ] `explain` запросов

- [x] `rack-mini-profiler`
- [x] `rails panel`
- [x] `bullet`
- [x] `explain` запросов

### Сдача задания

`PR` в этот репозиторий с кодом и case-study наподобие первых двух недель. На этот раз шаблона нет, законспектируйте ваш процесс оптимизации в свободной форме.

В case-study указать:

- за какое время выполняется импорт файла `fixtures/large.json`
- за какое время рендерится страница `автобусы/Самара/Москва`

Expand All @@ -60,7 +70,8 @@
Лучше защититься от такой регрессии тестом.

### bonus
*Советую приступать к бонусу только после завершения основной части ДЗ.*

_Советую приступать к бонусу только после завершения основной части ДЗ._

В качестве бонуса нужно справиться с импортом файлов `1M.json` (`codename mega`) и `10M.json` (`codename hardcore`)

Expand All @@ -72,6 +83,7 @@
### Мета-информация о данных

При реализации импорта нужно учесть наши инсайдерские знания о данных:

- первичным ключом для автобуса считаем `(model, number)`
- уникальных автобусов в файле `10M.json` ~ `10_000`
- ункикльных городов в файле `10M.json` ~ `100`
Expand Down
8 changes: 5 additions & 3 deletions app/controllers/trips_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# frozen_string_literal: true

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)
@from = City.find_by!(name: params[:from])
@to = City.find_by!(name: params[:to])
@trips = Trip.where(from: @from, to: @to).includes(bus: %i[buses_services services]).order(:start_time)
end
end
24 changes: 13 additions & 11 deletions app/models/bus.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# frozen_string_literal: true

class Bus < ApplicationRecord
MODELS = [
'Икарус',
'Мерседес',
'Сканиа',
'Буханка',
'УАЗ',
'Спринтер',
'ГАЗ',
'ПАЗ',
'Вольво',
'Газель',
MODELS = %w[
Икарус
Мерседес
Сканиа
Буханка
УАЗ
Спринтер
ГАЗ
ПАЗ
Вольво
Газель
].freeze

has_many :trips
Expand Down
4 changes: 3 additions & 1 deletion app/models/service.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

class Service < ApplicationRecord
SERVICES = [
'WiFi',
Expand All @@ -9,7 +11,7 @@ class Service < ApplicationRecord
'Телевизор общий',
'Телевизор индивидуальный',
'Стюардесса',
'Можно не печатать билет',
'Можно не печатать билет'
].freeze

has_and_belongs_to_many :buses, join_table: :buses_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.

22 changes: 17 additions & 5 deletions app/views/trips/_trip.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
<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>
<ul>
<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>

<% if trip.bus.services.any? %>
<li>Сервисы в автобусе:</li>
<ul>
<% trip.bus.services.each do |service| %>
<li><%= "#{service.name}" %></li>
<% end %>
</ul>
<% end %>
</ul>
====================================================
Loading