From 70f38b07514c46e2d338d17171cc9e8f893bc55f Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Sun, 20 Jun 2021 14:38:10 +0100 Subject: [PATCH 01/21] Update ruby version --- .ruby-version | 2 +- Gemfile | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.ruby-version b/.ruby-version index 9aa34646dc..13d683ccbf 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.0 \ No newline at end of file +3.0.1 \ No newline at end of file diff --git a/Gemfile b/Gemfile index 67b156b339..8b0d0b97b3 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,8 @@ source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } -ruby '2.7.0' +# ruby '2.7.0' +ruby '3.0.1' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.2.4' From f0680750ef1a162e2e4d5b753e1bbc079786b79a Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Mon, 21 Jun 2021 21:28:05 +0100 Subject: [PATCH 02/21] Add docs file containining ERD db img design --- docs/ERDdatabase.png | Bin 0 -> 34858 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/ERDdatabase.png diff --git a/docs/ERDdatabase.png b/docs/ERDdatabase.png new file mode 100644 index 0000000000000000000000000000000000000000..85772010da06c8b558a843e6c6e6c5613d0a440f GIT binary patch literal 34858 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 Date: Thu, 24 Jun 2021 17:31:54 +0100 Subject: [PATCH 03/21] Install gems dependencies, boostrap, devise, pg --- .gitignore | 2 + Gemfile | 10 ++- Gemfile.lock | 225 ++++++++++++++++++++++++++------------------------- 3 files changed, 127 insertions(+), 110 deletions(-) diff --git a/.gitignore b/.gitignore index 18b43c9cd2..b916d63abe 100644 --- a/.gitignore +++ b/.gitignore @@ -19,9 +19,11 @@ /node_modules /yarn-error.log +/Gemfile.lock /public/assets .byebug_history # Ignore master key for decrypting credentials and more. /config/master.key + diff --git a/Gemfile b/Gemfile index 8b0d0b97b3..d7a97350ac 100644 --- a/Gemfile +++ b/Gemfile @@ -7,11 +7,19 @@ ruby '3.0.1' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.2.4' # Use postgresql as the database for Active Record -gem 'pg', '>= 0.18', '< 2.0' +group :development, :test do + gem 'sqlite3' +end + +group :production do + gem 'pg' +end + # Use Puma as the app server gem 'puma', '~> 3.12' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' +gem 'bootstrap', '~> 4.0' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' # See https://github.com/rails/execjs#readme for more supported runtimes diff --git a/Gemfile.lock b/Gemfile.lock index b67d4b3306..1a601133af 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,55 +1,61 @@ GEM remote: https://rubygems.org/ specs: - actioncable (5.2.4.1) - actionpack (= 5.2.4.1) + actioncable (5.2.6) + actionpack (= 5.2.6) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.1) - actionpack (= 5.2.4.1) - actionview (= 5.2.4.1) - activejob (= 5.2.4.1) + actionmailer (5.2.6) + actionpack (= 5.2.6) + actionview (= 5.2.6) + activejob (= 5.2.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.1) - actionview (= 5.2.4.1) - activesupport (= 5.2.4.1) + actionpack (5.2.6) + actionview (= 5.2.6) + activesupport (= 5.2.6) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.1) - activesupport (= 5.2.4.1) + actionview (5.2.6) + activesupport (= 5.2.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.4.1) - activesupport (= 5.2.4.1) + activejob (5.2.6) + activesupport (= 5.2.6) globalid (>= 0.3.6) - activemodel (5.2.4.1) - activesupport (= 5.2.4.1) - activerecord (5.2.4.1) - activemodel (= 5.2.4.1) - activesupport (= 5.2.4.1) + activemodel (5.2.6) + activesupport (= 5.2.6) + activerecord (5.2.6) + activemodel (= 5.2.6) + activesupport (= 5.2.6) arel (>= 9.0) - activestorage (5.2.4.1) - actionpack (= 5.2.4.1) - activerecord (= 5.2.4.1) - marcel (~> 0.3.1) - activesupport (5.2.4.1) + activestorage (5.2.6) + actionpack (= 5.2.6) + activerecord (= 5.2.6) + marcel (~> 1.0.0) + activesupport (5.2.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) arel (9.0.0) - ast (2.4.0) - bcrypt (3.1.13) + ast (2.4.2) + autoprefixer-rails (10.2.5.1) + execjs (> 0) + bcrypt (3.1.16) bindex (0.8.1) - bootsnap (1.4.6) + bootsnap (1.7.5) msgpack (~> 1.0) + bootstrap (4.6.0) + autoprefixer-rails (>= 9.1.0) + popper_js (>= 1.14.3, < 2) + sassc-rails (>= 2.0.0) builder (3.2.4) - byebug (11.1.1) + byebug (11.1.3) coffee-rails (4.2.2) coffee-script (>= 2.2.0) railties (>= 4.0.0) @@ -57,117 +63,110 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.1.6) + concurrent-ruby (1.1.9) crass (1.0.6) - devise (4.7.1) + devise (4.8.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - diff-lcs (1.3) - erubi (1.9.0) - execjs (2.7.0) - ffi (1.12.2) - ffi (1.12.2-x64-mingw32) + diff-lcs (1.4.4) + erubi (1.10.0) + execjs (2.8.1) + ffi (1.15.3) globalid (0.4.2) activesupport (>= 4.2.0) - i18n (1.8.2) + i18n (1.8.10) concurrent-ruby (~> 1.0) - jaro_winkler (1.5.4) - jbuilder (2.10.0) + jbuilder (2.11.2) activesupport (>= 5.0.0) - listen (3.1.5) + listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - ruby_dep (~> 1.2) - loofah (2.4.0) + loofah (2.10.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) 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.4) - mini_mime (1.0.2) - mini_portile2 (2.5.0) - minitest (5.14.0) - msgpack (1.3.3) - msgpack (1.3.3-x64-mingw32) - nio4r (2.5.2) - nokogiri (1.11.1) - mini_portile2 (~> 2.5.0) - racc (~> 1.4) - nokogiri (1.11.1-x64-mingw32) + marcel (1.0.1) + method_source (1.0.0) + mini_mime (1.1.0) + minitest (5.14.4) + msgpack (1.4.2) + nio4r (2.5.7) + nokogiri (1.11.7-x86_64-darwin) racc (~> 1.4) orm_adapter (0.5.0) - parallel (1.19.1) - parser (2.7.0.4) - ast (~> 2.4.0) - pg (1.2.2) - pg (1.2.2-x64-mingw32) + parallel (1.20.1) + parser (3.0.1.1) + ast (~> 2.4.1) + pg (1.2.3) + popper_js (1.16.0) puma (3.12.6) racc (1.5.2) rack (2.2.3) rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.4.1) - actioncable (= 5.2.4.1) - actionmailer (= 5.2.4.1) - actionpack (= 5.2.4.1) - actionview (= 5.2.4.1) - activejob (= 5.2.4.1) - activemodel (= 5.2.4.1) - activerecord (= 5.2.4.1) - activestorage (= 5.2.4.1) - activesupport (= 5.2.4.1) + rails (5.2.6) + actioncable (= 5.2.6) + actionmailer (= 5.2.6) + actionpack (= 5.2.6) + actionview (= 5.2.6) + activejob (= 5.2.6) + activemodel (= 5.2.6) + activerecord (= 5.2.6) + activestorage (= 5.2.6) + activesupport (= 5.2.6) bundler (>= 1.3.0) - railties (= 5.2.4.1) + railties (= 5.2.6) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.3.0) loofah (~> 2.3) - railties (5.2.4.1) - actionpack (= 5.2.4.1) - activesupport (= 5.2.4.1) + railties (5.2.6) + actionpack (= 5.2.6) + activesupport (= 5.2.6) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) - rake (13.0.1) - rb-fsevent (0.10.3) + rake (13.0.3) + rb-fsevent (0.11.0) rb-inotify (0.10.1) ffi (~> 1.0) - responders (3.0.0) + regexp_parser (2.1.1) + responders (3.0.1) actionpack (>= 5.0) railties (>= 5.0) - rexml (3.2.4) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.1) - rspec-support (~> 3.9.1) - rspec-expectations (3.9.1) + rexml (3.2.5) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-support (3.9.2) - rubocop (0.80.1) - jaro_winkler (~> 1.5.1) + rspec-support (~> 3.10.0) + rspec-support (3.10.2) + rubocop (1.17.0) parallel (~> 1.10) - parser (>= 2.7.0.1) + parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) rexml + rubocop-ast (>= 1.7.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.7) - ruby-progressbar (1.10.1) - ruby_dep (1.5.0) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.7.0) + parser (>= 3.0.1.1) + ruby-progressbar (1.11.0) sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -179,53 +178,60 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - spring (2.1.0) + sassc (2.4.0) + ffi (~> 1.9) + sassc-rails (2.1.2) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt + spring (2.1.1) 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) + sprockets-rails (3.2.2) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - thor (1.0.1) + sqlite3 (1.4.2) + thor (1.1.0) thread_safe (0.3.6) tilt (2.0.10) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (1.2.6) + tzinfo (1.2.9) thread_safe (~> 0.1) - tzinfo-data (1.2020.1) - tzinfo (>= 1.0.0) uglifier (4.2.0) execjs (>= 0.3.0, < 3) - unicode-display_width (1.6.1) - warden (1.2.8) - rack (>= 2.0.6) + unicode-display_width (2.0.0) + warden (1.2.9) + rack (>= 2.0.9) web-console (3.7.0) actionview (>= 5.0) activemodel (>= 5.0) bindex (>= 0.4.0) railties (>= 5.0) - websocket-driver (0.7.1) + websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) PLATFORMS - ruby - x64-mingw32 + x86_64-darwin-19 DEPENDENCIES bootsnap (>= 1.1.0) + bootstrap (~> 4.0) byebug coffee-rails (~> 4.2) devise jbuilder (~> 2.5) listen (>= 3.0.5, < 3.2) - pg (>= 0.18, < 2.0) + pg puma (~> 3.12) rails (~> 5.2.4) rspec @@ -233,13 +239,14 @@ DEPENDENCIES sass-rails (~> 5.0) spring spring-watcher-listen (~> 2.0.0) + sqlite3 turbolinks (~> 5) tzinfo-data uglifier (>= 1.3.0) web-console (>= 3.3.0) RUBY VERSION - ruby 2.7.0p0 + ruby 3.0.1p64 BUNDLED WITH - 2.1.2 + 2.2.21 From d980d5221391364ad208d2fd79daaed6e16019cb Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 24 Jun 2021 20:54:43 +0100 Subject: [PATCH 04/21] Configure app with the appropriate gem --- Gemfile | 8 +-- Gemfile.lock | 153 +++++++++++++++++++++++++++------------------------ 2 files changed, 86 insertions(+), 75 deletions(-) diff --git a/Gemfile b/Gemfile index d7a97350ac..165066d88c 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '3.0.1' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 5.2.4' +gem 'rails', '~> 6.1.3', '>= 6.1.3.2' # Use postgresql as the database for Active Record group :development, :test do gem 'sqlite3' @@ -16,9 +16,9 @@ group :production do end # Use Puma as the app server -gem 'puma', '~> 3.12' +gem 'puma', '~> 5.0' # Use SCSS for stylesheets -gem 'sass-rails', '~> 5.0' +gem 'sass-rails', '>= 6' gem 'bootstrap', '~> 4.0' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' @@ -30,7 +30,7 @@ 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' +gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use ActiveModel has_secure_password diff --git a/Gemfile.lock b/Gemfile.lock index 1a601133af..1b0ab03fd3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,48 +1,65 @@ GEM remote: https://rubygems.org/ specs: - actioncable (5.2.6) - actionpack (= 5.2.6) + actioncable (6.1.3.2) + actionpack (= 6.1.3.2) + activesupport (= 6.1.3.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.6) - actionpack (= 5.2.6) - actionview (= 5.2.6) - activejob (= 5.2.6) + actionmailbox (6.1.3.2) + actionpack (= 6.1.3.2) + activejob (= 6.1.3.2) + activerecord (= 6.1.3.2) + activestorage (= 6.1.3.2) + activesupport (= 6.1.3.2) + mail (>= 2.7.1) + actionmailer (6.1.3.2) + actionpack (= 6.1.3.2) + actionview (= 6.1.3.2) + activejob (= 6.1.3.2) + activesupport (= 6.1.3.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.6) - actionview (= 5.2.6) - activesupport (= 5.2.6) - rack (~> 2.0, >= 2.0.8) + actionpack (6.1.3.2) + actionview (= 6.1.3.2) + activesupport (= 6.1.3.2) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.6) - activesupport (= 5.2.6) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.1.3.2) + actionpack (= 6.1.3.2) + activerecord (= 6.1.3.2) + activestorage (= 6.1.3.2) + activesupport (= 6.1.3.2) + nokogiri (>= 1.8.5) + actionview (6.1.3.2) + activesupport (= 6.1.3.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.6) - activesupport (= 5.2.6) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (6.1.3.2) + activesupport (= 6.1.3.2) globalid (>= 0.3.6) - activemodel (5.2.6) - activesupport (= 5.2.6) - activerecord (5.2.6) - activemodel (= 5.2.6) - activesupport (= 5.2.6) - arel (>= 9.0) - activestorage (5.2.6) - actionpack (= 5.2.6) - activerecord (= 5.2.6) + activemodel (6.1.3.2) + activesupport (= 6.1.3.2) + activerecord (6.1.3.2) + activemodel (= 6.1.3.2) + activesupport (= 6.1.3.2) + activestorage (6.1.3.2) + actionpack (= 6.1.3.2) + activejob (= 6.1.3.2) + activerecord (= 6.1.3.2) + activesupport (= 6.1.3.2) marcel (~> 1.0.0) - activesupport (5.2.6) + mini_mime (~> 1.0.2) + activesupport (6.1.3.2) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - arel (9.0.0) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) ast (2.4.2) autoprefixer-rails (10.2.5.1) execjs (> 0) @@ -91,7 +108,7 @@ GEM mini_mime (>= 0.1.1) marcel (1.0.1) method_source (1.0.0) - mini_mime (1.1.0) + mini_mime (1.0.3) minitest (5.14.4) msgpack (1.4.2) nio4r (2.5.7) @@ -103,35 +120,38 @@ GEM ast (~> 2.4.1) pg (1.2.3) popper_js (1.16.0) - puma (3.12.6) + puma (5.3.2) + nio4r (~> 2.0) racc (1.5.2) rack (2.2.3) rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.6) - actioncable (= 5.2.6) - actionmailer (= 5.2.6) - actionpack (= 5.2.6) - actionview (= 5.2.6) - activejob (= 5.2.6) - activemodel (= 5.2.6) - activerecord (= 5.2.6) - activestorage (= 5.2.6) - activesupport (= 5.2.6) - bundler (>= 1.3.0) - railties (= 5.2.6) + rails (6.1.3.2) + actioncable (= 6.1.3.2) + actionmailbox (= 6.1.3.2) + actionmailer (= 6.1.3.2) + actionpack (= 6.1.3.2) + actiontext (= 6.1.3.2) + actionview (= 6.1.3.2) + activejob (= 6.1.3.2) + activemodel (= 6.1.3.2) + activerecord (= 6.1.3.2) + activestorage (= 6.1.3.2) + activesupport (= 6.1.3.2) + bundler (>= 1.15.0) + railties (= 6.1.3.2) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.3.0) loofah (~> 2.3) - railties (5.2.6) - actionpack (= 5.2.6) - activesupport (= 5.2.6) + railties (6.1.3.2) + actionpack (= 6.1.3.2) + activesupport (= 6.1.3.2) method_source rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) + thor (~> 1.0) rainbow (3.0.0) rake (13.0.3) rb-fsevent (0.11.0) @@ -167,17 +187,8 @@ GEM rubocop-ast (1.7.0) parser (>= 3.0.1.1) ruby-progressbar (1.11.0) - 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.1.0) - railties (>= 5.2.0) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) + sass-rails (6.0.0) + sassc-rails (~> 2.1, >= 2.1.1) sassc (2.4.0) ffi (~> 1.9) sassc-rails (2.1.2) @@ -190,7 +201,7 @@ GEM spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) - sprockets (3.7.2) + sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) sprockets-rails (3.2.2) @@ -199,26 +210,26 @@ GEM sprockets (>= 3.0.0) sqlite3 (1.4.2) thor (1.1.0) - thread_safe (0.3.6) tilt (2.0.10) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (1.2.9) - thread_safe (~> 0.1) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) uglifier (4.2.0) execjs (>= 0.3.0, < 3) unicode-display_width (2.0.0) warden (1.2.9) rack (>= 2.0.9) - web-console (3.7.0) - actionview (>= 5.0) - activemodel (>= 5.0) + web-console (4.1.0) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) bindex (>= 0.4.0) - railties (>= 5.0) + railties (>= 6.0.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) + zeitwerk (2.4.2) PLATFORMS x86_64-darwin-19 @@ -229,14 +240,14 @@ DEPENDENCIES byebug coffee-rails (~> 4.2) devise - jbuilder (~> 2.5) + jbuilder (~> 2.7) listen (>= 3.0.5, < 3.2) pg - puma (~> 3.12) - rails (~> 5.2.4) + puma (~> 5.0) + rails (~> 6.1.3, >= 6.1.3.2) rspec rubocop - sass-rails (~> 5.0) + sass-rails (>= 6) spring spring-watcher-listen (~> 2.0.0) sqlite3 From 6ed7b0ab34f1d68c6b5fcddeb13a85de76c86677 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 24 Jun 2021 20:55:20 +0100 Subject: [PATCH 05/21] Create and migrate db schema --- config/routes.rb | 4 +--- db/schema.rb | 10 +++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index d34298b198..dfdb1c3e5c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,6 @@ Rails.application.routes.draw do - - root 'posts#index' - devise_for :users + root 'posts#index' resources :users, only: [:index, :show] resources :posts, only: [:index, :create] do diff --git a/db/schema.rb b/db/schema.rb index 30ee9f3fad..e41dface63 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,11 +2,11 @@ # 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). +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. From 89f8bc12e0c99b36c4f87937715f875e8c1df338 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 24 Jun 2021 23:27:37 +0100 Subject: [PATCH 06/21] Generate friendship model and migrate to db --- app/models/friendship.rb | 4 ++++ db/migrate/20210624220331_create_friendships.rb | 13 +++++++++++++ db/schema.rb | 15 ++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 app/models/friendship.rb create mode 100644 db/migrate/20210624220331_create_friendships.rb diff --git a/app/models/friendship.rb b/app/models/friendship.rb new file mode 100644 index 0000000000..5db5e0cfc8 --- /dev/null +++ b/app/models/friendship.rb @@ -0,0 +1,4 @@ +class Friendship < ApplicationRecord + belongs_to :user + belongs_to :friend +end diff --git a/db/migrate/20210624220331_create_friendships.rb b/db/migrate/20210624220331_create_friendships.rb new file mode 100644 index 0000000000..9351645cef --- /dev/null +++ b/db/migrate/20210624220331_create_friendships.rb @@ -0,0 +1,13 @@ +class CreateFriendships < ActiveRecord::Migration[6.1] + def change + create_table :friendships do |t| + t.integer :friendship_id + t.references :user, null: false, foreign_key: true + t.references :friend, null: false + t.boolean :confirmed + + t.timestamps + end + add_foreign_key :friendships, :users, column: :friend_id + end +end diff --git a/db/schema.rb b/db/schema.rb index e41dface63..05e131fea4 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: 2020_02_04_165841) do +ActiveRecord::Schema.define(version: 2021_06_24_220331) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -25,6 +25,17 @@ t.index ["user_id"], name: "index_comments_on_user_id" end + create_table "friendships", force: :cascade do |t| + t.integer "friendship_id" + t.bigint "user_id", null: false + t.bigint "friend_id", null: false + t.boolean "confirmed" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["friend_id"], name: "index_friendships_on_friend_id" + t.index ["user_id"], name: "index_friendships_on_user_id" + end + create_table "likes", force: :cascade do |t| t.integer "post_id" t.integer "user_id" @@ -54,4 +65,6 @@ t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end + add_foreign_key "friendships", "users" + add_foreign_key "friendships", "users", column: "friend_id" end From 1c4d8a348f1364c1f82b19ff569560f30ef0b9ac Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Fri, 25 Jun 2021 00:33:57 +0100 Subject: [PATCH 07/21] Create has_many in user belong-to in friendship record --- app/models/friendship.rb | 2 +- app/models/user.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/friendship.rb b/app/models/friendship.rb index 5db5e0cfc8..5210d88d1f 100644 --- a/app/models/friendship.rb +++ b/app/models/friendship.rb @@ -1,4 +1,4 @@ class Friendship < ApplicationRecord belongs_to :user - belongs_to :friend + belongs_to :friend, :class_name => "User" end diff --git a/app/models/user.rb b/app/models/user.rb index e97f1363c0..c77bc8e0c3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -9,4 +9,6 @@ class User < ApplicationRecord has_many :posts has_many :comments, dependent: :destroy has_many :likes, dependent: :destroy + has_many :friendships + has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id" end From 710cf35f96c1abb8246856e4f4ffc5741a1ced36 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Fri, 25 Jun 2021 13:20:22 +0100 Subject: [PATCH 08/21] Create a friends method in User model --- app/models/user.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index c77bc8e0c3..5c760686e2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -11,4 +11,12 @@ class User < ApplicationRecord has_many :likes, dependent: :destroy has_many :friendships has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id" -end + + # Helper methods + def friends + friends_array = friendships.map{|friendship| friendship.friend if friendship.confirmed} + friends_array + inverse_friendships.map{|friendship| friendship.user if friendship.confirmed} + friends_array.compact + end + + end From cf1c2a95ae3035b25985d39a5b77553d8c300fed Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Fri, 25 Jun 2021 14:05:32 +0100 Subject: [PATCH 09/21] Add pending freind request and friend request methods --- app/models/user.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/models/user.rb b/app/models/user.rb index 5c760686e2..ca244365ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -19,4 +19,15 @@ def friends friends_array.compact end + # Users who have yet to confirme friend requests + def pending_friends + friendships.map{|friendship| friendship.friend if !friendship.confirmed}.compact end + + # Users who have requested to be friends + def friend_requests + inverse_friendships.map{|friendship| friendship.user if !friendship.confirmed}.compact + end + + +end From 5ea654b05627fd4df1bd7c93a59ab390fecce3d0 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Fri, 25 Jun 2021 14:08:07 +0100 Subject: [PATCH 10/21] Create friend confirmation methods --- app/assets/stylesheets/friendship.scss | 3 +++ app/models/user.rb | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 app/assets/stylesheets/friendship.scss diff --git a/app/assets/stylesheets/friendship.scss b/app/assets/stylesheets/friendship.scss new file mode 100644 index 0000000000..0bc6dcf556 --- /dev/null +++ b/app/assets/stylesheets/friendship.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Friendship controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: https://sass-lang.com/ diff --git a/app/models/user.rb b/app/models/user.rb index ca244365ed..9100fe0c22 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,5 +29,13 @@ def friend_requests inverse_friendships.map{|friendship| friendship.user if !friendship.confirmed}.compact end - + def confirm_friend(user) + friendship = inverse_friendships.find{|friendship| friendship.user == user} + friendship.confirmed = true + friendship.save + end + + def friend?(user) + friends.include?(user) + end end From af8bb13ccd14fae9b2ad86c64431e8052398049d Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Fri, 25 Jun 2021 14:29:13 +0100 Subject: [PATCH 11/21] Update rubocop gem and Fix linters errors --- .rubocop.yml | 5 +++-- Gemfile | 2 +- app/models/friendship.rb | 2 +- app/models/user.rb | 12 ++++++------ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 89f3b6bdbd..d8187c3d53 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,8 @@ AllCops: + NewCops: enable Exclude: - "db/**/*" - - "bin/*" + - "bin/*" - "config/**/*" - "Guardfile" - "Rakefile" @@ -24,7 +25,7 @@ Metrics/AbcSize: Metrics/ClassLength: Max: 150 Metrics/BlockLength: - ExcludedMethods: ["describe"] + IgnoredMethods: ['describe'] Max: 30 Style/Documentation: diff --git a/Gemfile b/Gemfile index 165066d88c..0384aa0c48 100644 --- a/Gemfile +++ b/Gemfile @@ -18,8 +18,8 @@ end # Use Puma as the app server gem 'puma', '~> 5.0' # Use SCSS for stylesheets -gem 'sass-rails', '>= 6' gem 'bootstrap', '~> 4.0' +gem 'sass-rails', '>= 6' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' # See https://github.com/rails/execjs#readme for more supported runtimes diff --git a/app/models/friendship.rb b/app/models/friendship.rb index 5210d88d1f..b334b963e5 100644 --- a/app/models/friendship.rb +++ b/app/models/friendship.rb @@ -1,4 +1,4 @@ class Friendship < ApplicationRecord belongs_to :user - belongs_to :friend, :class_name => "User" + belongs_to :friend, class_name: 'User' end diff --git a/app/models/user.rb b/app/models/user.rb index 9100fe0c22..ee78cbe8ce 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,27 +10,27 @@ class User < ApplicationRecord has_many :comments, dependent: :destroy has_many :likes, dependent: :destroy has_many :friendships - has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id" + has_many :inverse_friendships, class_name: 'Friendship', foreign_key: 'friend_id' # Helper methods def friends - friends_array = friendships.map{|friendship| friendship.friend if friendship.confirmed} - friends_array + inverse_friendships.map{|friendship| friendship.user if friendship.confirmed} + friends_array = friendships.map { |friendship| friendship.friend if friendship.confirmed } + friends_array += inverse_friendships.map { |friendship| friendship.user if friendship.confirmed } friends_array.compact end # Users who have yet to confirme friend requests def pending_friends - friendships.map{|friendship| friendship.friend if !friendship.confirmed}.compact + friendships.map { |friendship| friendship.friend unless friendship.confirmed }.compact end # Users who have requested to be friends def friend_requests - inverse_friendships.map{|friendship| friendship.user if !friendship.confirmed}.compact + inverse_friendships.map { |friendship| friendship.user unless friendship.confirmed }.compact end def confirm_friend(user) - friendship = inverse_friendships.find{|friendship| friendship.user == user} + friendship = inverse_friendships.find { |friend| friend.user == user } friendship.confirmed = true friendship.save end From e0bbe8e21803ba132d4fae8e52c15524624ec7c0 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Fri, 25 Jun 2021 16:43:58 +0100 Subject: [PATCH 12/21] Fix linter issues --- .github/workflows/linters.yml | 36 ----------------------------------- .stylelintrc.json | 8 +------- 2 files changed, 1 insertion(+), 43 deletions(-) delete mode 100644 .github/workflows/linters.yml diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml deleted file mode 100644 index bd44d15a92..0000000000 --- a/.github/workflows/linters.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Linters - -on: pull_request - -env: - FORCE_COLOR: 1 - -jobs: - rubocop: - name: Rubocop - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-ruby@v1 - with: - ruby-version: 2.6.x - - name: Setup Rubocop - run: | - gem install --no-document rubocop:'~>0.81.0' # https://docs.rubocop.org/en/stable/installation/ - [ -f .rubocop.yml ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/ror/.rubocop.yml - - name: Rubocop Report - run: rubocop --color - stylelint: - name: Stylelint - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 - with: - node-version: "12.x" - - name: Setup Stylelint - run: | - npm install --save-dev stylelint@13.3.x stylelint-scss@3.17.x stylelint-config-standard@20.0.x stylelint-csstree-validator - [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/ror/.stylelintrc.json - - name: Stylelint Report - run: npx stylelint "**/*.{css,scss}" \ No newline at end of file diff --git a/.stylelintrc.json b/.stylelintrc.json index c592372ef2..b7b365775d 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,16 +1,10 @@ - { "extends": ["stylelint-config-standard"], "plugins": ["stylelint-scss", "stylelint-csstree-validator"], "rules": { "at-rule-no-unknown": null, "scss/at-rule-no-unknown": true, - "csstree/validator": - { - "properties": { - "width": "| fit-content" - } - } + "csstree/validator": true }, "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css"] } From 43794de51b8b86460b08e76d61426ba3091fa374 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Fri, 25 Jun 2021 17:18:38 +0100 Subject: [PATCH 13/21] Add github workflow folder --- .github/workflows/linters.yml | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/linters.yml diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml new file mode 100644 index 0000000000..150f9c4b75 --- /dev/null +++ b/.github/workflows/linters.yml @@ -0,0 +1,36 @@ +name: Linters + +on: pull_request + +env: + FORCE_COLOR: 1 + +jobs: + rubocop: + name: Rubocop + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-ruby@v1 + with: + ruby-version: 3.0.x + - name: Setup Rubocop + run: | + gem install --no-document rubocop -v '>= 1.0, < 2.0' # https://docs.rubocop.org/en/stable/installation/ + [ -f .rubocop.yml ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/ror/.rubocop.yml + - name: Rubocop Report + run: rubocop --color + stylelint: + name: Stylelint + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: "12.x" + - name: Setup Stylelint + run: | + npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x + [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/ror/.stylelintrc.json + - name: Stylelint Report + run: npx stylelint "**/*.{css,scss}" \ No newline at end of file From 70492d9ae144bbe8a81095a579591105b1b7c9da Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 1 Jul 2021 12:12:26 +0100 Subject: [PATCH 14/21] Implement action allow User invite freind request --- app/controllers/users_controller.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index b0350d70e4..f122cc5606 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -9,4 +9,13 @@ def show @user = User.find(params[:id]) @posts = @user.posts.ordered_by_most_recent end + + def request_friend + request = current_user.friendships.build(friend_id: params['id'], status: false) + request.save + flash[:notice] = 'Friend Request Successfully sent' + redirect_to users_path + end + + end From 538242a12372d677647d30aa981f24ca6bca5428 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 1 Jul 2021 12:20:36 +0100 Subject: [PATCH 15/21] Implement action allow User accept Freind request --- app/controllers/users_controller.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index f122cc5606..1a7c2e2c02 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -17,5 +17,12 @@ def request_friend redirect_to users_path end - + def accept_freind + current_user.accept_freindship(params[:id]) + user = User.find(params[:id]) + + flash[:notice] = "You Accepted #{user.name}'s Freind Request!" + redirect_to users_path + end + end From 2c2939a9b36743f483e549440834186717c649bd Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 1 Jul 2021 12:41:05 +0100 Subject: [PATCH 16/21] Implement action allow User declined or reject Friend request --- app/controllers/users_controller.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 1a7c2e2c02..3790e8ac39 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -18,11 +18,18 @@ def request_friend end def accept_freind - current_user.accept_freindship(params[:id]) + current_user.accept_friendship(params[:id]) user = User.find(params[:id]) - flash[:notice] = "You Accepted #{user.name}'s Freind Request!" + flash[:notice] = "You Accepted #{user.name}'s Friend Request!" redirect_to users_path end + def decline_friend + current_user.decline_friendship(params[:id]) + user = User.find(params[:id]) + + flash[:notice] = "You Declined #{user.name}'s Friends Request" + redirect_to users_path + end end From dee5bc455b211ed2d60896344f1ccfb896165397 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 1 Jul 2021 12:58:16 +0100 Subject: [PATCH 17/21] Modify active record between user and friendship --- app/models/friendship.rb | 3 +++ app/models/user.rb | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/models/friendship.rb b/app/models/friendship.rb index b334b963e5..cbc99ab545 100644 --- a/app/models/friendship.rb +++ b/app/models/friendship.rb @@ -1,4 +1,7 @@ class Friendship < ApplicationRecord + scope :pending_requests, -> { where(status: false) } + scope :accepted_requests, -> { where(status: true) } + belongs_to :user belongs_to :friend, class_name: 'User' end diff --git a/app/models/user.rb b/app/models/user.rb index ee78cbe8ce..428b54f99b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -19,7 +19,7 @@ def friends friends_array.compact end - # Users who have yet to confirme friend requests + # Users who have yet to confirmed friend requests def pending_friends friendships.map { |friendship| friendship.friend unless friendship.confirmed }.compact end @@ -38,4 +38,9 @@ def confirm_friend(user) def friend?(user) friends.include?(user) end + + def decline_friendship(user_id) + request = inverse_friendships.where(user_id: user_id).where(status: false).first + request.destroy + end end From 8ca70daa4c611af6d537fbe5ab63d960570f0693 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 1 Jul 2021 13:19:24 +0100 Subject: [PATCH 18/21] Modify postview & Add button for friendship action for userview --- app/views/posts/_post.html.erb | 37 ++++++++++++++++++---------------- app/views/users/_user.html.erb | 2 ++ app/views/users/show.html.erb | 3 +++ 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/app/views/posts/_post.html.erb b/app/views/posts/_post.html.erb index 271625b734..dc4778b30c 100644 --- a/app/views/posts/_post.html.erb +++ b/app/views/posts/_post.html.erb @@ -1,23 +1,26 @@

  • -
    - <%= link_to post.user.name, user_path(post.user), class: 'post-author' %> -
    -
    - - <%= like_or_dislike_btn(post) %> -
    -
    -

    - <%= post.content %> -

    + <% if current_user == post.user || current_user.friends.include?(post.user)%> +
    + <%= link_to post.user.name, user_path(post.user), class: 'post-author' %> +
    +
    + + <%= like_or_dislike_btn(post) %> +
    + +

    + <%= post.content %> +

    -
    - <%= render partial: 'comments/comment', collection: post.comments %> +
    + <%= render partial: 'comments/comment', collection: post.comments %> - <%= form_for(post.comments.new, url: post_comments_path(post)) do |form| %> - <%= form.text_field :content, id: :comment_content, class: 'form-control', placeholder: 'Add new Comment' %> - <%= form.submit 'Comment', class: 'btn btn-secondary' %> - <% end %> + <%= form_for(post.comments.new, url: post_comments_path(post)) do |form| %> + <%= form.text_field :content, id: :comment_content, class: 'form-control', placeholder: 'Add new Comment' %> + <%= form.submit 'Comment', class: 'btn btn-secondary' %> + <% end %> +
    + <% end %>
  • diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb index e03c4beb3f..e64b7a5469 100644 --- a/app/views/users/_user.html.erb +++ b/app/views/users/_user.html.erb @@ -2,5 +2,7 @@ Name: <%= user.name %> <%= link_to 'See Profile', user_path(user), class: 'profile-link' %> + + <%= request_status(user) %> \ No newline at end of file diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index e9919805de..ec37835ba1 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,5 +1,8 @@

    <%= "Name: #{@user.name}" %>

    + + <%= request_status(@user)%> +

    Recent posts:

      From 4f10d01c7b5b08a35828fb1d6a3a2c36b01e0a08 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 1 Jul 2021 14:06:56 +0100 Subject: [PATCH 19/21] Set-up gem and install RSpec and Capybara --- Gemfile | 11 +++++ Gemfile.lock | 33 ++++++++++++++ spec/rails_helper.rb | 64 +++++++++++++++++++++++++++ spec/spec_helper.rb | 102 +++++++++++++++++++++---------------------- 4 files changed, 158 insertions(+), 52 deletions(-) create mode 100644 spec/rails_helper.rb diff --git a/Gemfile b/Gemfile index 0384aa0c48..e4a9fccccd 100644 --- a/Gemfile +++ b/Gemfile @@ -57,6 +57,17 @@ group :test do gem 'rspec' end +group :development, :test do + # The RSpec testing framework + gem 'rspec-rails' + # Capybara, the library that allows us to interact with the browser using Ruby + gem 'capybara' + # The following gems aids with the nuts and bolts + # of interacting with the browser. + gem 'webdrivers' +end + + group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'listen', '>= 3.0.5', '< 3.2' diff --git a/Gemfile.lock b/Gemfile.lock index 1b0ab03fd3..3f2999e5ac 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,6 +60,8 @@ GEM minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) ast (2.4.2) autoprefixer-rails (10.2.5.1) execjs (> 0) @@ -73,6 +75,15 @@ GEM sassc-rails (>= 2.0.0) builder (3.2.4) byebug (11.1.3) + capybara (3.35.3) + addressable + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + childprocess (3.0.0) coffee-rails (4.2.2) coffee-script (>= 2.2.0) railties (>= 4.0.0) @@ -120,6 +131,7 @@ GEM ast (~> 2.4.1) pg (1.2.3) popper_js (1.16.0) + public_suffix (4.0.6) puma (5.3.2) nio4r (~> 2.0) racc (1.5.2) @@ -174,6 +186,14 @@ GEM rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) + rspec-rails (5.0.1) + actionpack (>= 5.2) + activesupport (>= 5.2) + railties (>= 5.2) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) rspec-support (3.10.2) rubocop (1.17.0) parallel (~> 1.10) @@ -187,6 +207,7 @@ GEM rubocop-ast (1.7.0) parser (>= 3.0.1.1) ruby-progressbar (1.11.0) + rubyzip (2.3.0) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) sassc (2.4.0) @@ -197,6 +218,9 @@ GEM sprockets (> 3.0) sprockets-rails tilt + selenium-webdriver (3.142.7) + childprocess (>= 0.5, < 4.0) + rubyzip (>= 1.2.2) spring (2.1.1) spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) @@ -226,9 +250,15 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) + webdrivers (4.6.0) + nokogiri (~> 1.6) + rubyzip (>= 1.3.0) + selenium-webdriver (>= 3.0, < 4.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) zeitwerk (2.4.2) PLATFORMS @@ -238,6 +268,7 @@ DEPENDENCIES bootsnap (>= 1.1.0) bootstrap (~> 4.0) byebug + capybara coffee-rails (~> 4.2) devise jbuilder (~> 2.7) @@ -246,6 +277,7 @@ DEPENDENCIES puma (~> 5.0) rails (~> 6.1.3, >= 6.1.3.2) rspec + rspec-rails rubocop sass-rails (>= 6) spring @@ -255,6 +287,7 @@ DEPENDENCIES tzinfo-data uglifier (>= 1.3.0) web-console (>= 3.3.0) + webdrivers RUBY VERSION ruby 3.0.1p64 diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 0000000000..00345af7c0 --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,64 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +require 'spec_helper' +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../config/environment', __dir__) +# Prevent database truncation if the environment is production +abort("The Rails environment is running in production mode!") if Rails.env.production? +require 'rspec/rails' +# Add additional requires below this line. Rails is not loaded until this point! + +# Requires supporting ruby files with custom matchers and macros, etc, in +# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are +# run as spec files by default. This means that files in spec/support that end +# in _spec.rb will both be required and run as specs, causing the specs to be +# run twice. It is recommended that you do not name files matching this glob to +# end with _spec.rb. You can configure this pattern with the --pattern +# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. +# +# The following line is provided for convenience purposes. It has the downside +# of increasing the boot-up time by auto-requiring all files in the support +# directory. Alternatively, in the individual `*_spec.rb` files, manually +# require only the support files necessary. +# +# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } + +# Checks for pending migrations and applies them before tests are run. +# If you are not using ActiveRecord, you can remove these lines. +begin + ActiveRecord::Migration.maintain_test_schema! +rescue ActiveRecord::PendingMigrationError => e + puts e.to_s.strip + exit 1 +end +RSpec.configure do |config| + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # You can uncomment this line to turn off ActiveRecord support entirely. + # config.use_active_record = false + + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, type: :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://relishapp.com/rspec/rspec-rails/docs + config.infer_spec_type_from_file_location! + + # Filter lines from Rails gems in backtraces. + config.filter_rails_from_backtrace! + # arbitrary gems may also be filtered via: + # config.filter_gems_from_backtrace("gem name") +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a403ac5360..ce33d66df6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,4 @@ -# This file was generated by the `rspec --init` command. Conventionally, all +# This file was generated by the `rails generate rspec:install` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause # this file to always be loaded, without a need to explicitly require it in any @@ -44,55 +44,53 @@ # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups - # The settings below are suggested to provide a good initial experience - # with RSpec, but feel free to customize to your heart's content. - # # This allows you to limit a spec run to individual examples or groups - # # you care about by tagging them with `:focus` metadata. When nothing - # # is tagged with `:focus`, all examples get run. RSpec also provides - # # aliases for `it`, `describe`, and `context` that include `:focus` - # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - # config.filter_run_when_matching :focus - # - # # Allows RSpec to persist some state between runs in order to support - # # the `--only-failures` and `--next-failure` CLI options. We recommend - # # you configure your source control system to ignore this file. - # config.example_status_persistence_file_path = "spec/examples.txt" - # - # # Limits the available syntax to the non-monkey patched syntax that is - # # recommended. For more details, see: - # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - # config.disable_monkey_patching! - # - # # This setting enables warnings. It's recommended, but in some cases may - # # be too noisy due to issues in dependencies. - # config.warnings = true - # - # # Many RSpec users commonly either run the entire suite or an individual - # # file, and it's useful to allow more verbose output when running an - # # individual spec file. - # if config.files_to_run.one? - # # Use the documentation formatter for detailed output, - # # unless a formatter has already been configured - # # (e.g. via a command-line flag). - # config.default_formatter = "doc" - # end - # - # # Print the 10 slowest examples and example groups at the - # # end of the spec run, to help surface which specs are running - # # particularly slow. - # config.profile_examples = 10 - # - # # Run specs in random order to surface order dependencies. If you find an - # # order dependency and want to debug it, you can fix the order by providing - # # the seed, which is printed after each run. - # # --seed 1234 - # config.order = :random - # - # # Seed global randomization in this process using the `--seed` CLI option. - # # Setting this allows you to use `--seed` to deterministically reproduce - # # test failures related to randomization by passing the same `--seed` value - # # as the one that triggered the failure. - # Kernel.srand config.seed +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # This allows you to limit a spec run to individual examples or groups + # you care about by tagging them with `:focus` metadata. When nothing + # is tagged with `:focus`, all examples get run. RSpec also provides + # aliases for `it`, `describe`, and `context` that include `:focus` + # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + config.filter_run_when_matching :focus + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + config.disable_monkey_patching! + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end end From 94566c579184546eb4b25197e0e5135e66cc3d91 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 1 Jul 2021 15:16:42 +0100 Subject: [PATCH 20/21] Add users unit and integration tests with minor fixes --- app/controllers/users_controller.rb | 2 +- app/models/user.rb | 2 +- spec/user_spec.rb | 149 ++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 spec/user_spec.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3790e8ac39..d2573592b7 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -11,7 +11,7 @@ def show end def request_friend - request = current_user.friendships.build(friend_id: params['id'], status: false) + request = current_user.friendships.build(friend_id: params['id'], confirmed: false) request.save flash[:notice] = 'Friend Request Successfully sent' redirect_to users_path diff --git a/app/models/user.rb b/app/models/user.rb index 428b54f99b..4933e8dff0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -40,7 +40,7 @@ def friend?(user) end def decline_friendship(user_id) - request = inverse_friendships.where(user_id: user_id).where(status: false).first + request = inverse_friendships.where(user_id: user_id).where(confirmed: false).first request.destroy end end diff --git a/spec/user_spec.rb b/spec/user_spec.rb new file mode 100644 index 0000000000..3b6978ff4e --- /dev/null +++ b/spec/user_spec.rb @@ -0,0 +1,149 @@ +require 'rails_helper' + +RSpec.describe User, type: :model do + include Warden::Test::Helpers + Warden.test_mode! + + let(:current_user) { User.create!(name: 'Tester', email: 'test@example.com', password: 'f4k3p455w0rd') } + let(:user) { User.create(name: 'JohnDoe', email: 'johndoe@example.com', password: '123456') } + let(:user2) { User.create(name: 'Ying Yang', email: 'yingyang@example.com', password: '123456') } + + describe 'validations' do + describe 'name' do + it 'must be present' do + user = described_class.new(name: 'John', email: 'john@example.com', password: '123456') + expect(user).to be_valid + user.name = nil + expect(user).to_not be_valid + end + end + + describe 'email' do + it 'must be present' do + user = described_class.new(name: 'John', email: 'john@example.com', password: '123456') + expect(user).to be_valid + user.email = nil + expect(user).to_not be_valid + end + end + + describe 'password' do + it 'must be present' do + user = described_class.new(name: 'John', email: 'john@example.com', password: '123456') + expect(user).to be_valid + user.password = nil + expect(user).to_not be_valid + end + end + end + + describe 'associations' do + it 'has many posts' do + user = User.reflect_on_association(:posts) + expect(user.macro).to eq(:has_many) + end + + it 'has many comments' do + user = User.reflect_on_association(:comments) + expect(user.macro).to eq(:has_many) + end + + it 'has many likes' do + user = User.reflect_on_association(:likes) + expect(user.macro).to eq(:has_many) + end + + it 'has many sent friendships' do + user = User.reflect_on_association(:friendships) + expect(user.macro).to eq(:has_many) + end + + it 'has many received friendships' do + user = User.reflect_on_association(:inverse_friendships) + expect(user.macro).to eq(:has_many) + end + end + + describe '#pending_friends' do + it 'returns an array' do + login_as(current_user, scope: :user) + + pending_requests = current_user.pending_friends + expect(pending_requests).to be_an Array + end + + # it 'should return an array with status false for all containing object' do + # login_as(current_user, scope: :user) + # current_user.friendships.build(friend_id: user.id, confirmed: false).save + + # pending_requests = current_user.pending_friends + # request_statuses = pending_requests.map do |user| + # user.inverse_friendships.where(user_id: current_user.id).pending_requests.first.confirmed + # end.compact + # expect(request_statuses.all?(false)).to be true + # end + end + + describe '#friends' do + it 'returns an array' do + login_as(current_user, scope: :user) + + requests = current_user.friends + expect(requests).to be_an Array + end + + it 'should return an array with status true for all containing object' do + login_as(current_user, scope: :user) + current_user.friendships.build(friend_id: user, confirmed: true).save + user.friendships.build(friend_id: current_user, confirmed: true).save + + requests = current_user.friends + request_statuses = requests.map do |user| + user.friendships.where(friend_id: current_user.id).accepted_requests.first.status + end.compact + expect(request_statuses.all?(true)).to be true + end + end + + describe '#friend_requests' do + it 'returns an array' do + login_as(current_user, scope: :user) + + requests = current_user.friend_requests + expect(requests).to be_an Array + end + + it 'should return an array with status false for all containing object' do + login_as(current_user, scope: :user) + user.friendships.build(friend_id: current_user, confirmed: false).save + user2.friendships.build(friend_id: current_user, confirmed: false).save + + requests = current_user.friend_requests + request_statuses = requests.map do |user| + user.friendships.where(friend_id: current_user).pending_requests.first.confirmed + end.compact + expect(request_statuses.all?(false)).to be true + end + end + + describe '#confirm_friend' do + it 'should change friend request status to true' do + login_as(current_user, scope: :user) + user.friendships.build(friend_id: current_user.id, confirmed: false).save + + current_user.confirm_friend(user) + expect(current_user.friends[0]).to eq user + expect(user.friends[0]).to eq current_user + end + end + + describe '#decline_friendship' do + it 'should change friend request status to true' do + login_as(current_user, scope: :user) + user.friendships.build(friend_id: current_user.id, confirmed: false).save + + current_user.decline_friendship(user.id) + expect(current_user.friends[0]).to be nil + end + end +end \ No newline at end of file From b162375ec2f0937f90aa49a0deea5928f3babf70 Mon Sep 17 00:00:00 2001 From: Daniel Samuel Date: Thu, 1 Jul 2021 15:22:36 +0100 Subject: [PATCH 21/21] Add unit & integration test for friendship --- spec/friendship_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 spec/friendship_spec.rb diff --git a/spec/friendship_spec.rb b/spec/friendship_spec.rb new file mode 100644 index 0000000000..2ca0e7ab8f --- /dev/null +++ b/spec/friendship_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +RSpec.describe User, type: :model do + describe 'associations' do + it 'belongs to a user' do + friendship = Friendship.reflect_on_association(:user) + expect(friendship.macro).to eq(:belongs_to) + end + + it 'belongs to a friend' do + friendship = Friendship.reflect_on_association(:friend) + expect(friendship.macro).to eq(:belongs_to) + end + end +end