From e19f2e05a96ddb7df62ed3f7183c5a993d5e615a Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Mon, 15 Apr 2019 14:58:56 -0700 Subject: [PATCH 01/49] Ran rails new --- .gitignore | 30 ++ .ruby-version | 1 + Gemfile | 81 ++++++ Gemfile.lock | 274 ++++++++++++++++++ Guardfile | 9 + Rakefile | 6 + app/assets/config/manifest.js | 3 + app/assets/images/.keep | 0 app/assets/javascripts/application.js | 16 + app/assets/javascripts/cable.js | 13 + app/assets/javascripts/channels/.keep | 0 app/assets/stylesheets/application.css | 15 + app/channels/application_cable/channel.rb | 4 + app/channels/application_cable/connection.rb | 4 + app/controllers/application_controller.rb | 2 + app/controllers/concerns/.keep | 0 app/helpers/application_helper.rb | 2 + app/jobs/application_job.rb | 2 + app/mailers/application_mailer.rb | 4 + app/models/application_record.rb | 3 + app/models/concerns/.keep | 0 app/views/layouts/application.html.erb | 15 + app/views/layouts/mailer.html.erb | 13 + app/views/layouts/mailer.text.erb | 1 + bin/bundle | 3 + bin/rails | 9 + bin/rake | 9 + bin/setup | 36 +++ bin/spring | 17 ++ bin/update | 31 ++ bin/yarn | 11 + config.ru | 5 + config/application.rb | 26 ++ config/boot.rb | 4 + config/cable.yml | 10 + config/credentials.yml.enc | 1 + config/database.yml | 85 ++++++ config/environment.rb | 5 + config/environments/development.rb | 61 ++++ config/environments/production.rb | 94 ++++++ config/environments/test.rb | 46 +++ config/initializers/action_view.rb | 1 + .../application_controller_renderer.rb | 8 + config/initializers/assets.rb | 14 + config/initializers/backtrace_silencers.rb | 7 + .../initializers/content_security_policy.rb | 25 ++ config/initializers/cookies_serializer.rb | 5 + .../initializers/filter_parameter_logging.rb | 4 + config/initializers/inflections.rb | 16 + config/initializers/mime_types.rb | 4 + config/initializers/wrap_parameters.rb | 14 + config/locales/en.yml | 33 +++ config/puma.rb | 34 +++ config/routes.rb | 3 + config/spring.rb | 6 + config/storage.yml | 34 +++ lib/assets/.keep | 0 lib/tasks/.keep | 0 log/.keep | 0 package.json | 5 + public/404.html | 67 +++++ public/422.html | 67 +++++ public/500.html | 66 +++++ public/apple-touch-icon-precomposed.png | 0 public/apple-touch-icon.png | 0 public/favicon.ico | 0 public/robots.txt | 1 + storage/.keep | 0 test/application_system_test_case.rb | 5 + test/controllers/.keep | 0 test/fixtures/.keep | 0 test/fixtures/files/.keep | 0 test/helpers/.keep | 0 test/integration/.keep | 0 test/mailers/.keep | 0 test/models/.keep | 0 test/system/.keep | 0 test/test_helper.rb | 26 ++ tmp/.keep | 0 vendor/.keep | 0 80 files changed, 1396 insertions(+) create mode 100644 .gitignore create mode 100644 .ruby-version create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Guardfile create mode 100644 Rakefile create mode 100644 app/assets/config/manifest.js create mode 100644 app/assets/images/.keep create mode 100644 app/assets/javascripts/application.js create mode 100644 app/assets/javascripts/cable.js create mode 100644 app/assets/javascripts/channels/.keep create mode 100644 app/assets/stylesheets/application.css create mode 100644 app/channels/application_cable/channel.rb create mode 100644 app/channels/application_cable/connection.rb create mode 100644 app/controllers/application_controller.rb create mode 100644 app/controllers/concerns/.keep create mode 100644 app/helpers/application_helper.rb create mode 100644 app/jobs/application_job.rb create mode 100644 app/mailers/application_mailer.rb create mode 100644 app/models/application_record.rb create mode 100644 app/models/concerns/.keep create mode 100644 app/views/layouts/application.html.erb create mode 100644 app/views/layouts/mailer.html.erb create mode 100644 app/views/layouts/mailer.text.erb create mode 100755 bin/bundle create mode 100755 bin/rails create mode 100755 bin/rake create mode 100755 bin/setup create mode 100755 bin/spring create mode 100755 bin/update create mode 100755 bin/yarn create mode 100644 config.ru create mode 100644 config/application.rb create mode 100644 config/boot.rb create mode 100644 config/cable.yml create mode 100644 config/credentials.yml.enc create mode 100644 config/database.yml create mode 100644 config/environment.rb create mode 100644 config/environments/development.rb create mode 100644 config/environments/production.rb create mode 100644 config/environments/test.rb create mode 100644 config/initializers/action_view.rb create mode 100644 config/initializers/application_controller_renderer.rb create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/backtrace_silencers.rb create mode 100644 config/initializers/content_security_policy.rb create mode 100644 config/initializers/cookies_serializer.rb create mode 100644 config/initializers/filter_parameter_logging.rb create mode 100644 config/initializers/inflections.rb create mode 100644 config/initializers/mime_types.rb create mode 100644 config/initializers/wrap_parameters.rb create mode 100644 config/locales/en.yml create mode 100644 config/puma.rb create mode 100644 config/routes.rb create mode 100644 config/spring.rb create mode 100644 config/storage.yml create mode 100644 lib/assets/.keep create mode 100644 lib/tasks/.keep create mode 100644 log/.keep create mode 100644 package.json create mode 100644 public/404.html create mode 100644 public/422.html create mode 100644 public/500.html create mode 100644 public/apple-touch-icon-precomposed.png create mode 100644 public/apple-touch-icon.png create mode 100644 public/favicon.ico create mode 100644 public/robots.txt create mode 100644 storage/.keep create mode 100644 test/application_system_test_case.rb create mode 100644 test/controllers/.keep create mode 100644 test/fixtures/.keep create mode 100644 test/fixtures/files/.keep create mode 100644 test/helpers/.keep create mode 100644 test/integration/.keep create mode 100644 test/mailers/.keep create mode 100644 test/models/.keep create mode 100644 test/system/.keep create mode 100644 test/test_helper.rb create mode 100644 tmp/.keep create mode 100644 vendor/.keep diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..11a546eaa --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# Ignore uploaded files in development +/storage/* +!/storage/.keep + +/node_modules +/yarn-error.log + +/public/assets +.byebug_history +/coverage +.DS_Store + + +# Ignore master key for decrypting credentials and more. +/config/master.key diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 000000000..25c81fe39 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +ruby-2.5.1 \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..e665f46d3 --- /dev/null +++ b/Gemfile @@ -0,0 +1,81 @@ +source 'https://rubygems.org' +git_source(:github) { |repo| "https://github.com/#{repo}.git" } + +ruby '2.5.1' + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 5.2.3' +# Use postgresql as the database for Active Record +gem 'pg', '>= 0.18', '< 2.0' +# Use Puma as the app server +gem 'puma', '~> 3.11' +# Use SCSS for stylesheets +gem 'sass-rails', '~> 5.0' +# Use Uglifier as compressor for JavaScript assets +gem 'uglifier', '>= 1.3.0' +# See https://github.com/rails/execjs#readme for more supported runtimes +# gem 'mini_racer', platforms: :ruby + +# Use CoffeeScript for .coffee assets and views +# gem 'coffee-rails', '~> 4.2' +# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks +gem 'turbolinks', '~> 5' +# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder +gem 'jbuilder', '~> 2.5' +# Use Redis adapter to run Action Cable in production +# gem 'redis', '~> 4.0' +# Use ActiveModel has_secure_password +# gem 'bcrypt', '~> 3.1.7' + +# Use ActiveStorage variant +# gem 'mini_magick', '~> 4.8' + +# Use Capistrano for deployment +# gem 'capistrano-rails', group: :development + +# Reduces boot times through caching; required in config/boot.rb +gem 'bootsnap', '>= 1.1.0', require: false + +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] +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 'listen', '>= 3.0.5', '< 3.2' + # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring + gem 'spring' + gem 'spring-watcher-listen', '~> 2.0.0' +end + +group :test do + # Adds support for Capybara system testing and selenium driver + gem 'capybara', '>= 2.15' + gem 'selenium-webdriver' + # Easy installation and use of chromedriver to run system tests with Chrome + gem 'chromedriver-helper' +end + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] + +gem 'jquery-turbolinks' +gem 'jquery-rails' +group :development, :test do + gem 'pry-rails' +end + +group :development do + gem 'better_errors' + gem 'binding_of_caller' + gem 'guard' + gem 'guard-minitest' +end + +group :test do + gem 'minitest-rails' + gem 'minitest-reporters' + gem 'minitest-skip' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..a98c85111 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,274 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.2.3) + actionpack (= 5.2.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.3) + actionpack (= 5.2.3) + actionview (= 5.2.3) + activejob (= 5.2.3) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.2.3) + actionview (= 5.2.3) + activesupport (= 5.2.3) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.2.3) + activesupport (= 5.2.3) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.2.3) + activesupport (= 5.2.3) + globalid (>= 0.3.6) + activemodel (5.2.3) + activesupport (= 5.2.3) + activerecord (5.2.3) + activemodel (= 5.2.3) + activesupport (= 5.2.3) + arel (>= 9.0) + activestorage (5.2.3) + actionpack (= 5.2.3) + activerecord (= 5.2.3) + marcel (~> 0.3.1) + activesupport (5.2.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.6.0) + public_suffix (>= 2.0.2, < 4.0) + ansi (1.5.0) + archive-zip (0.12.0) + io-like (~> 0.3.0) + arel (9.0.0) + better_errors (2.5.1) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + bindex (0.7.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + bootsnap (1.4.3) + msgpack (~> 1.0) + builder (3.2.3) + byebug (11.0.1) + capybara (3.16.2) + addressable + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (~> 1.2) + xpath (~> 3.2) + childprocess (0.9.0) + ffi (~> 1.0, >= 1.0.11) + chromedriver-helper (2.1.1) + archive-zip (~> 0.10) + nokogiri (~> 1.8) + coderay (1.1.2) + concurrent-ruby (1.1.5) + crass (1.0.4) + debug_inspector (0.0.3) + erubi (1.8.0) + execjs (2.7.0) + ffi (1.10.0) + formatador (0.2.5) + globalid (0.4.2) + activesupport (>= 4.2.0) + guard (2.15.0) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-minitest (2.4.6) + guard-compat (~> 1.2) + minitest (>= 3.0) + i18n (1.6.0) + concurrent-ruby (~> 1.0) + io-like (0.3.0) + jbuilder (2.8.0) + activesupport (>= 4.2.0) + multi_json (>= 1.2) + jquery-rails (4.3.3) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + jquery-turbolinks (2.1.0) + railties (>= 3.1.0) + turbolinks + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + loofah (2.2.3) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + lumberjack (1.0.13) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) + method_source (0.9.2) + mimemagic (0.3.3) + mini_mime (1.0.1) + mini_portile2 (2.4.0) + minitest (5.11.3) + minitest-rails (3.0.0) + minitest (~> 5.8) + railties (~> 5.0) + minitest-reporters (1.3.6) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + minitest-skip (0.0.1) + minitest (~> 5.0) + msgpack (1.2.9) + multi_json (1.13.1) + nenv (0.3.0) + nio4r (2.3.1) + nokogiri (1.10.2) + mini_portile2 (~> 2.4.0) + notiffany (0.1.1) + nenv (~> 0.1) + shellany (~> 0.0) + pg (1.1.4) + pry (0.12.2) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-rails (0.3.9) + pry (>= 0.10.4) + public_suffix (3.0.3) + puma (3.12.1) + rack (2.0.7) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.3) + actioncable (= 5.2.3) + actionmailer (= 5.2.3) + actionpack (= 5.2.3) + actionview (= 5.2.3) + activejob (= 5.2.3) + activemodel (= 5.2.3) + activerecord (= 5.2.3) + activestorage (= 5.2.3) + activesupport (= 5.2.3) + bundler (>= 1.3.0) + railties (= 5.2.3) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) + railties (5.2.3) + actionpack (= 5.2.3) + activesupport (= 5.2.3) + method_source + rake (>= 0.8.7) + thor (>= 0.19.0, < 2.0) + rake (12.3.2) + rb-fsevent (0.10.3) + rb-inotify (0.10.0) + ffi (~> 1.0) + regexp_parser (1.4.0) + ruby-progressbar (1.10.0) + ruby_dep (1.5.0) + rubyzip (1.2.2) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + selenium-webdriver (3.141.0) + childprocess (~> 0.5) + rubyzip (~> 1.2, >= 1.2.2) + shellany (0.0.1) + spring (2.0.2) + activesupport (>= 4.2) + spring-watcher-listen (2.0.1) + listen (>= 2.7, < 4.0) + spring (>= 1.2, < 3.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) + thor (0.20.3) + thread_safe (0.3.6) + tilt (2.0.9) + turbolinks (5.2.0) + turbolinks-source (~> 5.2) + turbolinks-source (5.2.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.1.20) + execjs (>= 0.3.0, < 3) + web-console (3.7.0) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) + websocket-driver (0.7.0) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + xpath (3.2.0) + nokogiri (~> 1.8) + +PLATFORMS + ruby + +DEPENDENCIES + better_errors + binding_of_caller + bootsnap (>= 1.1.0) + byebug + capybara (>= 2.15) + chromedriver-helper + guard + guard-minitest + jbuilder (~> 2.5) + jquery-rails + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + minitest-skip + pg (>= 0.18, < 2.0) + pry-rails + puma (~> 3.11) + rails (~> 5.2.3) + sass-rails (~> 5.0) + selenium-webdriver + spring + spring-watcher-listen (~> 2.0.0) + turbolinks (~> 5) + tzinfo-data + uglifier (>= 1.3.0) + web-console (>= 3.3.0) + +RUBY VERSION + ruby 2.5.1p57 + +BUNDLED WITH + 1.17.3 diff --git a/Guardfile b/Guardfile new file mode 100644 index 000000000..e34f706f4 --- /dev/null +++ b/Guardfile @@ -0,0 +1,9 @@ +guard :minitest, autorun: false, spring: true do + watch(%r{^app/(.+).rb$}) { |m| "test/#{m[1]}_test.rb" } + watch(%r{^app/controllers/application_controller.rb$}) { 'test/controllers' } + watch(%r{^app/controllers/(.+)_controller.rb$}) { |m| "test/integration/#{m[1]}_test.rb" } + watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" } + watch(%r{^lib/(.+).rb$}) { |m| "test/lib/#{m[1]}_test.rb" } + watch(%r{^test/.+_test.rb$}) + watch(%r{^test/test_helper.rb$}) { 'test' } +end diff --git a/Rakefile b/Rakefile new file mode 100644 index 000000000..e85f91391 --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative 'config/application' + +Rails.application.load_tasks diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 000000000..b16e53d6d --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,3 @@ +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css diff --git a/app/assets/images/.keep b/app/assets/images/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 000000000..82e6f0f6c --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,16 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's +// vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require rails-ujs +//= require activestorage +//= require turbolinks +//= require_tree . diff --git a/app/assets/javascripts/cable.js b/app/assets/javascripts/cable.js new file mode 100644 index 000000000..739aa5f02 --- /dev/null +++ b/app/assets/javascripts/cable.js @@ -0,0 +1,13 @@ +// Action Cable provides the framework to deal with WebSockets in Rails. +// You can generate new channels where WebSocket features live using the `rails generate channel` command. +// +//= require action_cable +//= require_self +//= require_tree ./channels + +(function() { + this.App || (this.App = {}); + + App.cable = ActionCable.createConsumer(); + +}).call(this); diff --git a/app/assets/javascripts/channels/.keep b/app/assets/javascripts/channels/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 000000000..d05ea0f51 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's + * vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 000000000..d67269728 --- /dev/null +++ b/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb new file mode 100644 index 000000000..0ff5442f4 --- /dev/null +++ b/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 000000000..09705d12a --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,2 @@ +class ApplicationController < ActionController::Base +end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 000000000..de6be7945 --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 000000000..a009ace51 --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,2 @@ +class ApplicationJob < ActiveJob::Base +end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 000000000..286b2239d --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 000000000..10a4cba84 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 000000000..692ca547e --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,15 @@ + + + + RideShareRails + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 000000000..cbd34d2e9 --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 000000000..37f0bddbd --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 000000000..f19acf5b5 --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails new file mode 100755 index 000000000..5badb2fde --- /dev/null +++ b/bin/rails @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +begin + load File.expand_path('../spring', __FILE__) +rescue LoadError => e + raise unless e.message.include?('spring') +end +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake new file mode 100755 index 000000000..d87d5f578 --- /dev/null +++ b/bin/rake @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +begin + load File.expand_path('../spring', __FILE__) +rescue LoadError => e + raise unless e.message.include?('spring') +end +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/bin/setup b/bin/setup new file mode 100755 index 000000000..94fd4d797 --- /dev/null +++ b/bin/setup @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/spring b/bin/spring new file mode 100755 index 000000000..fb2ec2ebb --- /dev/null +++ b/bin/spring @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby + +# This file loads spring without using Bundler, in order to be fast. +# It gets overwritten when you run the `spring binstub` command. + +unless defined?(Spring) + require 'rubygems' + require 'bundler' + + lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) + spring = lockfile.specs.detect { |spec| spec.name == "spring" } + if spring + Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path + gem 'spring', spring.version + require 'spring/binstub' + end +end diff --git a/bin/update b/bin/update new file mode 100755 index 000000000..58bfaed51 --- /dev/null +++ b/bin/update @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/yarn b/bin/yarn new file mode 100755 index 000000000..460dd565b --- /dev/null +++ b/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + begin + exec "yarnpkg", *ARGV + rescue Errno::ENOENT + $stderr.puts "Yarn executable was not detected in the system." + $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +end diff --git a/config.ru b/config.ru new file mode 100644 index 000000000..f7ba0b527 --- /dev/null +++ b/config.ru @@ -0,0 +1,5 @@ +# This file is used by Rack-based servers to start the application. + +require_relative 'config/environment' + +run Rails.application diff --git a/config/application.rb b/config/application.rb new file mode 100644 index 000000000..39685a85a --- /dev/null +++ b/config/application.rb @@ -0,0 +1,26 @@ +require_relative 'boot' + +require 'rails/all' + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module RideShareRails + class Application < Rails::Application + config.generators do |g| + # Force new test files to be generated in the minitest-spec style + g.test_framework :minitest, spec: true + + # Always use .js files, never .coffee + g.javascript_engine :js + end + # 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. + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 000000000..b9e460cef --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,4 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +require 'bundler/setup' # Set up gems listed in the Gemfile. +require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 000000000..0b6186ad8 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: ride-share-rails_production diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc new file mode 100644 index 000000000..cb949d143 --- /dev/null +++ b/config/credentials.yml.enc @@ -0,0 +1 @@ ++E/KLcAIHbq6B51o0+f90zqceGmtX2P72lSJ+jkbY74fPGdzU5OnHDbEDoW6Xn45jeVSJmyIqmmfCq42iKTuEPpWhfYU61bubtkzZ9DNaT2KOIiY7ghghdHjGAs8/jDrLA/nJ1nU50CzKX1uKSeL6kimjnbJJccmSJ2oghg/1PsQ/g8ZuysX91iyLdnTLOjTRxdHFH39xZAz3Bwlk10N4Ye+aiDm+Qopy27vaI+9QwTf/R66WmWkOHypCvmlCCOWYLtL9zIZjNrA+b5ySRp26OHGtOcEqtzyY1udZfh4Pm962rNGXMGGW2SMm7z2zKAQowhQnLIdrkHVQ54DXmVNu0vG4BsCJWM7J4+TO3woKt5NUIvF853ZGxgPax+P2lgK9gmCqu7H2ch2Fdd/RU2qX78aB+cN0fJSv15u--ZYMRrd0syumAF750--9XG+i/WHiq71PA8A3A75Fg== \ No newline at end of file diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 000000000..684902e69 --- /dev/null +++ b/config/database.yml @@ -0,0 +1,85 @@ +# PostgreSQL. Versions 9.1 and up are supported. +# +# Install the pg driver: +# gem install pg +# On OS X with Homebrew: +# gem install pg -- --with-pg-config=/usr/local/bin/pg_config +# On OS X with MacPorts: +# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config +# On Windows: +# gem install pg +# Choose the win32 build. +# Install PostgreSQL and put its /bin directory on your path. +# +# Configure Using Gemfile +# gem 'pg' +# +default: &default + adapter: postgresql + encoding: unicode + # For details on connection pooling, see Rails configuration guide + # http://guides.rubyonrails.org/configuring.html#database-pooling + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + +development: + <<: *default + database: ride-share-rails_development + + # The specified database role being used to connect to postgres. + # To create additional roles in postgres see `$ createuser --help`. + # When left blank, postgres will use the default role. This is + # the same name as the operating system user that initialized the database. + #username: ride-share-rails + + # The password associated with the postgres role (username). + #password: + + # Connect on a TCP socket. Omitted by default since the client uses a + # domain socket that doesn't need configuration. Windows does not have + # domain sockets, so uncomment these lines. + #host: localhost + + # The TCP port the server listens on. Defaults to 5432. + # If your server runs on a different port number, change accordingly. + #port: 5432 + + # Schema search path. The server defaults to $user,public + #schema_search_path: myapp,sharedapp,public + + # Minimum log levels, in increasing order: + # debug5, debug4, debug3, debug2, debug1, + # log, notice, warning, error, fatal, and panic + # Defaults to warning. + #min_messages: notice + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: ride-share-rails_test + +# As with config/secrets.yml, you never want to store sensitive information, +# like your database password, in your source code. If your source code is +# ever seen by anyone, they now have access to your database. +# +# Instead, provide the password as a unix environment variable when you boot +# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database +# for a full rundown on how to provide these environment variables in a +# production deployment. +# +# On Heroku and other platform providers, you may have a full connection URL +# available as an environment variable. For example: +# +# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" +# +# You can use this database configuration with: +# +# production: +# url: <%= ENV['DATABASE_URL'] %> +# +production: + <<: *default + database: ride-share-rails_production + username: ride-share-rails + password: <%= ENV['RIDE-SHARE-RAILS_DATABASE_PASSWORD'] %> diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 000000000..426333bb4 --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 000000000..1311e3e4e --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,61 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp', 'caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 000000000..cee449f7b --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,94 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "ride-share-rails_#{Rails.env}" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 000000000..0a38fd3ce --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,46 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/config/initializers/action_view.rb b/config/initializers/action_view.rb new file mode 100644 index 000000000..142d382f8 --- /dev/null +++ b/config/initializers/action_view.rb @@ -0,0 +1 @@ +Rails.application.config.action_view.form_with_generates_remote_forms = false diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 000000000..89d2efab2 --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 000000000..4b828e80c --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb new file mode 100644 index 000000000..59385cdf3 --- /dev/null +++ b/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..d3bcaa5ec --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb new file mode 100644 index 000000000..5a6a32d37 --- /dev/null +++ b/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 000000000..4a994e1e7 --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb new file mode 100644 index 000000000..ac033bf9d --- /dev/null +++ b/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb new file mode 100644 index 000000000..dc1899682 --- /dev/null +++ b/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb new file mode 100644 index 000000000..bbfc3961b --- /dev/null +++ b/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 000000000..decc5a857 --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,33 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 000000000..a5eccf816 --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,34 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 000000000..787824f88 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,3 @@ +Rails.application.routes.draw do + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html +end diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 000000000..9fa7863f9 --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,6 @@ +%w[ + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +].each { |path| Spring.watch(path) } diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 000000000..d32f76e8f --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/lib/assets/.keep b/lib/assets/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/lib/tasks/.keep b/lib/tasks/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/log/.keep b/log/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/package.json b/package.json new file mode 100644 index 000000000..75b35d319 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "name": "ride-share-rails", + "private": true, + "dependencies": {} +} diff --git a/public/404.html b/public/404.html new file mode 100644 index 000000000..2be3af26f --- /dev/null +++ b/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/422.html b/public/422.html new file mode 100644 index 000000000..c08eac0d1 --- /dev/null +++ b/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/500.html b/public/500.html new file mode 100644 index 000000000..78a030af2 --- /dev/null +++ b/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/apple-touch-icon-precomposed.png b/public/apple-touch-icon-precomposed.png new file mode 100644 index 000000000..e69de29bb diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 000000000..e69de29bb diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 000000000..e69de29bb diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 000000000..37b576a4a --- /dev/null +++ b/public/robots.txt @@ -0,0 +1 @@ +# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/storage/.keep b/storage/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb new file mode 100644 index 000000000..d19212abd --- /dev/null +++ b/test/application_system_test_case.rb @@ -0,0 +1,5 @@ +require "test_helper" + +class ApplicationSystemTestCase < ActionDispatch::SystemTestCase + driven_by :selenium, using: :chrome, screen_size: [1400, 1400] +end diff --git a/test/controllers/.keep b/test/controllers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/.keep b/test/fixtures/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/helpers/.keep b/test/helpers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/integration/.keep b/test/integration/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/mailers/.keep b/test/mailers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/models/.keep b/test/models/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/system/.keep b/test/system/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 000000000..10594a324 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,26 @@ +ENV["RAILS_ENV"] = "test" +require File.expand_path("../../config/environment", __FILE__) +require "rails/test_help" +require "minitest/rails" +require "minitest/reporters" # for Colorized output + +# For colorful output! +Minitest::Reporters.use!( + Minitest::Reporters::SpecReporter.new, + ENV, + Minitest.backtrace_filter +) + + +# To add Capybara feature tests add `gem "minitest-rails-capybara"` +# to the test group in the Gemfile and uncomment the following: +# require "minitest/rails/capybara" + +# Uncomment for awesome colorful output +# require "minitest/pride" + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + fixtures :all + # Add more helper methods to be used by all tests here... +end diff --git a/tmp/.keep b/tmp/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/.keep b/vendor/.keep new file mode 100644 index 000000000..e69de29bb From d3062d2efd014699eefa2ff0c5cf5b0b2ab8f694 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Mon, 15 Apr 2019 15:30:46 -0700 Subject: [PATCH 02/49] Created Driver and Passenger models --- app/models/driver.rb | 2 ++ app/models/passenger.rb | 2 ++ db/migrate/20190415222836_create_drivers.rb | 10 ++++++ .../20190415222959_create_passengers.rb | 10 ++++++ db/schema.rb | 32 +++++++++++++++++++ test/fixtures/drivers.yml | 9 ++++++ test/fixtures/passengers.yml | 9 ++++++ 7 files changed, 74 insertions(+) create mode 100644 app/models/driver.rb create mode 100644 app/models/passenger.rb create mode 100644 db/migrate/20190415222836_create_drivers.rb create mode 100644 db/migrate/20190415222959_create_passengers.rb create mode 100644 db/schema.rb create mode 100644 test/fixtures/drivers.yml create mode 100644 test/fixtures/passengers.yml diff --git a/app/models/driver.rb b/app/models/driver.rb new file mode 100644 index 000000000..1ff364562 --- /dev/null +++ b/app/models/driver.rb @@ -0,0 +1,2 @@ +class Driver < ApplicationRecord +end diff --git a/app/models/passenger.rb b/app/models/passenger.rb new file mode 100644 index 000000000..2c5748ac2 --- /dev/null +++ b/app/models/passenger.rb @@ -0,0 +1,2 @@ +class Passenger < ApplicationRecord +end diff --git a/db/migrate/20190415222836_create_drivers.rb b/db/migrate/20190415222836_create_drivers.rb new file mode 100644 index 000000000..cf564b3ab --- /dev/null +++ b/db/migrate/20190415222836_create_drivers.rb @@ -0,0 +1,10 @@ +class CreateDrivers < ActiveRecord::Migration[5.2] + def change + create_table :drivers do |t| + t.string :vin + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20190415222959_create_passengers.rb b/db/migrate/20190415222959_create_passengers.rb new file mode 100644 index 000000000..aeced4891 --- /dev/null +++ b/db/migrate/20190415222959_create_passengers.rb @@ -0,0 +1,10 @@ +class CreatePassengers < ActiveRecord::Migration[5.2] + def change + create_table :passengers do |t| + t.string :name + t.string :phone_num + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 000000000..9cca54a4e --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,32 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 2019_04_15_222959) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "drivers", force: :cascade do |t| + t.string "vin" + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "passengers", force: :cascade do |t| + t.string "name" + t.string "phone_num" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + +end diff --git a/test/fixtures/drivers.yml b/test/fixtures/drivers.yml new file mode 100644 index 000000000..9b121e04e --- /dev/null +++ b/test/fixtures/drivers.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + vin: MyString + name: MyString + +two: + vin: MyString + name: MyString diff --git a/test/fixtures/passengers.yml b/test/fixtures/passengers.yml new file mode 100644 index 000000000..2c97eae02 --- /dev/null +++ b/test/fixtures/passengers.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + phone_num: MyString + +two: + name: MyString + phone_num: MyString From b6186661ecb0a252e7bbfc53ea0ed9230da525fb Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Mon, 15 Apr 2019 15:44:46 -0700 Subject: [PATCH 03/49] Link passenger and driver to trips --- Gemfile | 2 +- Gemfile.lock | 3 --- app/models/driver.rb | 1 + app/models/passenger.rb | 1 + app/models/trip.rb | 3 +++ db/migrate/20190415223501_create_trips.rb | 11 +++++++++++ .../20190415223846_add_driver_id_to_trips.rb | 5 +++++ .../20190415224218_add_passenger_id_to_trips.rb | 5 +++++ db/schema.rb | 16 +++++++++++++++- test/fixtures/trips.yml | 11 +++++++++++ 10 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 app/models/trip.rb create mode 100644 db/migrate/20190415223501_create_trips.rb create mode 100644 db/migrate/20190415223846_add_driver_id_to_trips.rb create mode 100644 db/migrate/20190415224218_add_passenger_id_to_trips.rb create mode 100644 test/fixtures/trips.yml diff --git a/Gemfile b/Gemfile index e665f46d3..d8c77a8f5 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } -ruby '2.5.1' + # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.2.3' diff --git a/Gemfile.lock b/Gemfile.lock index a98c85111..c614b21db 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -267,8 +267,5 @@ DEPENDENCIES uglifier (>= 1.3.0) web-console (>= 3.3.0) -RUBY VERSION - ruby 2.5.1p57 - BUNDLED WITH 1.17.3 diff --git a/app/models/driver.rb b/app/models/driver.rb index 1ff364562..197e65507 100644 --- a/app/models/driver.rb +++ b/app/models/driver.rb @@ -1,2 +1,3 @@ class Driver < ApplicationRecord + has_many :trips end diff --git a/app/models/passenger.rb b/app/models/passenger.rb index 2c5748ac2..2fef89192 100644 --- a/app/models/passenger.rb +++ b/app/models/passenger.rb @@ -1,2 +1,3 @@ class Passenger < ApplicationRecord + has_many :trips end diff --git a/app/models/trip.rb b/app/models/trip.rb new file mode 100644 index 000000000..28c02c3a8 --- /dev/null +++ b/app/models/trip.rb @@ -0,0 +1,3 @@ +class Trip < ApplicationRecord + belongs_to :driver, :passenger +end diff --git a/db/migrate/20190415223501_create_trips.rb b/db/migrate/20190415223501_create_trips.rb new file mode 100644 index 000000000..0082137f6 --- /dev/null +++ b/db/migrate/20190415223501_create_trips.rb @@ -0,0 +1,11 @@ +class CreateTrips < ActiveRecord::Migration[5.2] + def change + create_table :trips do |t| + t.date :date + t.integer :rating + t.float :cost + + t.timestamps + end + end +end diff --git a/db/migrate/20190415223846_add_driver_id_to_trips.rb b/db/migrate/20190415223846_add_driver_id_to_trips.rb new file mode 100644 index 000000000..22c611432 --- /dev/null +++ b/db/migrate/20190415223846_add_driver_id_to_trips.rb @@ -0,0 +1,5 @@ +class AddDriverIdToTrips < ActiveRecord::Migration[5.2] + def change + add_reference :trips, :driver, foreign_key: true + end +end diff --git a/db/migrate/20190415224218_add_passenger_id_to_trips.rb b/db/migrate/20190415224218_add_passenger_id_to_trips.rb new file mode 100644 index 000000000..fffb1117a --- /dev/null +++ b/db/migrate/20190415224218_add_passenger_id_to_trips.rb @@ -0,0 +1,5 @@ +class AddPassengerIdToTrips < ActiveRecord::Migration[5.2] + def change + add_reference :trips, :passenger, foreign_key: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 9cca54a4e..c6722b8b8 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.define(version: 2019_04_15_222959) do +ActiveRecord::Schema.define(version: 2019_04_15_224218) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -29,4 +29,18 @@ t.datetime "updated_at", null: false end + create_table "trips", force: :cascade do |t| + t.date "date" + t.integer "rating" + t.float "cost" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "driver_id" + t.bigint "passenger_id" + t.index ["driver_id"], name: "index_trips_on_driver_id" + t.index ["passenger_id"], name: "index_trips_on_passenger_id" + end + + add_foreign_key "trips", "drivers" + add_foreign_key "trips", "passengers" end diff --git a/test/fixtures/trips.yml b/test/fixtures/trips.yml new file mode 100644 index 000000000..9f2868672 --- /dev/null +++ b/test/fixtures/trips.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + date: 2019-04-15 + rating: 1 + cost: 1.5 + +two: + date: 2019-04-15 + rating: 1 + cost: 1.5 From 7eac96b9ebfddaf4d2374121261829668649fa6a Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Mon, 15 Apr 2019 16:04:30 -0700 Subject: [PATCH 04/49] updated Trip model and updated Gemfile for readline error --- Gemfile | 5 +++++ Gemfile.lock | 2 ++ app/models/trip.rb | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index d8c77a8f5..723d47087 100644 --- a/Gemfile +++ b/Gemfile @@ -41,6 +41,11 @@ group :development, :test do gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] end +group :development do + # Adding this for a readline issue that prevents rails console from opening + gem 'rb-readline' +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' diff --git a/Gemfile.lock b/Gemfile.lock index c614b21db..c5f8caf4b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -183,6 +183,7 @@ GEM rb-fsevent (0.10.3) rb-inotify (0.10.0) ffi (~> 1.0) + rb-readline (0.5.5) regexp_parser (1.4.0) ruby-progressbar (1.10.0) ruby_dep (1.5.0) @@ -258,6 +259,7 @@ DEPENDENCIES pry-rails puma (~> 3.11) rails (~> 5.2.3) + rb-readline sass-rails (~> 5.0) selenium-webdriver spring diff --git a/app/models/trip.rb b/app/models/trip.rb index 28c02c3a8..8e2566cd8 100644 --- a/app/models/trip.rb +++ b/app/models/trip.rb @@ -1,3 +1,4 @@ class Trip < ApplicationRecord - belongs_to :driver, :passenger + belongs_to :driver + belongs_to :passenger end From b93f223e19deed3213e1f2bfa021f334e6dc50f4 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Mon, 15 Apr 2019 16:34:56 -0700 Subject: [PATCH 05/49] add RESTful routes --- config/routes.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 787824f88..b786460b8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,5 @@ Rails.application.routes.draw do - # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + resources :passengers + resources :drivers + resources :trips end From d57dd71e6b10838c6eeca321d71a09e36066a973 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Tue, 16 Apr 2019 11:07:58 -0700 Subject: [PATCH 06/49] Wrote test for driver controller index method, wrote method and view to pass --- app/assets/javascripts/drivers.js | 2 ++ app/assets/stylesheets/drivers.scss | 3 +++ app/controllers/drivers_controller.rb | 5 +++++ app/helpers/drivers_helper.rb | 2 ++ app/views/drivers/index.html.erb | 9 +++++++++ test/controllers/drivers_controller_test.rb | 6 +++++- 6 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/drivers.js create mode 100644 app/assets/stylesheets/drivers.scss create mode 100644 app/controllers/drivers_controller.rb create mode 100644 app/helpers/drivers_helper.rb create mode 100644 app/views/drivers/index.html.erb diff --git a/app/assets/javascripts/drivers.js b/app/assets/javascripts/drivers.js new file mode 100644 index 000000000..dee720fac --- /dev/null +++ b/app/assets/javascripts/drivers.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/drivers.scss b/app/assets/stylesheets/drivers.scss new file mode 100644 index 000000000..8c1768a14 --- /dev/null +++ b/app/assets/stylesheets/drivers.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Drivers controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/drivers_controller.rb b/app/controllers/drivers_controller.rb new file mode 100644 index 000000000..fa03c2e90 --- /dev/null +++ b/app/controllers/drivers_controller.rb @@ -0,0 +1,5 @@ +class DriversController < ApplicationController + def index + @drivers = Driver.all + end +end diff --git a/app/helpers/drivers_helper.rb b/app/helpers/drivers_helper.rb new file mode 100644 index 000000000..e5fc532e4 --- /dev/null +++ b/app/helpers/drivers_helper.rb @@ -0,0 +1,2 @@ +module DriversHelper +end diff --git a/app/views/drivers/index.html.erb b/app/views/drivers/index.html.erb new file mode 100644 index 000000000..283c9a692 --- /dev/null +++ b/app/views/drivers/index.html.erb @@ -0,0 +1,9 @@ +

