Skip to content
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

homework #105

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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 .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
25 changes: 17 additions & 8 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,33 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.3'

gem 'rails', '~> 5.2.3'
gem 'activerecord-import'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'oj'
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 'bullet'
gem 'byebug', platforms: %i[mri mingw x64_mingw]
gem 'memory_profiler'
gem 'rspec-rails'
gem 'rspec-benchmark'
gem 'ruby-prof'
gem 'ruby-progressbar'
end

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

gem 'pghero'
gem 'pg_query', '>= 2'
gem 'rack-mini-profiler', require: false
group :test do
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]
68 changes: 67 additions & 1 deletion 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.5.0)
activerecord (>= 4.2)
activestorage (5.2.3)
actionpack (= 5.2.3)
activerecord (= 5.2.3)
Expand All @@ -43,17 +45,25 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
arel (9.0.0)
benchmark-malloc (0.2.0)
benchmark-perf (0.6.0)
benchmark-trend (0.4.0)
bindex (0.6.0)
bootsnap (1.4.2)
msgpack (~> 1.0)
builder (3.2.3)
bullet (7.1.3)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.0.1)
concurrent-ruby (1.1.5)
crass (1.0.4)
diff-lcs (1.5.0)
erubi (1.8.0)
ffi (1.10.0)
globalid (0.4.2)
activesupport (>= 4.2.0)
google-protobuf (3.23.4)
i18n (1.6.0)
concurrent-ruby (~> 1.0)
listen (3.1.5)
Expand All @@ -67,18 +77,33 @@ GEM
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
memory_profiler (1.0.1)
meta_request (0.7.4)
rack-contrib (>= 1.1, < 3)
railties (>= 3.0.0, < 7.1)
method_source (0.9.2)
mimemagic (0.3.3)
mimemagic (0.3.10)
nokogiri (~> 1)
rake
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)
oj (3.14.2)
pg (1.1.4)
pg_query (4.2.3)
google-protobuf (>= 3.22.3)
pghero (2.8.3)
activerecord (>= 5)
puma (3.12.1)
rack (2.0.6)
rack-contrib (2.4.0)
rack (< 4)
rack-mini-profiler (3.1.1)
rack (>= 1.2.0)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.3)
Expand Down Expand Up @@ -109,6 +134,34 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
rspec (3.12.0)
rspec-core (~> 3.12.0)
rspec-expectations (~> 3.12.0)
rspec-mocks (~> 3.12.0)
rspec-benchmark (0.6.0)
benchmark-malloc (~> 0.2)
benchmark-perf (~> 0.6)
benchmark-trend (~> 0.4)
rspec (>= 3.0)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-mocks (3.12.6)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-rails (5.1.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.12.1)
ruby-prof (1.4.3)
ruby-progressbar (1.13.0)
ruby_dep (1.5.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
Expand All @@ -121,6 +174,7 @@ GEM
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uniform_notifier (1.16.0)
web-console (3.7.0)
actionview (>= 5.0)
activemodel (>= 5.0)
Expand All @@ -134,12 +188,24 @@ PLATFORMS
ruby

DEPENDENCIES
activerecord-import
bootsnap (>= 1.1.0)
bullet
byebug
listen (>= 3.0.5, < 3.2)
memory_profiler
meta_request
oj
pg (>= 0.18, < 2.0)
pg_query (>= 2)
pghero
puma (~> 3.11)
rack-mini-profiler
rails (~> 5.2.3)
rspec-benchmark
rspec-rails
ruby-prof
ruby-progressbar
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: :services).where(from: @from, to: @to).order(:start_time).load
end
end
3 changes: 2 additions & 1 deletion app/models/bus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class Bus < ApplicationRecord
].freeze

has_many :trips
has_and_belongs_to_many :services, join_table: :buses_services
has_many :buses_services
has_many :services, through: :buses_services

validates :number, presence: true, uniqueness: true
validates :model, inclusion: { in: MODELS }
Expand Down
4 changes: 4 additions & 0 deletions app/models/buses_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class BusesService < ApplicationRecord
belongs_to :bus
belongs_to :service
end
5 changes: 3 additions & 2 deletions app/models/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ class Service < ApplicationRecord
'Телевизор общий',
'Телевизор индивидуальный',
'Стюардесса',
'Можно не печатать билет',
'Можно не печатать билет'
].freeze

has_and_belongs_to_many :buses, join_table: :buses_services
has_many :buses_services
has_many :buses, through: :buses_services

validates :name, presence: true
validates :name, inclusion: { in: SERVICES }
Expand Down
107 changes: 107 additions & 0 deletions app/services/reload_json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# frozen_string_literal: true

require 'oj'
class ReloadJson
Copy link
Collaborator

Choose a reason for hiding this comment

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

  • за отдельный класс

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
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.

21 changes: 16 additions & 5 deletions app/views/trips/_trip.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
<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.present? %>
<li>Сервисы в автобусе:</li>
<ul>
<% trip.bus.services.each do |service| %>
<li><%= "#{service.name}" %></li>
<% end %>
</ul>
<% end %>
</ul>
====================================================
12 changes: 2 additions & 10 deletions app/views/trips/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@
<%= "Автобусы #{@from.name} – #{@to.name}" %>
</h1>
<h2>
<%= "В расписании #{@trips.count} рейсов" %>
<%= "В расписании #{@trips.size} рейсов" %>
</h2>

<% @trips.each do |trip| %>
<ul>
<%= render "trip", trip: trip %>
<% if trip.bus.services.present? %>
<%= render "services", services: trip.bus.services %>
<% end %>
</ul>
<%= render "delimiter" %>
<% end %>
<%= render partial: 'trip', collection: @trips, as: :trip %>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Есть ещё забавная возможность задать разделитель параметром: https://guides.rubyonrails.org/layouts_and_rendering.html#spacer-templates

Loading