Drivers

+
    + <% @drivers.each do |driver|%> +
  • + <%= link_to driver.name, driver_path(driver)%> +
  • + <%end%> +
+ diff --git a/test/controllers/drivers_controller_test.rb b/test/controllers/drivers_controller_test.rb index 59e15818c..d0480ba6a 100644 --- a/test/controllers/drivers_controller_test.rb +++ b/test/controllers/drivers_controller_test.rb @@ -3,7 +3,11 @@ describe DriversController do describe "index" do it "can get index" do - # Your code here + # Act + get drivers_path + + # Assert + must_respond_with :success end end From 82c338d1525c791b9445eb1f1c6790bdcb72f5ec Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Tue, 16 Apr 2019 11:52:00 -0700 Subject: [PATCH 07/49] Wrote tests for driver#show, wrote method and html to pass test --- app/controllers/drivers_controller.rb | 10 ++++++++++ app/views/drivers/show.html.erb | 9 +++++++++ test/controllers/drivers_controller_test.rb | 21 ++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 app/views/drivers/show.html.erb diff --git a/app/controllers/drivers_controller.rb b/app/controllers/drivers_controller.rb index fa03c2e90..842b470a1 100644 --- a/app/controllers/drivers_controller.rb +++ b/app/controllers/drivers_controller.rb @@ -2,4 +2,14 @@ class DriversController < ApplicationController def index @drivers = Driver.all end + + def show + driver_id = params[:id] + + @driver = Driver.find_by(id: driver_id) + + unless @driver + redirect_to drivers_path, :flash => {:error => "Could not find driver with id: #{driver_id}"} + end + end end diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb new file mode 100644 index 000000000..406a2394d --- /dev/null +++ b/app/views/drivers/show.html.erb @@ -0,0 +1,9 @@ +

Driver Details

+ +

+ Driver: <%= @driver.name %> +

+ +<%# <%= link_to "Edit Task", edit_task_path(@driver.id) %> +<%# <%= link_to "Delete", task_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %> + diff --git a/test/controllers/drivers_controller_test.rb b/test/controllers/drivers_controller_test.rb index d0480ba6a..cc8046883 100644 --- a/test/controllers/drivers_controller_test.rb +++ b/test/controllers/drivers_controller_test.rb @@ -1,6 +1,10 @@ require "test_helper" describe DriversController do + let (:driver) { + Driver.create name: "Alfred Jenkins", vin: "12345678901234567" + } + describe "index" do it "can get index" do # Act @@ -12,7 +16,22 @@ end describe "show" do - # Your tests go here + it "can get a valid driver" do + # Act + get driver_path(driver.id) + + # Assert + must_respond_with :success + end + + it "will redirect for an invalid driver" do + # Act + get driver_path(-1) + + # Assert + must_respond_with :redirect + expect(flash[:error]).must_equal "Could not find driver with id: -1" + end end describe "edit" do From 1892ca390ed141975720c31d4d6d2947a8058778 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Tue, 16 Apr 2019 12:02:49 -0700 Subject: [PATCH 08/49] wrote tests for driver#update, wrote method and html to pass tests --- app/controllers/drivers_controller.rb | 10 +++++++++ app/views/drivers/edit.html.erb | 19 +++++++++++++++++ test/controllers/drivers_controller_test.rb | 23 ++++++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 app/views/drivers/edit.html.erb diff --git a/app/controllers/drivers_controller.rb b/app/controllers/drivers_controller.rb index 842b470a1..bc9696c8a 100644 --- a/app/controllers/drivers_controller.rb +++ b/app/controllers/drivers_controller.rb @@ -12,4 +12,14 @@ def show redirect_to drivers_path, :flash => {:error => "Could not find driver with id: #{driver_id}"} end end + + def edit + driver_id = (params[:id]) + + @driver = Driver.find_by(id: driver_id) + + unless @driver + redirect_to drivers_path, :flash => {:error => "Could not find driver with id: #{driver_id}"} + end + end end diff --git a/app/views/drivers/edit.html.erb b/app/views/drivers/edit.html.erb new file mode 100644 index 000000000..98acfb6ae --- /dev/null +++ b/app/views/drivers/edit.html.erb @@ -0,0 +1,19 @@ +

Edit Driver

+ + +<%= form_for @driver do |f| %> +

Please enter the information you would like to edit

+ +
+ <%= f.label :name, 'Please enter the desired name' %> + <%= f.text_field :name %> +
+ +
+ <%= f.label 'Please enter the task description' %> + <%= f.text_field :vin %> +
+ + <%= f.submit "Submit" %> + +<% end %> \ No newline at end of file diff --git a/test/controllers/drivers_controller_test.rb b/test/controllers/drivers_controller_test.rb index cc8046883..f54b8171c 100644 --- a/test/controllers/drivers_controller_test.rb +++ b/test/controllers/drivers_controller_test.rb @@ -35,7 +35,28 @@ end describe "edit" do - # Your tests go here + it "can get the edit page for an existing driver" do + #Arrange + driver_data = { + name: "Updated Name", + vin: "NEW Vin Num", + } + + #Act + get edit_driver_path(driver.id), params: driver_data + + #Assert + must_respond_with :success + end + + it "will respond with redirect when attempting to edit a nonexistant driver" do + #Act + get edit_driver_path(-1) + + # Assert + must_respond_with :redirect + expect(flash[:error]).must_equal "Could not find driver with id: -1" + end end describe "update" do From 54bcef8eddb66d1e961a10e2b5675f6ca61728bd Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Tue, 16 Apr 2019 12:38:43 -0700 Subject: [PATCH 09/49] Add edit, update, show controllers and views --- app/assets/javascripts/passengers.js | 2 + app/assets/stylesheets/passengers.scss | 3 ++ app/controllers/passengers_controller.rb | 53 +++++++++++++++++++ app/helpers/passengers_helper.rb | 2 + app/views/passengers/edit.html.erb | 3 ++ app/views/passengers/index.html.erb | 6 +++ app/views/passengers/show.html.erb | 1 + .../controllers/passengers_controller_test.rb | 46 ++++++++++++++-- 8 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/passengers.js create mode 100644 app/assets/stylesheets/passengers.scss create mode 100644 app/controllers/passengers_controller.rb create mode 100644 app/helpers/passengers_helper.rb create mode 100644 app/views/passengers/edit.html.erb create mode 100644 app/views/passengers/index.html.erb create mode 100644 app/views/passengers/show.html.erb diff --git a/app/assets/javascripts/passengers.js b/app/assets/javascripts/passengers.js new file mode 100644 index 000000000..dee720fac --- /dev/null +++ b/app/assets/javascripts/passengers.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/passengers.scss b/app/assets/stylesheets/passengers.scss new file mode 100644 index 000000000..0e27942f7 --- /dev/null +++ b/app/assets/stylesheets/passengers.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Passengers controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/passengers_controller.rb b/app/controllers/passengers_controller.rb new file mode 100644 index 000000000..8b29e3841 --- /dev/null +++ b/app/controllers/passengers_controller.rb @@ -0,0 +1,53 @@ +class PassengersController < ApplicationController + def index + @passengers = Passenger.all + end + + def show + passenger_id = params[:id] + @passenger = Passenger.find_by(id: passenger_id) + + unless @passenger + redirect_to passengers_path, :flash => { :error => "Could not find passenger with id: #{passenger_id}" } + end + end + + def edit + passenger_id = params[:id] + @passenger = Passenger.find_by(id: passenger_id) + + unless @passenger + redirect_to passengers_path, :flash => { :error => "Could not find passenger with id: #{passenger_id}" } + end + end + + def update + @passenger = Passenger.find_by(id: params[:id]) + + unless @passenger + redirect_to passengers_path, :flash => { :error => "Could not find passenger with id: #{passenger_id}" } + end + + @passenger.update(passenger_params) + + redirect_to passenger_path(@passenger) + end + + def new + @passenger = Passenger.new + end + + def create + @passenger = Passenger.new(passenger_params) + + @passenger.save + + redirect_to passengers_path + end + + private + + def passenger_params + return params.require(:passenger).permit(:name, :phone_num) + end +end diff --git a/app/helpers/passengers_helper.rb b/app/helpers/passengers_helper.rb new file mode 100644 index 000000000..1af9e68f1 --- /dev/null +++ b/app/helpers/passengers_helper.rb @@ -0,0 +1,2 @@ +module PassengersHelper +end diff --git a/app/views/passengers/edit.html.erb b/app/views/passengers/edit.html.erb new file mode 100644 index 000000000..ae683fcd2 --- /dev/null +++ b/app/views/passengers/edit.html.erb @@ -0,0 +1,3 @@ +

Edit Passenger Info

+ + content! \ No newline at end of file diff --git a/app/views/passengers/index.html.erb b/app/views/passengers/index.html.erb new file mode 100644 index 000000000..ba540fa60 --- /dev/null +++ b/app/views/passengers/index.html.erb @@ -0,0 +1,6 @@ +

Passengers Index

+ +<% @passengers.each do |passenger| %> + <%= passenger.name %>
+ <%= passenger.phone_num %>
+<% end %> \ No newline at end of file diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb new file mode 100644 index 000000000..173e0c19b --- /dev/null +++ b/app/views/passengers/show.html.erb @@ -0,0 +1 @@ +

Passenger Show Page

\ No newline at end of file diff --git a/test/controllers/passengers_controller_test.rb b/test/controllers/passengers_controller_test.rb index d6030cbf6..cdceaa845 100644 --- a/test/controllers/passengers_controller_test.rb +++ b/test/controllers/passengers_controller_test.rb @@ -1,20 +1,58 @@ require "test_helper" describe PassengersController do + let (:passenger) { + Passenger.create name: "Bebop Phung", phone_num: "206-323-3148" + } describe "index" do - # Your tests go here + it "can get to the index" do + get passengers_path + + # Assert + must_respond_with :success + end end describe "show" do - # Your tests go here + it "can get a valid passenger" do + get passenger_path(passenger.id) + + must_respond_with :success + end + + it "will display an error for an invalid passenger ID" do + get passenger_path(-1) + + must_respond_with :redirect + expect(flash[:error]).must_equal "Could not find passenger with id: -1" + end end describe "edit" do - # Your tests go here + it "can get to a Passenger's edit page" do + get edit_passenger_path(1) + + must_respond_with :found + end end describe "update" do - # Your tests go here + it "can update an existing Passenger" do + passenger = Passenger.create!(name: "Bebop Phung") + passenger_data = { + passenger: { + name: "Bebop Houle", + }, + } + + patch passenger_path(passenger.id), params: passenger_data + + must_respond_with :redirect + must_redirect_to passenger_path(passenger) + + passenger.reload + expect(passenger.name).must_equal(passenger_data[:passenger][:name]) + end end describe "new" do From af6fe495650b3f78f30c0d0edd4a5396288228f0 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Tue, 16 Apr 2019 14:55:11 -0700 Subject: [PATCH 10/49] edits to update method in passengers --- test/controllers/passengers_controller_test.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/controllers/passengers_controller_test.rb b/test/controllers/passengers_controller_test.rb index cdceaa845..2906e590a 100644 --- a/test/controllers/passengers_controller_test.rb +++ b/test/controllers/passengers_controller_test.rb @@ -53,6 +53,8 @@ passenger.reload expect(passenger.name).must_equal(passenger_data[:passenger][:name]) end + + end describe "new" do From e89648816aa7bca69491765c7cb6d232268e96e9 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Tue, 16 Apr 2019 15:38:30 -0700 Subject: [PATCH 11/49] Remove spurious model tests --- test/models/driver_test.rb | 78 ----------------------------------- test/models/passenger_test.rb | 68 ------------------------------ test/models/trip_test.rb | 24 ----------- 3 files changed, 170 deletions(-) delete mode 100644 test/models/driver_test.rb delete mode 100644 test/models/passenger_test.rb delete mode 100644 test/models/trip_test.rb diff --git a/test/models/driver_test.rb b/test/models/driver_test.rb deleted file mode 100644 index 44f62ff69..000000000 --- a/test/models/driver_test.rb +++ /dev/null @@ -1,78 +0,0 @@ -require "test_helper" - -describe Driver do - let (:new_driver) { - Driver.new(name: "Kari", vin: "123", active: true, - car_make: "Cherry", car_model: "DR5") - } - it "can be instantiated" do - # Assert - expect(new_driver.valid?).must_equal true - end - - it "will have the required fields" do - # Arrange - driver = Driver.first - [:name, :vin, :active, :car_make, :car_model].each do |field| - - # Assert - expect(driver).must_respond_to field - end - end - - describe "relationships" do - it "can have many trips" do - # Arrange - driver = Driver.first - - # Assert - expect(driver.trips.count).must_be :>=, 0 - driver.trips.each do |trip| - expect(trip).must_be_instance_of Trip - end - end - end - - describe "validations" do - it "must have a name" do - # Arrange - new_driver.name = nil - - # Assert - expect(new_driver.valid?).must_equal false - expect(new_driver.errors.messages).must_include :name - expect(new_driver.errors.messages[:name]).must_equal ["can't be blank"] - end - - it "must have a VIN number" do - # Arrange - new_driver.vin = nil - - # Assert - expect(new_driver.valid?).must_equal false - expect(new_driver.errors.messages).must_include :vin - expect(new_driver.errors.messages[:vin]).must_equal ["can't be blank"] - end - end - - # Tests for methods you create should go here - describe "custom methods" do - describe "average rating" do - # Your code here - end - - describe "total earnings" do - # Your code here - end - - describe "can go online" do - # Your code here - end - - describe "can go offline" do - # Your code here - end - - # You may have additional methods to test - end -end diff --git a/test/models/passenger_test.rb b/test/models/passenger_test.rb deleted file mode 100644 index 23f974ff9..000000000 --- a/test/models/passenger_test.rb +++ /dev/null @@ -1,68 +0,0 @@ -require "test_helper" - -describe Passenger do - let (:new_passenger) { - Passenger.new(name: "Kari", phone_number: "111-111-1211") - } - it "can be instantiated" do - # Assert - expect(new_passenger.valid?).must_equal true - end - - it "will have the required fields" do - # Arrange - passenger = Passenger.first - [:name, :phone_number].each do |field| - - # Assert - expect(passenger).must_respond_to field - end - end - - describe "relationships" do - it "can have many trips" do - # Arrange - passenger = Passenger.first - - # Assert - expect(passenger.trips.count).must_be :>, 0 - passenger.trips.each do |trip| - expect(trip).must_be_instance_of Trip - end - end - end - - describe "validations" do - it "must have a name" do - # Arrange - new_passenger.name = nil - - # Assert - expect(new_passenger.valid?).must_equal false - expect(new_passenger.errors.messages).must_include :name - expect(new_passenger.errors.messages[:name]).must_equal ["can't be blank"] - end - - it "must have a phone number" do - # Arrange - new_passenger.phone_number = nil - - # Assert - expect(new_passenger.valid?).must_equal false - expect(new_passenger.errors.messages).must_include :new_passenger - expect(new_passenger.errors.messages[:new_passenger]).must_equal ["can't be blank"] - end - end - - # Tests for methods you create should go here - describe "custom methods" do - describe "request a ride" do - # Your code here - end - - describe "complete trip" do - # Your code here - end - # You may have additional methods to test here - end -end diff --git a/test/models/trip_test.rb b/test/models/trip_test.rb deleted file mode 100644 index 0b0b2da32..000000000 --- a/test/models/trip_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -require "test_helper" - -describe Trip do - it "can be instantiated" do - # Your code here - end - - it "will have the required fields" do - # Your code here - end - - describe "relationships" do - # Your tests go here - end - - describe "validations" do - # Your tests go here - end - - # Tests for methods you create should go here - describe "custom methods" do - # Your tests here - end -end From e3f8bb0d5868b35e38760e3028585dc9b455d7ce Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Tue, 16 Apr 2019 15:42:36 -0700 Subject: [PATCH 12/49] edit homepage and trips controllers --- test/controllers/homepages_controller_test.rb | 2 +- test/controllers/trips_controller_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/controllers/homepages_controller_test.rb b/test/controllers/homepages_controller_test.rb index 9dd7648db..506543f8d 100644 --- a/test/controllers/homepages_controller_test.rb +++ b/test/controllers/homepages_controller_test.rb @@ -1,6 +1,6 @@ require "test_helper" -describe HomepagesController do +describe "HomepagesController" do it "can get the homepage" do get root_path diff --git a/test/controllers/trips_controller_test.rb b/test/controllers/trips_controller_test.rb index 0e6b170d1..9f3e6ca84 100644 --- a/test/controllers/trips_controller_test.rb +++ b/test/controllers/trips_controller_test.rb @@ -1,6 +1,6 @@ require "test_helper" -describe TripsController do +describe "TripsController" do describe "show" do # Your tests go here end From ad0b0223e711bcc27a4780c4268b6c3826233c26 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Tue, 16 Apr 2019 16:30:45 -0700 Subject: [PATCH 13/49] add passenger controller update tests --- app/controllers/passengers_controller.rb | 9 ++++--- app/models/passenger.rb | 4 +++ .../controllers/passengers_controller_test.rb | 26 ++++++++++++++++--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/app/controllers/passengers_controller.rb b/app/controllers/passengers_controller.rb index 8b29e3841..6c63041f9 100644 --- a/app/controllers/passengers_controller.rb +++ b/app/controllers/passengers_controller.rb @@ -26,11 +26,14 @@ def update unless @passenger redirect_to passengers_path, :flash => { :error => "Could not find passenger with id: #{passenger_id}" } + return end - @passenger.update(passenger_params) - - redirect_to passenger_path(@passenger) + if @passenger.update(passenger_params) + redirect_to passenger_path(@passenger) + else + render :edit, status: :bad_request + end end def new diff --git a/app/models/passenger.rb b/app/models/passenger.rb index 2fef89192..7d8994524 100644 --- a/app/models/passenger.rb +++ b/app/models/passenger.rb @@ -1,3 +1,7 @@ class Passenger < ApplicationRecord has_many :trips + + # must provide a valid phone number + validates :phone_num, presence: true + validates :name, presence: true end diff --git a/test/controllers/passengers_controller_test.rb b/test/controllers/passengers_controller_test.rb index 2906e590a..50845495a 100644 --- a/test/controllers/passengers_controller_test.rb +++ b/test/controllers/passengers_controller_test.rb @@ -38,10 +38,11 @@ describe "update" do it "can update an existing Passenger" do - passenger = Passenger.create!(name: "Bebop Phung") + passenger = Passenger.create!(name: "Bebop Phung", phone_num: "555555") passenger_data = { passenger: { name: "Bebop Houle", + phone_num: "1234567", }, } @@ -53,8 +54,27 @@ passenger.reload expect(passenger.name).must_equal(passenger_data[:passenger][:name]) end - - + + it "responds with BAD REQUEST for bad data" do + passenger = Passenger.create(name: "Test passenger", phone_num: "bbbb") + # Arrange + passenger_data = { + passenger: { + name: "", + phone_num: "", + }, + } + # Assumptions + passenger.assign_attributes(passenger_data[:passenger]) + expect(passenger).wont_be :valid? + passenger.reload + + # Act + patch passenger_path(passenger), params: passenger_data + + # Assert + must_respond_with :bad_request + end end describe "new" do From 98e53d64bbb231cd10f6211e5b77912f4a1da145 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Tue, 16 Apr 2019 21:04:25 -0700 Subject: [PATCH 14/49] add Passenger destroy method & index view html --- Gemfile.lock | 2 +- app/assets/images/til-the-end.png | Bin 0 -> 92035 bytes app/controllers/passengers_controller.rb | 16 ++++++++++++++++ app/views/passengers/_form.html.erb | 15 +++++++++++++++ app/views/passengers/edit.html.erb | 5 ++++- app/views/passengers/index.html.erb | 12 +++++++++--- 6 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 app/assets/images/til-the-end.png create mode 100644 app/views/passengers/_form.html.erb diff --git a/Gemfile.lock b/Gemfile.lock index c5f8caf4b..2c924cd90 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -270,4 +270,4 @@ DEPENDENCIES web-console (>= 3.3.0) BUNDLED WITH - 1.17.3 + 1.16.6 diff --git a/app/assets/images/til-the-end.png b/app/assets/images/til-the-end.png new file mode 100644 index 0000000000000000000000000000000000000000..18c2b25aaaba6b12824a7d2b9acee54b91025f48 GIT binary patch literal 92035 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 + +
+ <%= task.label :name%> + <%= task.text_field :name, placeholder: "Passenger name" %> +
+ +
+ <%= task.label :phone_num %> + <%= task.text_field :phone_num, placeholder: "1234567890" %> +
+ + <%= task.submit action_name, class: "button" %> + +<% end %> \ No newline at end of file diff --git a/app/views/passengers/edit.html.erb b/app/views/passengers/edit.html.erb index ae683fcd2..e1b3900bb 100644 --- a/app/views/passengers/edit.html.erb +++ b/app/views/passengers/edit.html.erb @@ -1,3 +1,6 @@

Edit Passenger Info

- content! \ No newline at end of file +<%= render partial: "form", locals: { + form_class: "edit-passenger", + action_name: "Save changes" +} %> \ No newline at end of file diff --git a/app/views/passengers/index.html.erb b/app/views/passengers/index.html.erb index ba540fa60..372e3c8fd 100644 --- a/app/views/passengers/index.html.erb +++ b/app/views/passengers/index.html.erb @@ -1,6 +1,12 @@

Passengers Index

<% @passengers.each do |passenger| %> - <%= passenger.name %>
- <%= passenger.phone_num %>
-<% end %> \ No newline at end of file + <%= image_tag "til-the-end.png" %> + <%= link_to "passenger.name", passenger_path(passenger.id) %>
+ <%= link_to "Edit", edit_passenger_path(passenger.id) %> + <%= link_to "Delete", task_path(task.id), method: :delete, data: { confirm: "Are you sure you want to remove this passenger?" } %> +<% end %> + + + <%# <%= passenger.name %> + <%# <%= passenger.phone_num %> \ No newline at end of file From ef3fea765a0f82a3a5eb904785d091d74cfb7172 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Tue, 16 Apr 2019 16:18:01 -0700 Subject: [PATCH 15/49] wrote tests for driver#update method and wrote method to pass --- app/controllers/drivers_controller.rb | 23 ++++++++ app/models/driver.rb | 3 + test/controllers/drivers_controller_test.rb | 62 ++++++++++++++++++++- 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/app/controllers/drivers_controller.rb b/app/controllers/drivers_controller.rb index bc9696c8a..cdbb6866f 100644 --- a/app/controllers/drivers_controller.rb +++ b/app/controllers/drivers_controller.rb @@ -22,4 +22,27 @@ def edit redirect_to drivers_path, :flash => {:error => "Could not find driver with id: #{driver_id}"} end end + + def update + driver_id = (params[:id]) + + @driver = Driver.find_by(id: driver_id) + + unless @driver + redirect_to drivers_path, :flash => {:error => "Could not find driver with id: #{driver_id}"} + return + end + + if @driver.update(driver_params) + redirect_to driver_path(@driver) + else + render :edit, status: :bad_request + end + end + + private + + def driver_params + return params.require(:driver).permit(:name, :vin) + end end diff --git a/app/models/driver.rb b/app/models/driver.rb index 197e65507..ad0d81b5d 100644 --- a/app/models/driver.rb +++ b/app/models/driver.rb @@ -1,3 +1,6 @@ class Driver < ApplicationRecord has_many :trips + + validates :name, presence: true + validates :vin, presence: true, uniqueness: true, length: {is: 17} end diff --git a/test/controllers/drivers_controller_test.rb b/test/controllers/drivers_controller_test.rb index f54b8171c..19a69ed6c 100644 --- a/test/controllers/drivers_controller_test.rb +++ b/test/controllers/drivers_controller_test.rb @@ -2,7 +2,7 @@ describe DriversController do let (:driver) { - Driver.create name: "Alfred Jenkins", vin: "12345678901234567" + Driver.create name: "Alfred Jenkins", vin: "2A8HR541X9R665072" } describe "index" do @@ -39,7 +39,7 @@ #Arrange driver_data = { name: "Updated Name", - vin: "NEW Vin Num", + vin: "NEWSX9C51FT697232", } #Act @@ -60,7 +60,63 @@ end describe "update" do - # Your tests go here + it "can update an existing driver" do + id = Driver.first.id + + driver_data = { + driver: { + name: "New name", + vin: "NEWNUMC51FT697232", + }, + } + + expect { + patch driver_path(id), params: driver_data + }.wont_change "Driver.count" + + must_respond_with :redirect + must_redirect_to driver_path + + driver = Driver.find_by(id: id) + expect(driver.name).must_equal driver_data[:driver][:name] + expect(driver.vin).must_equal driver_data[:driver][:vin] + end + + it "will redirect to the root page if given an invalid id" do + id = -1 + + driver_data = { + name: "Update failure name", + vin: "FAILC9C51FT697232", + } + + patch driver_path(id), params: driver_data + + must_respond_with :redirect + expect(flash[:error]).must_equal "Could not find driver with id: -1" + end + + it "responds with BAD REQUEST for bad data" do + driver = Driver.create(name: "Test Driver", vin: "1FUJA6CG57LY48020") + # Arrange + driver_data = { + driver: { + name: "New name", + vin: "bad vin", + }, + } + + # Assumptions + driver.assign_attributes(driver_data[:driver]) + expect(driver).wont_be :valid? + driver.reload + + # Act + patch driver_path(driver), params: driver_data + + # Assert + must_respond_with :bad_request + end end describe "new" do From b34cf011298c7d65ae367863b875e045cbb3e263 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Tue, 16 Apr 2019 16:53:41 -0700 Subject: [PATCH 16/49] wrote tests for driver#new method and wrote method/html to pass --- app/controllers/drivers_controller.rb | 4 ++++ app/views/drivers/new.html.erb | 18 ++++++++++++++++++ test/controllers/drivers_controller_test.rb | 8 +++++++- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 app/views/drivers/new.html.erb diff --git a/app/controllers/drivers_controller.rb b/app/controllers/drivers_controller.rb index cdbb6866f..b02a12582 100644 --- a/app/controllers/drivers_controller.rb +++ b/app/controllers/drivers_controller.rb @@ -40,6 +40,10 @@ def update end end + def new + @driver = Driver.new + end + private def driver_params diff --git a/app/views/drivers/new.html.erb b/app/views/drivers/new.html.erb new file mode 100644 index 000000000..a490d9f29 --- /dev/null +++ b/app/views/drivers/new.html.erb @@ -0,0 +1,18 @@ +

New Driver Form

+ +<%= form_with model: @driver, class: 'driver-form' do |f|%> +

Please fill out this driver's information

+ +
+ <%= f.label :name, "Please enter the new driver" %> + <%= f.text_field :name, placeholder: "Driver Name" %> +
+ +
+ <%= f.label :vin %> + <%= f.text_field :vin, placeholder: "Vin Number"%> +
+ + <%= f.submit "Submit" %> + +<% end %> \ No newline at end of file diff --git a/test/controllers/drivers_controller_test.rb b/test/controllers/drivers_controller_test.rb index 19a69ed6c..e3f060051 100644 --- a/test/controllers/drivers_controller_test.rb +++ b/test/controllers/drivers_controller_test.rb @@ -120,7 +120,13 @@ end describe "new" do - # Your tests go here + it "can get the new driver page" do + # Act + get new_driver_path + + # Assert + must_respond_with :success + end end describe "create" do From 7d0d38be8c987102849071ec105d1c7be9306116 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Tue, 16 Apr 2019 18:38:26 -0700 Subject: [PATCH 17/49] Wrote tests for driver#create method and updated code to match --- app/controllers/drivers_controller.rb | 11 ++++++++++ test/controllers/drivers_controller_test.rb | 23 ++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/app/controllers/drivers_controller.rb b/app/controllers/drivers_controller.rb index b02a12582..c36bcb517 100644 --- a/app/controllers/drivers_controller.rb +++ b/app/controllers/drivers_controller.rb @@ -44,6 +44,17 @@ def new @driver = Driver.new end + def create + @driver = Driver.new(driver_params) + + successful = @driver.save + if successful + redirect_to drivers_path + else + render :new, status: :bad_request + end + end + private def driver_params diff --git a/test/controllers/drivers_controller_test.rb b/test/controllers/drivers_controller_test.rb index e3f060051..d004c0d28 100644 --- a/test/controllers/drivers_controller_test.rb +++ b/test/controllers/drivers_controller_test.rb @@ -130,7 +130,28 @@ end describe "create" do - # Your tests go here + it "creates a new driver" do + # Arrange + driver_data = { + driver: { + name: "New Driver", + vin: "5J8TB18239A001655", + }, + } + + # Act + expect { + post drivers_path, params: driver_data + }.must_change "Driver.count", +1 + + # Assert + must_respond_with :redirect + must_redirect_to drivers_path + + driver = Driver.last + expect(driver.name).must_equal driver_data[:driver][:name] + expect(driver.vin).must_equal driver_data[:driver][:vin] + end end describe "destroy" do From 0f40e0607ad63ed06afc66427f53b53e25462604 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Tue, 16 Apr 2019 18:54:26 -0700 Subject: [PATCH 18/49] Wrote tests for driver#create method and wrote method to pass test --- app/controllers/drivers_controller.rb | 13 ++++++++ test/controllers/drivers_controller_test.rb | 34 +++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/app/controllers/drivers_controller.rb b/app/controllers/drivers_controller.rb index c36bcb517..d8617cc1e 100644 --- a/app/controllers/drivers_controller.rb +++ b/app/controllers/drivers_controller.rb @@ -55,6 +55,19 @@ def create end end + def destroy + driver_id = params[:id] + + driver = Driver.find_by(id: driver_id) + + if driver + driver.destroy + redirect_to drivers_path + else + head :not_found + end + end + private def driver_params diff --git a/test/controllers/drivers_controller_test.rb b/test/controllers/drivers_controller_test.rb index d004c0d28..be47c012e 100644 --- a/test/controllers/drivers_controller_test.rb +++ b/test/controllers/drivers_controller_test.rb @@ -97,7 +97,6 @@ end it "responds with BAD REQUEST for bad data" do - driver = Driver.create(name: "Test Driver", vin: "1FUJA6CG57LY48020") # Arrange driver_data = { driver: { @@ -131,6 +130,8 @@ describe "create" do it "creates a new driver" do + driver = Driver.create(name: "Test Driver", vin: "1FUJA6CG57LY48020") + # Arrange driver_data = { driver: { @@ -155,6 +156,35 @@ end describe "destroy" do - # Your tests go here + it "removes the driver from the database" do + driver = Driver.create(name: "Test Driver", vin: "1FUJA6CG57LY48020") + # Act + expect { + delete driver_path(driver) + }.must_change "Driver.count", -1 + + # Assert + must_respond_with :redirect + must_redirect_to drivers_path + + after_driver = Driver.find_by(id: driver.id) + expect(after_driver).must_be_nil + end + + it "returns a 404 if the driver does not exist" do + # Arrange + driver_id = -1 + + # Assumptions + expect(Driver.find_by(id: driver_id)).must_be_nil + + # Act + expect { + delete driver_path(driver_id) + }.wont_change "Driver.count" + + # Assert + must_respond_with :not_found + end end end From 38f2b302704b16807a05bd270d5a3d5266709adf Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Tue, 16 Apr 2019 19:04:36 -0700 Subject: [PATCH 19/49] Updated html pages for driver to include edit/delete links and driver links --- app/views/drivers/edit.html.erb | 2 +- app/views/drivers/index.html.erb | 3 +++ app/views/drivers/show.html.erb | 7 +++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/views/drivers/edit.html.erb b/app/views/drivers/edit.html.erb index 98acfb6ae..c2a1f89b1 100644 --- a/app/views/drivers/edit.html.erb +++ b/app/views/drivers/edit.html.erb @@ -10,7 +10,7 @@
- <%= f.label 'Please enter the task description' %> + <%= f.label 'Please enter the desired VIN number' %> <%= f.text_field :vin %>
diff --git a/app/views/drivers/index.html.erb b/app/views/drivers/index.html.erb index 283c9a692..c59441433 100644 --- a/app/views/drivers/index.html.erb +++ b/app/views/drivers/index.html.erb @@ -3,6 +3,9 @@ <% @drivers.each do |driver|%>
  • <%= link_to driver.name, driver_path(driver)%> + <%= "VIN Number: #{driver.vin}" %> + <%= link_to "Edit", edit_driver_path(driver)%> + <%= link_to "Delete", driver_path(driver), method: :delete, data: {confirm: "Are you sure?"} %>
  • <%end%> diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index 406a2394d..c171d16e8 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -3,7 +3,10 @@

    Driver: <%= @driver.name %>

    +

    + VIN: <%= @driver.vin %> +

    -<%# <%= link_to "Edit Task", edit_task_path(@driver.id) %> -<%# <%= link_to "Delete", task_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %> +<%= link_to "Edit Driver", edit_driver_path(@driver.id) %> +<%= link_to "Delete", driver_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %> From b4df97e4eb7e081b2f7b533be9d088522c765918 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Tue, 16 Apr 2019 21:13:18 -0700 Subject: [PATCH 20/49] add successful delete flash notice --- app/controllers/passengers_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/passengers_controller.rb b/app/controllers/passengers_controller.rb index 751e980ee..d26780015 100644 --- a/app/controllers/passengers_controller.rb +++ b/app/controllers/passengers_controller.rb @@ -58,7 +58,7 @@ def destroy end if @passenger.destroy - redirect_to passengers_path + redirect_to passengers_path, flash[:notice] = "Passenger successfully deleted" else render :edit, status: :bad_request end From 25ee081970150f164ad5013412510c3bd65f6542 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Tue, 16 Apr 2019 21:36:05 -0700 Subject: [PATCH 21/49] add kaminari--pagination gem to gemfile --- Gemfile | 4 ++-- Gemfile.lock | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 723d47087..1b5232355 100644 --- a/Gemfile +++ b/Gemfile @@ -1,8 +1,8 @@ source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } - - +# Use Kaminari for pagination functionality +gem 'kaminari' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.2.3' # Use postgresql as the database for Active Record diff --git a/Gemfile.lock b/Gemfile.lock index 2c924cd90..315d3707e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -108,6 +108,18 @@ GEM jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks + kaminari (1.1.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.1.1) + kaminari-activerecord (= 1.1.1) + kaminari-core (= 1.1.1) + kaminari-actionview (1.1.1) + actionview + kaminari-core (= 1.1.1) + kaminari-activerecord (1.1.1) + activerecord + kaminari-core (= 1.1.1) + kaminari-core (1.1.1) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -251,6 +263,7 @@ DEPENDENCIES jbuilder (~> 2.5) jquery-rails jquery-turbolinks + kaminari listen (>= 3.0.5, < 3.2) minitest-rails minitest-reporters From 217b099c254b058f8806c08e6c6ae54486cd55c8 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Wed, 17 Apr 2019 11:55:50 -0700 Subject: [PATCH 22/49] update form with passenger --- app/controllers/passengers_controller.rb | 2 +- app/views/passengers/_form.html.erb | 12 ++++++------ app/views/passengers/index.html.erb | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/passengers_controller.rb b/app/controllers/passengers_controller.rb index d26780015..3103625bc 100644 --- a/app/controllers/passengers_controller.rb +++ b/app/controllers/passengers_controller.rb @@ -52,7 +52,7 @@ def destroy passenger_id = params[:id] @passenger = Passenger.find_by(id: passenger_id) - unless @task + unless @passenger head :not_found return end diff --git a/app/views/passengers/_form.html.erb b/app/views/passengers/_form.html.erb index fc3d05795..be3d8b338 100644 --- a/app/views/passengers/_form.html.erb +++ b/app/views/passengers/_form.html.erb @@ -1,15 +1,15 @@ -<%= form_with model: @task, class: form_class do |task| %> +<%= form_with model: @passenger, class: form_class do |passenger| %>
    - <%= task.label :name%> - <%= task.text_field :name, placeholder: "Passenger name" %> + <%= passenger.label :name%> + <%= passenger.text_field :name, placeholder: "Passenger name" %>
    - <%= task.label :phone_num %> - <%= task.text_field :phone_num, placeholder: "1234567890" %> + <%= passenger.label :phone_num %> + <%= passenger.text_field :phone_num, placeholder: "1234567890" %>
    - <%= task.submit action_name, class: "button" %> + <%= passenger.submit action_name, class: "button" %> <% end %> \ No newline at end of file diff --git a/app/views/passengers/index.html.erb b/app/views/passengers/index.html.erb index 372e3c8fd..dd749ebe8 100644 --- a/app/views/passengers/index.html.erb +++ b/app/views/passengers/index.html.erb @@ -4,7 +4,7 @@ <%= image_tag "til-the-end.png" %> <%= link_to "passenger.name", passenger_path(passenger.id) %>
    <%= link_to "Edit", edit_passenger_path(passenger.id) %> - <%= link_to "Delete", task_path(task.id), method: :delete, data: { confirm: "Are you sure you want to remove this passenger?" } %> + <%= link_to "Delete", passenger_path(passenger.id), method: :delete, data: { confirm: "Are you sure you want to remove this passenger?" } %> <% end %> From 03b46f246de95b132a412edd360e5f946b38e0a0 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Wed, 17 Apr 2019 12:20:15 -0700 Subject: [PATCH 23/49] Added nav bar and added new page for passenger --- app/views/layouts/application.html.erb | 25 ++++++++++++++++++++++++- app/views/passengers/new.html.erb | 18 ++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 app/views/passengers/new.html.erb diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 692ca547e..6e1f739a4 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -10,6 +10,29 @@ - <%= yield %> + + + +
    + <%= yield %> +
    diff --git a/app/views/passengers/new.html.erb b/app/views/passengers/new.html.erb new file mode 100644 index 000000000..a68c4969b --- /dev/null +++ b/app/views/passengers/new.html.erb @@ -0,0 +1,18 @@ +

    New Passenger Form

    + +<%= form_with model: @passenger, class: 'passenger-form' do |f|%> +

    Please fill out this passenger's information

    + +
    + <%= f.label :name, "Please enter the new passenger" %> + <%= f.text_field :name, placeholder: "Passenger Name" %> +
    + +
    + <%= f.label :phone_num, "Please enter phone number" %> + <%= f.text_field :phone_num, placeholder: "Phone Number"%> +
    + + <%= f.submit "Submit" %> + +<% end %> \ No newline at end of file From 449404acdea1e84bceca47fa3585f5abd67f8787 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Wed, 17 Apr 2019 12:32:02 -0700 Subject: [PATCH 24/49] update show index passenger pages --- app/views/drivers/show.html.erb | 2 +- app/views/passengers/index.html.erb | 2 +- app/views/passengers/show.html.erb | 13 ++++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index c171d16e8..9d32ded07 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -1,7 +1,7 @@

    Driver Details

    - Driver: <%= @driver.name %> + Name: <%= @driver.name %>

    VIN: <%= @driver.vin %> diff --git a/app/views/passengers/index.html.erb b/app/views/passengers/index.html.erb index dd749ebe8..44115d1a5 100644 --- a/app/views/passengers/index.html.erb +++ b/app/views/passengers/index.html.erb @@ -2,7 +2,7 @@ <% @passengers.each do |passenger| %> <%= image_tag "til-the-end.png" %> - <%= link_to "passenger.name", passenger_path(passenger.id) %>
    + <%= link_to passenger.name, passenger_path(passenger.id) %>
    <%= link_to "Edit", edit_passenger_path(passenger.id) %> <%= link_to "Delete", passenger_path(passenger.id), method: :delete, data: { confirm: "Are you sure you want to remove this passenger?" } %> <% end %> diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb index 173e0c19b..d17ae1f58 100644 --- a/app/views/passengers/show.html.erb +++ b/app/views/passengers/show.html.erb @@ -1 +1,12 @@ -

    Passenger Show Page

    \ No newline at end of file +

    Passenger Show Page

    + +

    + Name: <%= @passenger.name %> +

    +

    + Phone number: <%= @passenger.phone_num %> +

    + +<%= link_to "Edit passenger", edit_passenger_path(@passenger.id) %> +<%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> + From 2db398ea2c4db0ca733b8bf84040486ad8b5cb16 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Wed, 17 Apr 2019 15:31:15 -0700 Subject: [PATCH 25/49] add some styling to passengers index page --- app/assets/stylesheets/application.css | 65 ++++++++++++++++++++------ app/views/passengers/index.html.erb | 26 ++++++----- 2 files changed, 65 insertions(+), 26 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index d05ea0f51..a1459762d 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1,15 +1,50 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's - * vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS - * files in this directory. Styles in this file should be added after the last require_* statement. - * It is generally better to create a new file per style scope. - * - *= require_tree . - *= require_self - */ +img { + width: 200px; + height: auto; + display: block; +} + +a { + color: rgb(97, 82, 116); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +nav { + margin: 2.5rem 0 1rem .5rem; + background-color: rgb(97, 82, 116); +} + +nav a { + color: white; + font-family: 'Helvetica', sans-serif; +} + +nav ul { + display: inline; +} + +nav ul li { + display: inline; + margin-left: auto; +} + +ul { +display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* see notes below */ + grid-auto-rows: minmax(200px, auto); + grid-gap: 5rem; +} + +li { +display: flex; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + color: #5d5e5e; + margin: 2rem; + padding: 1rem; +} \ No newline at end of file diff --git a/app/views/passengers/index.html.erb b/app/views/passengers/index.html.erb index 44115d1a5..dcc2b26f0 100644 --- a/app/views/passengers/index.html.erb +++ b/app/views/passengers/index.html.erb @@ -1,12 +1,16 @@ -

    Passengers Index

    +
    +
    +

    Passengers Index

    +
    -<% @passengers.each do |passenger| %> - <%= image_tag "til-the-end.png" %> - <%= link_to passenger.name, passenger_path(passenger.id) %>
    - <%= link_to "Edit", edit_passenger_path(passenger.id) %> - <%= link_to "Delete", passenger_path(passenger.id), method: :delete, data: { confirm: "Are you sure you want to remove this passenger?" } %> -<% end %> - - - <%# <%= passenger.name %> - <%# <%= passenger.phone_num %> \ No newline at end of file +
      + <% @passengers.each do |passenger| %> +
    • + <%= image_tag "til-the-end.png" %> + <%= link_to passenger.name, passenger_path(passenger.id) %> + <%= link_to "Edit", edit_passenger_path(passenger.id) %> + <%= link_to "Delete", passenger_path(passenger.id), method: :delete, data: { confirm: "Are you sure you want to remove this passenger?" } %> + <% end %> +
    • +
    +
    From 9c91bbcc68dee5f8dd51b82c6752523d514ee533 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Wed, 17 Apr 2019 16:26:06 -0700 Subject: [PATCH 26/49] Created trip controller, updated driver model with new methods and updated driver details page --- app/assets/javascripts/trips.js | 2 ++ app/assets/stylesheets/trips.scss | 3 +++ app/controllers/trips_controller.rb | 11 +++++++++++ app/helpers/trips_helper.rb | 2 ++ app/models/driver.rb | 20 ++++++++++++++++++++ app/views/drivers/show.html.erb | 5 +++++ config/routes.rb | 10 +++++++--- test/controllers/trips_controller_test.rb | 13 ++++++++++++- 8 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/trips.js create mode 100644 app/assets/stylesheets/trips.scss create mode 100644 app/controllers/trips_controller.rb create mode 100644 app/helpers/trips_helper.rb diff --git a/app/assets/javascripts/trips.js b/app/assets/javascripts/trips.js new file mode 100644 index 000000000..dee720fac --- /dev/null +++ b/app/assets/javascripts/trips.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/trips.scss b/app/assets/stylesheets/trips.scss new file mode 100644 index 000000000..f1f72ad11 --- /dev/null +++ b/app/assets/stylesheets/trips.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Trips controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb new file mode 100644 index 000000000..989d68911 --- /dev/null +++ b/app/controllers/trips_controller.rb @@ -0,0 +1,11 @@ +class TripsController < ApplicationController + def show + trip_id = params[:id] + + @trip = Trip.find_by(id: trip_id) + + unless @trip + redirect_to passenger_trips_path, :flash => {:error => "Could not find trip with id: #{trip_id}"} + end + end +end diff --git a/app/helpers/trips_helper.rb b/app/helpers/trips_helper.rb new file mode 100644 index 000000000..04f333d46 --- /dev/null +++ b/app/helpers/trips_helper.rb @@ -0,0 +1,2 @@ +module TripsHelper +end diff --git a/app/models/driver.rb b/app/models/driver.rb index ad0d81b5d..34e76c860 100644 --- a/app/models/driver.rb +++ b/app/models/driver.rb @@ -3,4 +3,24 @@ class Driver < ApplicationRecord validates :name, presence: true validates :vin, presence: true, uniqueness: true, length: {is: 17} + + def total_revenue + total_revenue = 0 + + trips.each do |trip| + total_revenue += (trip.cost - 1.65) * 0.8 + end + + return total_revenue + end + + def average_rating + total = 0 + + trips.each do |trip| + total += trip.rating + end + + return total / trips.length + end end diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index c171d16e8..8af2dea58 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -6,6 +6,11 @@

    VIN: <%= @driver.vin %>

    +

    + Average Rating: <%= @driver.average_rating %> +

    +

    + Total Revenue: <%= @driver.total_revenue %> <%= link_to "Edit Driver", edit_driver_path(@driver.id) %> <%= link_to "Delete", driver_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %> diff --git a/config/routes.rb b/config/routes.rb index b786460b8..1eebb788e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,9 @@ Rails.application.routes.draw do - resources :passengers - resources :drivers - resources :trips + resources :passengers do + resources :trips, except: [:index, :new] + end + + resources :drivers do + resources :trips, except: [:index, :new] + end end diff --git a/test/controllers/trips_controller_test.rb b/test/controllers/trips_controller_test.rb index 9f3e6ca84..3225330f5 100644 --- a/test/controllers/trips_controller_test.rb +++ b/test/controllers/trips_controller_test.rb @@ -2,7 +2,18 @@ describe "TripsController" do describe "show" do - # Your tests go here + it "can get a valid trip" do + get passenger_trip_path(trip.id) + + must_respond_with :success + end + + it "will display an error for an invalid trip ID" do + get passenger_trip_path(-1) + + must_respond_with :redirect + expect(flash[:error]).must_equal "Could not find trip with id: -1" + end end describe "edit" do From 2f6e8f21646e318a3b09051ce705400f202df054 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Wed, 17 Apr 2019 17:05:14 -0700 Subject: [PATCH 27/49] add styling to passenger index page & navigation --- app/assets/stylesheets/application.css | 34 +++++++++++++++++----- app/views/layouts/application.html.erb | 39 +++++++++++++------------- app/views/passengers/_form.html.erb | 2 +- app/views/passengers/index.html.erb | 8 ++++-- config/routes.rb | 9 ++++-- 5 files changed, 58 insertions(+), 34 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index a1459762d..233f85556 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1,3 +1,11 @@ +* { + font-family: 'Helvetica', sans-serif; +} + +main { + margin: 2rem 5rem; +} + img { width: 200px; height: auto; @@ -5,7 +13,7 @@ img { } a { - color: rgb(97, 82, 116); + color: rgb(17, 184, 170); text-decoration: none; } @@ -14,13 +22,12 @@ a:hover { } nav { - margin: 2.5rem 0 1rem .5rem; - background-color: rgb(97, 82, 116); + padding: 1.5rem 0 1.5rem 0; + background-color: white; } nav a { - color: white; - font-family: 'Helvetica', sans-serif; + color: rgb(97, 82, 116); } nav ul { @@ -36,7 +43,7 @@ ul { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* see notes below */ grid-auto-rows: minmax(200px, auto); - grid-gap: 5rem; + grid-gap: 1rem 5rem; } li { @@ -44,7 +51,20 @@ display: flex; -ms-flex-direction: column; flex-direction: column; position: relative; - color: #5d5e5e; + color: #141414; margin: 2rem; padding: 1rem; +} + +h4 { + font-size: 1.25rem; +} + +div.actions { + display: flex; + flex-flow: row wrap; +} + +.actions a { + margin-right: 1rem; } \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 6e1f739a4..ed2563314 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -10,26 +10,25 @@ -

    - +
    <%= yield %> diff --git a/app/views/passengers/_form.html.erb b/app/views/passengers/_form.html.erb index be3d8b338..a4bd82496 100644 --- a/app/views/passengers/_form.html.erb +++ b/app/views/passengers/_form.html.erb @@ -6,7 +6,7 @@
    - <%= passenger.label :phone_num %> + <%= passenger.label :phone_num, "Phone number" %> <%= passenger.text_field :phone_num, placeholder: "1234567890" %>
    diff --git a/app/views/passengers/index.html.erb b/app/views/passengers/index.html.erb index dcc2b26f0..640db7baa 100644 --- a/app/views/passengers/index.html.erb +++ b/app/views/passengers/index.html.erb @@ -7,9 +7,11 @@ <% @passengers.each do |passenger| %>
  • <%= image_tag "til-the-end.png" %> - <%= link_to passenger.name, passenger_path(passenger.id) %> - <%= link_to "Edit", edit_passenger_path(passenger.id) %> - <%= link_to "Delete", passenger_path(passenger.id), method: :delete, data: { confirm: "Are you sure you want to remove this passenger?" } %> +

    <%= link_to passenger.name, passenger_path(passenger.id) %>

    +
    + <%= link_to "Edit", edit_passenger_path(passenger.id) %> + <%= link_to "Delete", passenger_path(passenger.id), method: :delete, data: { confirm: "Are you sure you want to remove this passenger?" } %> +
    <% end %>
  • diff --git a/config/routes.rb b/config/routes.rb index b786460b8..91c45157f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,8 @@ Rails.application.routes.draw do - resources :passengers - resources :drivers - resources :trips + resources :passengers do + resources :trips, only: [:index, :new] + end + resources :drivers do + resources :trips, only: [:index, :new] + end end From 859c2a566322ea528c47757b43c9e175dd6e705b Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Wed, 17 Apr 2019 17:39:54 -0700 Subject: [PATCH 28/49] added global styles --- app/assets/stylesheets/application.css | 153 ++++++++++++++++++++++--- app/views/layouts/application.html.erb | 4 + 2 files changed, 142 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index d05ea0f51..6be07bcdd 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1,15 +1,138 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's - * vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS - * files in this directory. Styles in this file should be added after the last require_* statement. - * It is generally better to create a new file per style scope. - * - *= require_tree . - *= require_self - */ +* { + * { + font-family: 'Helvetica', sans-serif; +} + +main { + margin: 2rem 5rem; +} + +img { + width: 200px; + height: auto; + display: block; +} + +a { + color: rgb(17, 184, 170); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +nav { + padding: 1.5rem 0 1.5rem 0; + background-color: white; +} + +nav a { + color: rgb(97, 82, 116); +} + +nav ul { + display: inline; +} + +nav ul li { + display: inline; + margin-left: auto; +} + +ul { +display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* see notes below */ + grid-auto-rows: minmax(200px, auto); + grid-gap: 1rem 5rem; +} + +li { +display: flex; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + color: #141414; + margin: 2rem; + padding: 1rem; +} + +h4 { + font-size: 1.25rem; +} + +div.actions { + display: flex; + flex-flow: row wrap; +} + +.actions a { + margin-right: 1rem; +} + +main { + margin: 2rem 5rem; +} + +img { + width: 200px; + height: auto; + display: block; +} + +a { + color: rgb(17, 184, 170); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +nav { + padding: 1.5rem 0 1.5rem 0; + background-color: white; +} + +nav a { + color: rgb(97, 82, 116); +} + +nav ul { + display: inline; +} + +nav ul li { + display: inline; + margin-left: auto; +} + +ul { +display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* see notes below */ + grid-auto-rows: minmax(200px, auto); + grid-gap: 1rem 5rem; +} + +li { +display: flex; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + color: #141414; + margin: 2rem; + padding: 1rem; +} + +h4 { + font-size: 1.25rem; +} + +div.actions { + display: flex; + flex-flow: row wrap; +} + +.actions a { + margin-right: 1rem; +} \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 6e1f739a4..70a6edd05 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -7,6 +7,10 @@ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + + From 2f4e16c29d72d6abe2615751c4010ad96bafd424 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 08:47:14 -0700 Subject: [PATCH 29/49] more styling --- app/assets/stylesheets/application.css | 24 +++++++++++++++++++----- app/controllers/passengers_controller.rb | 6 +++++- app/views/drivers/index.html.erb | 15 +++++++++------ app/views/drivers/new.html.erb | 2 +- app/views/passengers/_form.html.erb | 2 +- app/views/passengers/edit.html.erb | 2 +- app/views/passengers/index.html.erb | 6 +----- config/routes.rb | 7 ------- 8 files changed, 37 insertions(+), 27 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index a780f5476..50e065dc8 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -13,7 +13,7 @@ img { } a { - color: rgb(17, 184, 170); + color: rgb(57, 198, 233); text-decoration: none; } @@ -27,7 +27,7 @@ nav { } nav a { - color: rgb(97, 82, 116); + color: rgb(57, 198, 233); } nav ul { @@ -51,20 +51,34 @@ display: flex; -ms-flex-direction: column; flex-direction: column; position: relative; - color: #141414; + color: #272727; margin: 2rem; padding: 1rem; } h4 { font-size: 1.25rem; + color: #272727; + margin-bottom: 1rem; } div.actions { display: flex; - flex-flow: row wrap; + flex-flow: row wrap; + justify-content: flex-start } .actions a { - margin-right: 1rem; + margin: 1rem 1rem 0 0; +} + +.form { + display: flex; + flex-flow: column wrap; + justify-content: space-evenly; + max-width: 30vw; +} + +.form div { + margin-bottom: 10px; } \ No newline at end of file diff --git a/app/controllers/passengers_controller.rb b/app/controllers/passengers_controller.rb index 3103625bc..ea8f6a8ec 100644 --- a/app/controllers/passengers_controller.rb +++ b/app/controllers/passengers_controller.rb @@ -45,7 +45,11 @@ def create @passenger.save - redirect_to passengers_path + unless @passenger + redirect_to passenger_path(@passenger), flash[:notice] = "Passenger created!" + else + render :new, :flash => { :error => "Could not create passenger" } + end end def destroy diff --git a/app/views/drivers/index.html.erb b/app/views/drivers/index.html.erb index c59441433..a1bc3f097 100644 --- a/app/views/drivers/index.html.erb +++ b/app/views/drivers/index.html.erb @@ -1,11 +1,14 @@

    Drivers

    -
      +
        <% @drivers.each do |driver|%> -
      • - <%= link_to driver.name, driver_path(driver)%> - <%= "VIN Number: #{driver.vin}" %> - <%= link_to "Edit", edit_driver_path(driver)%> - <%= link_to "Delete", driver_path(driver), method: :delete, data: {confirm: "Are you sure?"} %> +
      • + <%= image_tag "til-the-end.png" %> +

        <%= link_to driver.name, driver_path(driver)%>

        +
        + <%= "VIN Number: #{driver.vin}" %> + <%= link_to "Edit", edit_driver_path(driver)%> + <%= link_to "Delete", driver_path(driver), method: :delete, data: {confirm: "Are you sure?"} %> +
      • <%end%>
      diff --git a/app/views/drivers/new.html.erb b/app/views/drivers/new.html.erb index a490d9f29..1c5f8a314 100644 --- a/app/views/drivers/new.html.erb +++ b/app/views/drivers/new.html.erb @@ -1,6 +1,6 @@

      New Driver Form

      -<%= form_with model: @driver, class: 'driver-form' do |f|%> +<%= form_with model: @driver, class: 'form' do |f|%>

      Please fill out this driver's information

      diff --git a/app/views/passengers/_form.html.erb b/app/views/passengers/_form.html.erb index a4bd82496..2e319ea76 100644 --- a/app/views/passengers/_form.html.erb +++ b/app/views/passengers/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_with model: @passenger, class: form_class do |passenger| %> +<%= form_with model: @passenger, class: 'form' do |passenger| %>
      <%= passenger.label :name%> diff --git a/app/views/passengers/edit.html.erb b/app/views/passengers/edit.html.erb index e1b3900bb..41cb54514 100644 --- a/app/views/passengers/edit.html.erb +++ b/app/views/passengers/edit.html.erb @@ -1,6 +1,6 @@

      Edit Passenger Info

      <%= render partial: "form", locals: { - form_class: "edit-passenger", + class: "form", action_name: "Save changes" } %> \ No newline at end of file diff --git a/app/views/passengers/index.html.erb b/app/views/passengers/index.html.erb index 640db7baa..a306ad0e5 100644 --- a/app/views/passengers/index.html.erb +++ b/app/views/passengers/index.html.erb @@ -1,7 +1,4 @@ -
      -
      -

      Passengers Index

      -
      +

      Passengers

        <% @passengers.each do |passenger| %> @@ -15,4 +12,3 @@ <% end %>
      -
      diff --git a/config/routes.rb b/config/routes.rb index fa3e74228..1eebb788e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,16 +1,9 @@ Rails.application.routes.draw do resources :passengers do -<<<<<<< HEAD - resources :trips, only: [:index, :new] - end - resources :drivers do - resources :trips, only: [:index, :new] -======= resources :trips, except: [:index, :new] end resources :drivers do resources :trips, except: [:index, :new] ->>>>>>> 9c91bbcc68dee5f8dd51b82c6752523d514ee533 end end From 6b285c5f33c323f4f94e0273729e9338d5009d39 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 09:27:56 -0700 Subject: [PATCH 30/49] more styling --- app/assets/stylesheets/application.css | 11 ++++++++++- app/views/drivers/show.html.erb | 1 + app/views/passengers/_form.html.erb | 12 ++++++------ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 50e065dc8..f572e568e 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -44,6 +44,7 @@ display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* see notes below */ grid-auto-rows: minmax(200px, auto); grid-gap: 1rem 5rem; + padding: 0; } li { @@ -56,12 +57,20 @@ display: flex; padding: 1rem; } +h1 { + font-size: 2.75rem; + font-weight: 300; +} + h4 { font-size: 1.25rem; - color: #272727; margin-bottom: 1rem; } +h4 a { + color: #272727; +} + div.actions { display: flex; flex-flow: row wrap; diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index c0096341d..3bb27ace0 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -1,3 +1,4 @@ +

      Driver Details

      diff --git a/app/views/passengers/_form.html.erb b/app/views/passengers/_form.html.erb index 2e319ea76..1658001d5 100644 --- a/app/views/passengers/_form.html.erb +++ b/app/views/passengers/_form.html.erb @@ -1,15 +1,15 @@ -<%= form_with model: @passenger, class: 'form' do |passenger| %> +<%= form_with model: @passenger, class: 'form' do |f| %>

      - <%= passenger.label :name%> - <%= passenger.text_field :name, placeholder: "Passenger name" %> + <%= f.label :name%> + <%= f.text_field :name, placeholder: "Passenger name" %>
      - <%= passenger.label :phone_num, "Phone number" %> - <%= passenger.text_field :phone_num, placeholder: "1234567890" %> + <%= f.label :phone_num, "Phone number" %> + <%= f.text_field :phone_num, placeholder: "1234567890" %>
      - <%= passenger.submit action_name, class: "button" %> + <%= f.submit action_name, class: "button" %> <% end %> \ No newline at end of file From be89bccfc298bacf373ee626cc730d722ee9a679 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 10:11:32 -0700 Subject: [PATCH 31/49] add new trip button to passenger show page --- app/views/passengers/show.html.erb | 1 + config/routes.rb | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb index d17ae1f58..2af3bcba5 100644 --- a/app/views/passengers/show.html.erb +++ b/app/views/passengers/show.html.erb @@ -9,4 +9,5 @@ <%= link_to "Edit passenger", edit_passenger_path(@passenger.id) %> <%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> +<%= link_to "New trip", new_passenger_trip_path(@passenger.id) %> diff --git a/config/routes.rb b/config/routes.rb index 1eebb788e..cff51bad1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,9 @@ Rails.application.routes.draw do resources :passengers do - resources :trips, except: [:index, :new] + resources :trips, only: [:index, :new] end resources :drivers do - resources :trips, except: [:index, :new] + resources :trips, only: [:index, :new] end end From 6404e69653b26146800dc39e97d6a64b3f9e6f35 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Thu, 18 Apr 2019 10:11:46 -0700 Subject: [PATCH 32/49] Added Trips to driver details page --- app/views/drivers/show.html.erb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index 3bb27ace0..52c6efb56 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -16,3 +16,14 @@ <%= link_to "Edit Driver", edit_driver_path(@driver.id) %> <%= link_to "Delete", driver_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %> +

      Trips

      +
        + <% @driver.trips.each do |trip|%> +
      • <%= trip.id %>
      • +
      • <%= trip.driver_id %>
      • +
      • <%= trip.passenger_id %>
      • +
      • <%= trip.date %>
      • +
      • <%= trip.rating %>
      • +
      • <%= trip.cost %>
      • + <% end %> +
      \ No newline at end of file From f60f2be8633c398f6ea3e228a64a5685be2c6af2 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Thu, 18 Apr 2019 14:40:46 -0700 Subject: [PATCH 33/49] Updated passenger detail page to include trips, added error handling to driver --- app/views/drivers/edit.html.erb | 14 ++++++++++++++ app/views/drivers/new.html.erb | 15 +++++++++++++++ app/views/drivers/show.html.erb | 2 +- app/views/passengers/show.html.erb | 11 +++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/app/views/drivers/edit.html.erb b/app/views/drivers/edit.html.erb index c2a1f89b1..e26288dff 100644 --- a/app/views/drivers/edit.html.erb +++ b/app/views/drivers/edit.html.erb @@ -1,5 +1,19 @@

      Edit Driver

      +<% if @driver.errors.messages.any? %> +
      + There were some issues with your submission +
        + <% @driver.errors.messages.each do |column, problem_list| %> + <% problem_list.each do |problem| %> +
      • + <%= column %>: <%= problem %> +
      • + <% end %> + <% end %> +
      +
      +<% end %> <%= form_for @driver do |f| %>

      Please enter the information you would like to edit

      diff --git a/app/views/drivers/new.html.erb b/app/views/drivers/new.html.erb index 1c5f8a314..100f7e5a2 100644 --- a/app/views/drivers/new.html.erb +++ b/app/views/drivers/new.html.erb @@ -1,5 +1,20 @@

      New Driver Form

      +<% if @driver.errors.messages.any? %> +
      + There were some issues with your submission +
        + <% @driver.errors.messages.each do |column, problem_list| %> + <% problem_list.each do |problem| %> +
      • + <%= column %>: <%= problem %> +
      • + <% end %> + <% end %> +
      +
      +<% end %> + <%= form_with model: @driver, class: 'form' do |f|%>

      Please fill out this driver's information

      diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index 52c6efb56..2ff9746b8 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -24,6 +24,6 @@
    • <%= trip.passenger_id %>
    • <%= trip.date %>
    • <%= trip.rating %>
    • -
    • <%= trip.cost %>
    • +
    • $<%= trip.cost %>
    • <% end %>
    \ No newline at end of file diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb index 2af3bcba5..3cab5e0de 100644 --- a/app/views/passengers/show.html.erb +++ b/app/views/passengers/show.html.erb @@ -11,3 +11,14 @@ <%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> <%= link_to "New trip", new_passenger_trip_path(@passenger.id) %> +

    Trips

    +
      + <% @passenger.trips.each do |trip|%> +
    • <%= trip.id %>
    • +
    • <%= trip.driver_id %>
    • +
    • <%= trip.passenger_id %>
    • +
    • <%= trip.date %>
    • +
    • <%= trip.rating %>
    • +
    • $<%= trip.cost %>
    • + <% end %> +
    \ No newline at end of file From 78e14f9f855b9cfe9f0cd1568fdba5e25bcaf33a Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 14:49:17 -0700 Subject: [PATCH 34/49] update request trip path & method --- app/controllers/trips_controller.rb | 32 +++++++++++++++++++++++++++++ app/views/passengers/show.html.erb | 2 +- app/views/trips/new.html.erb | 21 +++++++++++++++++++ config/routes.rb | 2 +- 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 app/views/trips/new.html.erb diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index 989d68911..ec5cb8959 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -8,4 +8,36 @@ def show redirect_to passenger_trips_path, :flash => {:error => "Could not find trip with id: #{trip_id}"} end end + + def new + if params[:passenger_id] + @passenger = Passenger.find_by(id: params[:passenger_id]) + + if @passenger + @trip = @passenger.trips.new + else + head :not_found + return + end + else + @trip = Trip.new + end + end + + def create + @trip = Trip.new(trip_params) + + successful = @trip.save + if successful + redirect_to passenger_trips_path + else + render :new, status: :bad_request + end + end + + private + + def trip_params + return params.require(:trip).permit(:driver_id, :passenger_id) + end end diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb index 2af3bcba5..f57e5bbf1 100644 --- a/app/views/passengers/show.html.erb +++ b/app/views/passengers/show.html.erb @@ -9,5 +9,5 @@ <%= link_to "Edit passenger", edit_passenger_path(@passenger.id) %> <%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> -<%= link_to "New trip", new_passenger_trip_path(@passenger.id) %> +<%= link_to "Request trip", passenger_path(@passenger.id), method: :get %> diff --git a/app/views/trips/new.html.erb b/app/views/trips/new.html.erb new file mode 100644 index 000000000..bebde1f7c --- /dev/null +++ b/app/views/trips/new.html.erb @@ -0,0 +1,21 @@ +

    Add a Trip

    + +<%= form_with model: @trips, class: 'form' do |f|%> +

    Please enter new trip information

    + +
    + <%= f.label :name, "Driver" %> + <%= f.text_field :name, placeholder: "Driver Name" %> +
    + +
    + <%= f.hidden_field :passenger_id %> + +
    + <%= f.label :rating %> + <%= f.text_field :rating, placeholder: ""%> +
    + + <%= f.submit "Submit" %> + +<% end %> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index cff51bad1..3c400a4c1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,6 @@ Rails.application.routes.draw do resources :passengers do - resources :trips, only: [:index, :new] + resources :trips, only: [:index, :new, :create] end resources :drivers do From 21c639e4d22079a2236ca2d039124a00315f6068 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 15:24:38 -0700 Subject: [PATCH 35/49] request trip method --- app/assets/stylesheets/application.css | 1 + app/controllers/trips_controller.rb | 10 +++++-- app/views/drivers/show.html.erb | 36 ++++++++++++++--------- app/views/passengers/show.html.erb | 40 ++++++++++++++++---------- 4 files changed, 57 insertions(+), 30 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index f572e568e..7f7a65294 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -57,6 +57,7 @@ display: flex; padding: 1rem; } + h1 { font-size: 2.75rem; font-weight: 300; diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index ec5cb8959..7ae985444 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -25,11 +25,17 @@ def new end def create - @trip = Trip.new(trip_params) + trip_data = { + passenger_id: params[:passenger_id], + driver_id: 1, + rating: nil + } + + @trip = Trip.new(trip_data) successful = @trip.save if successful - redirect_to passenger_trips_path + redirect_to passenger_path(params[:passenger_id]) else render :new, status: :bad_request end diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index 2ff9746b8..6c6d88103 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -1,8 +1,8 @@

    Driver Details

    - +

    <%= @driver.name %>

    - Name: <%= @driver.name %> + ID: <%= @driver.id %>

    VIN: <%= @driver.vin %> @@ -12,18 +12,28 @@

    Total Revenue: <%= @driver.total_revenue %> +

    <%= link_to "Edit Driver", edit_driver_path(@driver.id) %> -<%= link_to "Delete", driver_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %> +<%= link_to "Delete", driver_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %>

    Trips

    -
      - <% @driver.trips.each do |trip|%> -
    • <%= trip.id %>
    • -
    • <%= trip.driver_id %>
    • -
    • <%= trip.passenger_id %>
    • -
    • <%= trip.date %>
    • -
    • <%= trip.rating %>
    • -
    • $<%= trip.cost %>
    • - <% end %> -
    \ No newline at end of file + + + + + + + + + + <% @driver.trips.each do |trip|%> + + + + + + + + <% end %> +
    Trip IDPassengerDateRatingCost
    <%= trip.id %><%= Passenger.find_by(id: trip.passenger_id).name %><%= trip.date %><%= trip.rating %>$<%= trip.cost %>
    \ No newline at end of file diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb index 99f4ac81f..b8aeccfd3 100644 --- a/app/views/passengers/show.html.erb +++ b/app/views/passengers/show.html.erb @@ -1,24 +1,34 @@ -

    Passenger Show Page

    +

    Passenger Details

    -

    - Name: <%= @passenger.name %> -

    +

    +<%= @passenger.name %> +

    +

    ID: <%= @passenger.id %>

    Phone number: <%= @passenger.phone_num %>

    <%= link_to "Edit passenger", edit_passenger_path(@passenger.id) %> <%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> -<%= link_to "Request trip", passenger_path(@passenger.id), method: :get %> +<%= link_to "Request trip", passenger_trips_path(@passenger.id), method: :post %>

    Trips

    -
      - <% @passenger.trips.each do |trip|%> -
    • <%= trip.id %>
    • -
    • <%= trip.driver_id %>
    • -
    • <%= trip.passenger_id %>
    • -
    • <%= trip.date %>
    • -
    • <%= trip.rating %>
    • -
    • $<%= trip.cost %>
    • - <% end %> -
    \ No newline at end of file + + + + + + + + + + <% @passenger.trips.each do |trip|%> + + + + + + + + <% end %> +
    Trip IDDriverDateRatingCost
    <%= trip.id %><%= Driver.find_by(id: trip.driver_id).name %><%= trip.date %><%= trip.rating %>$<%= trip.cost %>
    \ No newline at end of file From df7ea973f444ef9cf908c81b52d7feae2dde0649 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 15:26:59 -0700 Subject: [PATCH 36/49] add date to trip --- app/controllers/trips_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index 7ae985444..8bfc98997 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -28,7 +28,8 @@ def create trip_data = { passenger_id: params[:passenger_id], driver_id: 1, - rating: nil + rating: nil, + date: Date.today } @trip = Trip.new(trip_data) From d12a4748ddf31582f5ff7f2ee0b2ac45ac84a828 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Thu, 18 Apr 2019 15:40:32 -0700 Subject: [PATCH 37/49] Added status to Driver --- config/routes.rb | 2 +- db/migrate/20190418223620_add_status_to_drivers.rb | 5 +++++ db/schema.rb | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20190418223620_add_status_to_drivers.rb diff --git a/config/routes.rb b/config/routes.rb index cff51bad1..3c400a4c1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,6 @@ Rails.application.routes.draw do resources :passengers do - resources :trips, only: [:index, :new] + resources :trips, only: [:index, :new, :create] end resources :drivers do diff --git a/db/migrate/20190418223620_add_status_to_drivers.rb b/db/migrate/20190418223620_add_status_to_drivers.rb new file mode 100644 index 000000000..6919a7064 --- /dev/null +++ b/db/migrate/20190418223620_add_status_to_drivers.rb @@ -0,0 +1,5 @@ +class AddStatusToDrivers < ActiveRecord::Migration[5.2] + def change + add_column :drivers, :status, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index c6722b8b8..85d6223c8 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.define(version: 2019_04_15_224218) do +ActiveRecord::Schema.define(version: 2019_04_18_223620) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -20,6 +20,7 @@ t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "status" end create_table "passengers", force: :cascade do |t| From 0b5743073fc9717966ec0a815b24bbd4cbd01302 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 15:42:05 -0700 Subject: [PATCH 38/49] add driver and cost to create trip --- app/controllers/trips_controller.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index 8bfc98997..fa3df3131 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -25,11 +25,14 @@ def new end def create + driver = Driver.find_by(status: "available") + trip_data = { passenger_id: params[:passenger_id], - driver_id: 1, rating: nil, - date: Date.today + date: Date.today, + cost: rand(4..120), + driver_id: driver.id, } @trip = Trip.new(trip_data) From b273d1e15c33b576d559fc26cf4cb94cb9a81bfe Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Thu, 18 Apr 2019 15:54:17 -0700 Subject: [PATCH 39/49] migration to update all driver status to available --- db/migrate/20190418224920_update_status_for_drivers.rb | 10 ++++++++++ db/schema.rb | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20190418224920_update_status_for_drivers.rb diff --git a/db/migrate/20190418224920_update_status_for_drivers.rb b/db/migrate/20190418224920_update_status_for_drivers.rb new file mode 100644 index 000000000..86659b4f0 --- /dev/null +++ b/db/migrate/20190418224920_update_status_for_drivers.rb @@ -0,0 +1,10 @@ +class UpdateStatusForDrivers < ActiveRecord::Migration[5.2] + def change + change_column :drivers, :status, :string + + Driver.find_each do |driver| + driver.status = "available" + driver.save! + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 85d6223c8..30e90e2e0 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.define(version: 2019_04_18_223620) do +ActiveRecord::Schema.define(version: 2019_04_18_224920) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" From 76aec5f947a9b585badb236da834ee6dfacef5b7 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 16:34:10 -0700 Subject: [PATCH 40/49] trip destroy method --- app/controllers/trips_controller.rb | 20 ++++++++++++++++++++ app/models/driver.rb | 8 ++++++-- app/models/passenger.rb | 14 ++++++++++++++ app/views/drivers/show.html.erb | 5 ++++- app/views/passengers/show.html.erb | 8 ++++---- config/routes.rb | 2 ++ 6 files changed, 50 insertions(+), 7 deletions(-) diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index fa3df3131..8b54b9659 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -45,6 +45,26 @@ def create end end + def destroy + trip_id = params[:id] + + trip = Trip.find_by(id: trip_id) + + unless trip + head :not_found + return + end + + successful = trip.destroy + + if successful + flash[:info] = "Event deleted" + + redirect_to :back + + end + end + private def trip_params diff --git a/app/models/driver.rb b/app/models/driver.rb index 34e76c860..eb9745995 100644 --- a/app/models/driver.rb +++ b/app/models/driver.rb @@ -8,7 +8,9 @@ def total_revenue total_revenue = 0 trips.each do |trip| - total_revenue += (trip.cost - 1.65) * 0.8 + if trip.cost + total_revenue += (trip.cost - 1.65) * 0.8 + end end return total_revenue @@ -18,7 +20,9 @@ def average_rating total = 0 trips.each do |trip| - total += trip.rating + if trip.rating + total += trip.rating + end end return total / trips.length diff --git a/app/models/passenger.rb b/app/models/passenger.rb index 7d8994524..5d37cc88f 100644 --- a/app/models/passenger.rb +++ b/app/models/passenger.rb @@ -4,4 +4,18 @@ class Passenger < ApplicationRecord # must provide a valid phone number validates :phone_num, presence: true validates :name, presence: true + + + def total_spent + total_spent = 0 + + trips.each do |trip| + if trip.cost + total_spent += trip.cost + end + end + + return total_spent + end + end diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index 6c6d88103..468eb07a0 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -11,7 +11,10 @@ Average Rating: <%= @driver.average_rating %>

    - Total Revenue: <%= @driver.total_revenue %> + Total Revenue: $<%= (@driver.total_revenue).round(2) %> +

    +

    + Status: <%= @driver.status %>

    <%= link_to "Edit Driver", edit_driver_path(@driver.id) %> diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb index b8aeccfd3..3d83933ae 100644 --- a/app/views/passengers/show.html.erb +++ b/app/views/passengers/show.html.erb @@ -3,10 +3,9 @@

    <%= @passenger.name %>

    -

    ID: <%= @passenger.id %>

    -

    - Phone number: <%= @passenger.phone_num %> -

    +

    ID: <%= @passenger.id %>

    +

    Phone number: <%= @passenger.phone_num %>

    +

    Total spent: $<%= (@passenger.total_spent).round(2) %>

    <%= link_to "Edit passenger", edit_passenger_path(@passenger.id) %> <%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> @@ -29,6 +28,7 @@ <%= trip.date %> <%= trip.rating %> $<%= trip.cost %> + <%= link_to "Edit Trip", passenger_trips_path(@passenger.id), method: :post %> <% end %> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 3c400a4c1..e1029dade 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,4 +6,6 @@ resources :drivers do resources :trips, only: [:index, :new] end + + resources :trips, only: [:edit, :update, :destroy] end From 22d696d1188ddd24345df63d02ff83b65ef35e04 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Thu, 18 Apr 2019 22:29:23 -0700 Subject: [PATCH 41/49] reroute passenger trip detail page --- app/assets/stylesheets/application.css | 27 ++++++++++++- app/controllers/passengers_controller.rb | 2 +- app/controllers/trips_controller.rb | 25 +++++++++++- app/views/drivers/show.html.erb | 6 ++- app/views/passengers/show.html.erb | 30 +++------------ app/views/trips/edit.html.erb | 48 ++++++++++++++++++++++++ app/views/trips/index.html.erb | 26 +++++++++++++ app/views/trips/show.html.erb | 26 +++++++++++++ config/routes.rb | 2 +- 9 files changed, 162 insertions(+), 30 deletions(-) create mode 100644 app/views/trips/edit.html.erb create mode 100644 app/views/trips/index.html.erb create mode 100644 app/views/trips/show.html.erb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 7f7a65294..64ae02d69 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -57,6 +57,29 @@ display: flex; padding: 1rem; } +table { + border-collapse: collapse; +} + +tr { + border: 1px solid rgb(192, 192, 192); + border-left: none; + border-right: none; +} + +tr:last-child { + border-bottom: none; +} + +tr:first-child{ + border-top: none; +} + +td, th { + padding: .5rem; + text-align: left; + width: 200px; +} h1 { font-size: 2.75rem; @@ -75,7 +98,9 @@ h4 a { div.actions { display: flex; flex-flow: row wrap; - justify-content: flex-start + justify-content: space-between; + align-items: baseline; + max-width: 15vw; } .actions a { diff --git a/app/controllers/passengers_controller.rb b/app/controllers/passengers_controller.rb index ea8f6a8ec..ed8212752 100644 --- a/app/controllers/passengers_controller.rb +++ b/app/controllers/passengers_controller.rb @@ -25,7 +25,7 @@ def update @passenger = Passenger.find_by(id: params[:id]) unless @passenger - redirect_to passengers_path, :flash => { :error => "Could not find passenger with id: #{passenger_id}" } + redirect_to passengers_path, :flash => { :error => "Could not find passenger with id: #{@passenger.id}" } return end diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index 8b54b9659..9716c24b1 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -1,4 +1,9 @@ class TripsController < ApplicationController + def index + @passenger = Passenger.find_by(id: params[:passenger_id]) + @passenger.trips.all + end + def show trip_id = params[:id] @@ -35,16 +40,34 @@ def create driver_id: driver.id, } + @passenger = Passenger.find(params[:passenger_id]) @trip = Trip.new(trip_data) successful = @trip.save if successful - redirect_to passenger_path(params[:passenger_id]) + redirect_to passenger_path(@passenger) else render :new, status: :bad_request end end + def edit + trip_id = params[:id] + @passenger = Passenger.find(params[:passenger_id]) + + @trip = Trip.find_by(id: trip_id) + end + + def update + @trip = Trip.find_by(id: params[:id]) + + if @trip.update(trip_params) + redirect_to passenger_trips_path(@trip.passenger_id) + else + render :edit, status: :bad_request + end + end + def destroy trip_id = params[:id] diff --git a/app/views/drivers/show.html.erb b/app/views/drivers/show.html.erb index 468eb07a0..400b4d5f7 100644 --- a/app/views/drivers/show.html.erb +++ b/app/views/drivers/show.html.erb @@ -17,8 +17,10 @@ Status: <%= @driver.status %>

    -<%= link_to "Edit Driver", edit_driver_path(@driver.id) %> -<%= link_to "Delete", driver_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %> +
    + <%= link_to "Edit Driver", edit_driver_path(@driver.id) %> + <%= link_to "Delete", driver_path(@driver.id), method: :delete, data: {confirm: "Are you sure?"} %> +

    Trips

    diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb index 3d83933ae..95639aedc 100644 --- a/app/views/passengers/show.html.erb +++ b/app/views/passengers/show.html.erb @@ -7,28 +7,10 @@

    Phone number: <%= @passenger.phone_num %>

    Total spent: $<%= (@passenger.total_spent).round(2) %>

    -<%= link_to "Edit passenger", edit_passenger_path(@passenger.id) %> -<%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> -<%= link_to "Request trip", passenger_trips_path(@passenger.id), method: :post %> +
    + <%= link_to "View trip history", passenger_trips_path(@passenger.id) %> + <%= link_to "Edit passenger", edit_passenger_path(@passenger.id) %> + <%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> + <%= link_to "Request trip", passenger_trips_path(@passenger.id), method: :post %> +
    -

    Trips

    -
    - - - - - - - - - <% @passenger.trips.each do |trip|%> - - - - - - - - <% end %> -
    Trip IDDriverDateRatingCost
    <%= trip.id %><%= Driver.find_by(id: trip.driver_id).name %><%= trip.date %><%= trip.rating %>$<%= trip.cost %><%= link_to "Edit Trip", passenger_trips_path(@passenger.id), method: :post %> -
    \ No newline at end of file diff --git a/app/views/trips/edit.html.erb b/app/views/trips/edit.html.erb new file mode 100644 index 000000000..7e8e09430 --- /dev/null +++ b/app/views/trips/edit.html.erb @@ -0,0 +1,48 @@ +

    Trip Details

    + +<% if @trip.errors.messages.any? %> +
    + There were some issues with your submission +
      + <% @trip.errors.messages.each do |column, problem_list| %> + <% problem_list.each do |problem| %> +
    • + <%= column %>: <%= problem %> +
    • + <% end %> + <% end %> +
    +
    +<% end %> + + + + + + + + + + + + + + + + + +
    Trip IDDriverDateCost
    <%= @trip.id %><%= Driver.find_by(id: @trip.driver_id).name %><%= @trip.date %>$<%= @trip.cost %>
    +
    +
    + <%= form_with model: @trip do |f| %> + + <%= f.label :rating %> + <%= f.text_field :rating %> + + <%= f.submit "Update!", method: :patch %> + <% end %> +
    + + + + diff --git a/app/views/trips/index.html.erb b/app/views/trips/index.html.erb new file mode 100644 index 000000000..4924b7e82 --- /dev/null +++ b/app/views/trips/index.html.erb @@ -0,0 +1,26 @@ +

    Trip Details

    + +

    Trips

    + + + + + + + + + + <% @passenger.trips.each do |trip|%> + + + + + + + + <% end %> +
    Trip IDDriverDateRatingCost
    <%= trip.id %><%= Driver.find_by(id: trip.driver_id).name %><%= trip.date %><%= trip.rating %>$<%= trip.cost %><%= link_to "Edit Trip", edit_passenger_trip_path(id: trip.id) %> +
    + + + diff --git a/app/views/trips/show.html.erb b/app/views/trips/show.html.erb new file mode 100644 index 000000000..8ed05a779 --- /dev/null +++ b/app/views/trips/show.html.erb @@ -0,0 +1,26 @@ +

    Trip Details

    + +<% if @trip.errors.messages.any? %> +
    + There were some issues with your submission +
      + <% @trip.errors.messages.each do |column, problem_list| %> + <% problem_list.each do |problem| %> +
    • + <%= column %>: <%= problem %> +
    • + <% end %> + <% end %> +
    +
    +<% end %> + +<%= form_for @trip do |f| %> +
    + <%= f.label :rating %> + <%= f.text_field :rating, %> +
    + + <%= f.submit "Submit" %> + +<% end %> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index e1029dade..ff7dd59de 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,6 @@ Rails.application.routes.draw do resources :passengers do - resources :trips, only: [:index, :new, :create] + resources :trips, only: [:index, :new, :create, :edit, :update] end resources :drivers do From 56320c5e549a478bc068d658d803d8d23f83c767 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Fri, 19 Apr 2019 10:18:09 -0700 Subject: [PATCH 42/49] add button to update passenger trip --- app/assets/stylesheets/application.css | 11 ++++++++++- app/views/passengers/show.html.erb | 5 ++++- app/views/trips/edit.html.erb | 6 +++++- app/views/trips/index.html.erb | 3 +-- config/routes.rb | 1 + 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 64ae02d69..0cfc574e9 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -62,7 +62,7 @@ table { } tr { - border: 1px solid rgb(192, 192, 192); + border: .5px solid rgb(192, 192, 192); border-left: none; border-right: none; } @@ -116,4 +116,13 @@ div.actions { .form div { margin-bottom: 10px; +} + +input[type=text] { + border-bottom: .5px solid gray; + + height: 1rem; + width: 1vw; + padding: 5px; + margin: 0 .5rem; } \ No newline at end of file diff --git a/app/views/passengers/show.html.erb b/app/views/passengers/show.html.erb index 95639aedc..6ddae6868 100644 --- a/app/views/passengers/show.html.erb +++ b/app/views/passengers/show.html.erb @@ -11,6 +11,9 @@ <%= link_to "View trip history", passenger_trips_path(@passenger.id) %> <%= link_to "Edit passenger", edit_passenger_path(@passenger.id) %> <%= link_to "Delete", passenger_path(@passenger.id), method: :delete, data: {confirm: "Are you sure?"} %> - <%= link_to "Request trip", passenger_trips_path(@passenger.id), method: :post %> + <%# <%= link_to "Request trip", passenger_trips_path(@passenger.id), method: :post %>
    +<%= button_to "Request Trip", passenger_trips_path(@passenger.id) %> +
    +
    diff --git a/app/views/trips/edit.html.erb b/app/views/trips/edit.html.erb index 7e8e09430..1cf0669d8 100644 --- a/app/views/trips/edit.html.erb +++ b/app/views/trips/edit.html.erb @@ -39,10 +39,14 @@ <%= f.label :rating %> <%= f.text_field :rating %> - <%= f.submit "Update!", method: :patch %> + <%= f.submit "Update!", method: :post %> <% end %> +<%= button_to "Update Rating", passenger_trip_path(@passenger.id) %> +
    +
    + diff --git a/app/views/trips/index.html.erb b/app/views/trips/index.html.erb index 4924b7e82..5702079b3 100644 --- a/app/views/trips/index.html.erb +++ b/app/views/trips/index.html.erb @@ -1,6 +1,5 @@ -

    Trip Details

    +

    Trip History

    -

    Trips

    diff --git a/config/routes.rb b/config/routes.rb index ff7dd59de..d574f5b51 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,4 +8,5 @@ end resources :trips, only: [:edit, :update, :destroy] + patch "/passengers/:passenger_id/trips/:id", to: "trips#update" end From 8552a5ac5f67a1277399cbe8dd575a1631f5bd49 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Fri, 19 Apr 2019 10:38:44 -0700 Subject: [PATCH 43/49] Added HomepagesController and added html for homepage --- app/assets/javascripts/homepages.js | 2 ++ app/assets/stylesheets/homepages.scss | 3 +++ app/controllers/homepages_controller.rb | 4 ++++ app/helpers/homepages_helper.rb | 2 ++ app/views/homepages/index.html.erb | 8 ++++++++ app/views/layouts/application.html.erb | 2 +- config/routes.rb | 5 ++++- 7 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/homepages.js create mode 100644 app/assets/stylesheets/homepages.scss create mode 100644 app/controllers/homepages_controller.rb create mode 100644 app/helpers/homepages_helper.rb create mode 100644 app/views/homepages/index.html.erb diff --git a/app/assets/javascripts/homepages.js b/app/assets/javascripts/homepages.js new file mode 100644 index 000000000..dee720fac --- /dev/null +++ b/app/assets/javascripts/homepages.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/homepages.scss b/app/assets/stylesheets/homepages.scss new file mode 100644 index 000000000..2305c36d1 --- /dev/null +++ b/app/assets/stylesheets/homepages.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Homepages controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/homepages_controller.rb b/app/controllers/homepages_controller.rb new file mode 100644 index 000000000..f200c8ac2 --- /dev/null +++ b/app/controllers/homepages_controller.rb @@ -0,0 +1,4 @@ +class HomepagesController < ApplicationController + def index + end +end diff --git a/app/helpers/homepages_helper.rb b/app/helpers/homepages_helper.rb new file mode 100644 index 000000000..4bd8098f3 --- /dev/null +++ b/app/helpers/homepages_helper.rb @@ -0,0 +1,2 @@ +module HomepagesHelper +end diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb new file mode 100644 index 000000000..896011eb6 --- /dev/null +++ b/app/views/homepages/index.html.erb @@ -0,0 +1,8 @@ +
      +
    • + <%= link_to "Passengers", passengers_path %> +
    • +
    • + <%= link_to "Drivers", drivers_path %> +
    • +
    \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 10334634f..741c6d813 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -17,7 +17,7 @@

    - <%= form_with model: @trip do |f| %> + <%= form_for @trip, class: "rating" do |f| %> <%= f.label :rating %> <%= f.text_field :rating %> - <%= f.submit "Update!", method: :post %> + <%= f.submit "Update!"%> <% end %>
    - -<%= button_to "Update Rating", passenger_trip_path(@passenger.id) %> -
    -
    - - - - diff --git a/config/routes.rb b/config/routes.rb index 639df8d58..730045ce0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,6 +10,6 @@ resources :trips, only: [:index, :new] end - resources :trips, only: [:edit, :update, :destroy] + resources :trips patch "/passengers/:passenger_id/trips/:id", to: "trips#update" end From b572d2fd657638e43607ec3654d1f02317576df8 Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Fri, 19 Apr 2019 15:01:37 -0700 Subject: [PATCH 46/49] add rating to strong params --- app/controllers/trips_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index 4f5b68466..081e088da 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -94,6 +94,6 @@ def destroy private def trip_params - return params.require(:trip).permit(:driver_id, :passenger_id) + return params.require(:trip).permit(:driver_id, :passenger_id, :rating) end end From 9b8a125e10ae07aaf9027f797d4d697cf86ca9d3 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Fri, 19 Apr 2019 15:21:57 -0700 Subject: [PATCH 47/49] Updated tests for trip controller --- app/controllers/trips_controller.rb | 11 ++-- config/routes.rb | 2 +- test/controllers/trips_controller_test.rb | 62 +++++++++++++---------- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index e833ade8f..8a96ce937 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -45,7 +45,7 @@ def create successful = @trip.save if successful - redirect_to passenger_path(@passenger) + redirect_to passenger_trips_path(@passenger) else render :new, status: :bad_request end @@ -74,7 +74,7 @@ def update def destroy trip_id = params[:id] - + passenger_id = params[:passenger_id] trip = Trip.find_by(id: trip_id) unless trip @@ -87,18 +87,13 @@ def destroy if successful flash[:info] = "Event deleted" - redirect_to :back + redirect_to passenger_trips_path(passenger_id: passenger_id) end end private def trip_params -<<<<<<< HEAD return params.require(:trip).permit(:driver_id, :passenger_id, :rating) - end -======= - return params.require(:trip).permit(:driver_id, :passenger_id) end ->>>>>>> origin end diff --git a/config/routes.rb b/config/routes.rb index ca4922e49..d876f8727 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,7 +3,7 @@ resources :homepages, only: :index resources :passengers do - resources :trips, only: [:index, :show, :new, :create, :edit, :update] + resources :trips end resources :drivers do diff --git a/test/controllers/trips_controller_test.rb b/test/controllers/trips_controller_test.rb index 78b11055b..5985a141e 100644 --- a/test/controllers/trips_controller_test.rb +++ b/test/controllers/trips_controller_test.rb @@ -66,40 +66,50 @@ update_trip = Trip.find_by(id: trip.id) expect(update_trip.rating).must_equal trip_data[:trip][:rating] end + end - it "will respond with bad request when attempting to edit a nonexistant trip" do + describe "create" do + it "creates a new trip" do passenger = Passenger.create(name: "Test Passenger", phone_num: "2065502929") - patch passenger_trip_path(passenger_id: passenger.id, id: -1) + passenger_id = passenger.id + driver = Driver.create(name: "Test Driver", vin: "01234567890123456", status: "available") + + trip_data = { + passenger_id: passenger.id, driver_id: driver.id, + } + + # Act + expect { + post passenger_trips_path(passenger_id), params: trip_data + }.must_change "Trip.count", +1 # Assert + trip = Trip.last must_respond_with :redirect - expect(flash[:error]).must_equal "Could not find trip with id: -1" - end - end + must_redirect_to passenger_trips_path(trip.passenger_id) - describe "create" do - # it "creates a new trip" do - # passenger = Passenger.create(name: "Test Passenger", phone_num: "2065502929") - # driver = Driver.create(name: "Test Driver", vin: "01234567890123456") - # trip = Trip.create(passenger_id: passenger.id, driver_id: driver.id) - - # # Act - # expect { - # post passenger_trips_path(passenger_id: passenger.id) - # }.must_change "Trip.count", +1 - - # # Assert - # must_respond_with :redirect - # must_redirect_to trips_path - - # trip = Trip.last - # expect(trip.passenger_id).must_equal passenger.id - # expect(trip.driver_id).must_equal driver.id - # expect(trip.rating).must_be_nil - # end + expect(trip.passenger_id).must_equal passenger.id + expect(trip.driver_id).must_equal driver.id + expect(trip.rating).must_be_nil + end end describe "destroy" do - # Your tests go here + it "removes the Trip from the database" do + passenger = Passenger.create(name: "Test Passenger", phone_num: "2065502929") + driver = Driver.create(name: "Test Driver", vin: "01234567890123456") + trip = Trip.create(passenger_id: passenger.id, driver_id: driver.id) + # Act + expect { + delete passenger_trip_path(passenger_id: passenger.id, id: trip.id) + }.must_change "Trip.count", -1 + + # Assert + must_respond_with :redirect + must_redirect_to passenger_trips_path(passenger_id: passenger.id) + + after_trip = Trip.find_by(id: trip.id) + expect(after_trip).must_be_nil + end end end From f29723ce939690539b665b5cd7159f50e939f1fe Mon Sep 17 00:00:00 2001 From: Amy Phung Date: Fri, 19 Apr 2019 16:51:39 -0700 Subject: [PATCH 48/49] final styling --- app/assets/images/ride-connect-logo.png | Bin 0 -> 9698 bytes app/assets/stylesheets/application.css | 57 ++++++++++++++++++++++-- app/controllers/trips_controller.rb | 1 + app/views/drivers/edit.html.erb | 6 +-- app/views/homepages/index.html.erb | 10 ++--- app/views/layouts/application.html.erb | 7 ++- 6 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 app/assets/images/ride-connect-logo.png diff --git a/app/assets/images/ride-connect-logo.png b/app/assets/images/ride-connect-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d5329bf190dc55ecb79376658d3e17a245635a81 GIT binary patch literal 9698 zcmd6NF5R(+AWI_+OSdSE zz{Br;Ufut}{bD}Xb!b+$!+n_|ca%fL4W@|U1@sFF# zVzHXl#=rHo!RGg?JVp5_i=Q^i%M*N;c4;40j;#UAmh#(h;>Z=K*Bv~YG9lpHltF8o;CuqfcECL7BON$Dy#qV@ znl`WlsZim$OR^n(IA@_{>fAYK+!?LOgLAv-ieaZXj}v=i%8?8rw+epob6>lv5_}en zL17`T<|jcyV-zi3W-WcnZyqO5WT6gDZ&)ZYE&?<5MZ7aUwyk=ey2DI3D2(+;+mLN_ z;URQv8y4L*y^rp1%T?mLZ7VpkF{hkN8#CvljDav?(~Q3P_EaC7N!-Dt1suuMRbx{; zb-}Dh=O+Dhuil_g-?Ms|coNHP^f%mcc|^MqrW@CF+&YlUbcI0Ho7_c$GSoT==U zwFOrJmv&xj6xy$yk34su6p>P)o--SC^%NJU(cu$6jTcgn2SPj8%(6Uw^_WXQkoSUA zD6SsS%aqS`qarQpA0k}>57dcXLx)xP=>)_+kU6Ic+>vp^F^c?D=X9v#)KQBu-+;)@ zio`8Btn-$n5jvGK2;NJ$J8D@upk~b{GKO-Z;oQz^W&5@t>&=7``8pP>hA$(DF~}LH z)wc8Dm%K9lkaDv1TVNJfpRdkGRw><6P-|dj|AO79CYLz*1kzj~9=LPHH~_QQjD+Vg zrNV3uHYKZ4ZQM_rRHk6u^(Q-L>;vwxOE%xk!1}ayv{Tk?){!S#oO<#NbrB&KKjL4mxXQH# zf_t<|-N|S&jJo?-+bG+9&%+4C?+ZTZQmB~2AHmYd{@q~Z`NE1iu?TMlcp#=!?Nm7+ z#XI1kzLyT&*!8gPDMNRZS3osh*&;a7cqZZCfsW=+AAu9^;6b3bw8;;b&Wmn`q9zyA z33Gu)(it5n8~=!+n>@;C+70yPd#w8=xrFQc;nF_SeXZt{8(%${zd?<8G)(ldo?mU6 zeE=MA^06-0&IW{V^9ct^cAU2 z5f|%^fENXWQIN#&DYQQ*sF>`PGf}ppj&uIxU}JR1%1l=&%?Ne4{>%XK?&fmpQy4)k z^*HMQCI6-@Z%dl4+rQ)*t&4ZgSh2=?5cqqR0+hC{2&IRj*BdiQ(gZO4d~IOdw*=8* z@Dh$oTzWOpURFlv7!5#KVjf}3kWUuj7$RT*?p*WW8!Jb^JM&smPh&8$?GkJMqiAQ3 zG|!7^qqvZAYE)l%!<1tZhrycTm$0Yf`>V8jm9;69G32^wXu`|iFL9eaqv*j|yvxm5 zjCRMbvx?p7=%2V2@*d{it~PQdPe(&oOwVT_ha}O8V^Iq^5hudj!BQpyMf(lE%Lf`T z)|b{a^Lov*wdDQfe;)s{!fm{nqnPRVUIx$=MVAGP*pIiOi=z_m@tZv_o}VpGw|y^L z{!yj~N+X6;P%;ev<(6x0)YBQ44I7vga&LEXszmtYUIKztV_{A%leN7o4oFe9P(Ubz zs46#XIWrOiUHB}qR⩔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 U3%15TUfRM?SJ76kRPlease enter the information you would like to edit

    - <%= f.label :name, 'Please enter the desired name' %> + <%= f.label :name, 'Name:' %> <%= f.text_field :name %> -
    +
    - <%= f.label 'Please enter the desired VIN number' %> + <%= f.label 'VIN number:' %> <%= f.text_field :vin %>
    diff --git a/app/views/homepages/index.html.erb b/app/views/homepages/index.html.erb index 896011eb6..42cd5a98d 100644 --- a/app/views/homepages/index.html.erb +++ b/app/views/homepages/index.html.erb @@ -1,8 +1,8 @@ -
      -
    • - <%= link_to "Passengers", passengers_path %> +
        +
      • +

        <%= link_to "Passengers", passengers_path %>

      • -
      • - <%= link_to "Drivers", drivers_path %> +
      • +

        <%= link_to "Drivers", drivers_path %>

      \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 741c6d813..cc74e67fe 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -14,11 +14,10 @@ +
      + <%= link_to image_tag('ride-connect-logo.png'), root_path %> - +
      <%= yield %>
      From 69e87bced289597847cee5ac141586acae14d0c4 Mon Sep 17 00:00:00 2001 From: Erica Norris Date: Mon, 22 Apr 2019 08:29:45 -0700 Subject: [PATCH 49/49] Added delete trip to trip index --- app/views/trips/index.html.erb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/trips/index.html.erb b/app/views/trips/index.html.erb index 5702079b3..927bfcb19 100644 --- a/app/views/trips/index.html.erb +++ b/app/views/trips/index.html.erb @@ -17,6 +17,7 @@ <%= trip.rating %> $<%= trip.cost %> <%= link_to "Edit Trip", edit_passenger_trip_path(id: trip.id) %> + <%= link_to "Delete Trip", passenger_trip_path(id: trip.id), method: :delete, data: {confirm: "Are you sure?"} %> <% end %>