From c77d6849682b5cc0d036e26e7e41d44ff239c9c7 Mon Sep 17 00:00:00 2001 From: marikoja Date: Wed, 18 Apr 2018 17:16:32 -0700 Subject: [PATCH 001/320] generated new rails project --- .gitignore | 19 + Gemfile | 72 ++ Gemfile.lock | 236 +++++ Rakefile | 6 + app/assets/config/manifest.js | 3 + app/assets/images/.keep | 0 app/assets/javascripts/application.js | 20 + app/assets/javascripts/cable.js | 13 + app/assets/javascripts/channels/.keep | 0 app/assets/stylesheets/_settings.scss | 869 ++++++++++++++++++ app/assets/stylesheets/application.css | 19 + app/assets/stylesheets/browserslist | 4 + .../stylesheets/foundation_and_overrides.scss | 61 ++ app/channels/application_cable/channel.rb | 4 + app/channels/application_cable/connection.rb | 4 + app/controllers/application_controller.rb | 3 + 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 | 19 + 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 | 38 + bin/spring | 17 + bin/update | 29 + bin/yarn | 11 + config.ru | 5 + config/application.rb | 25 + config/boot.rb | 3 + config/cable.yml | 10 + config/database.yml | 85 ++ config/environment.rb | 5 + config/environments/development.rb | 54 ++ config/environments/production.rb | 91 ++ config/environments/test.rb | 42 + .../application_controller_renderer.rb | 8 + config/initializers/assets.rb | 14 + config/initializers/backtrace_silencers.rb | 7 + 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 | 56 ++ config/routes.rb | 3 + config/secrets.yml | 32 + config/spring.rb | 6 + db/seeds.rb | 7 + 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 + 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 78 files changed, 2259 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 Gemfile.lock 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/_settings.scss create mode 100644 app/assets/stylesheets/application.css create mode 100644 app/assets/stylesheets/browserslist create mode 100644 app/assets/stylesheets/foundation_and_overrides.scss 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/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/application_controller_renderer.rb create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/backtrace_silencers.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/secrets.yml create mode 100644 config/spring.rb create mode 100644 db/seeds.rb 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 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 0000000000..82701fedc8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# 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 + +/node_modules +/yarn-error.log + +.byebug_history diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..8490d0efb5 --- /dev/null +++ b/Gemfile @@ -0,0 +1,72 @@ +source 'https://rubygems.org' + +git_source(:github) do |repo_name| + repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") + "https://github.com/#{repo_name}.git" +end + + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 5.1.6' +# Use postgresql as the database for Active Record +gem 'pg', '>= 0.18', '< 2.0' +# Use Puma as the app server +gem 'puma', '~> 3.7' +# 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 'therubyracer', 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 Capistrano for deployment +# gem 'capistrano-rails', group: :development + +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] + # Adds support for Capybara system testing and selenium driver + gem 'capybara', '~> 2.13' + gem 'selenium-webdriver' +end + +group :development do + # Access an IRB console on exception pages or by using <%= 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 + +# 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' +gem 'foundation-rails' +gem 'normalize-rails' +group :development, :test do + gem 'pry-rails' +end + +group :development do + gem 'better_errors' + gem 'binding_of_caller' +end + +group :test do + gem 'minitest-rails' + gem 'minitest-reporters' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..d528acb17a --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,236 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.1.6) + actionpack (= 5.1.6) + nio4r (~> 2.0) + websocket-driver (~> 0.6.1) + actionmailer (5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.1.6) + actionview (= 5.1.6) + activesupport (= 5.1.6) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.1.6) + activesupport (= 5.1.6) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.1.6) + activesupport (= 5.1.6) + globalid (>= 0.3.6) + activemodel (5.1.6) + activesupport (= 5.1.6) + activerecord (5.1.6) + activemodel (= 5.1.6) + activesupport (= 5.1.6) + arel (~> 8.0) + activesupport (5.1.6) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + ansi (1.5.0) + arel (8.0.0) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + better_errors (2.4.0) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + bindex (0.5.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + builder (3.2.3) + byebug (10.0.2) + capybara (2.18.0) + addressable + mini_mime (>= 0.1.3) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (>= 2.0, < 4.0) + childprocess (0.9.0) + ffi (~> 1.0, >= 1.0.11) + coderay (1.1.2) + concurrent-ruby (1.0.5) + crass (1.0.4) + debug_inspector (0.0.3) + erubi (1.7.1) + execjs (2.7.0) + ffi (1.9.23) + foundation-rails (6.4.3.0) + railties (>= 3.1.0) + sass (>= 3.3.0, < 3.5) + sprockets-es6 (>= 0.9.0) + globalid (0.4.1) + activesupport (>= 4.2.0) + i18n (1.0.1) + concurrent-ruby (~> 1.0) + jbuilder (2.7.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.2) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.0) + mini_mime (>= 0.1.1) + method_source (0.9.0) + mini_mime (1.0.0) + mini_portile2 (2.3.0) + minitest (5.11.3) + minitest-rails (3.0.0) + minitest (~> 5.8) + railties (~> 5.0) + minitest-reporters (1.2.0) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + multi_json (1.13.1) + nio4r (2.3.0) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + normalize-rails (4.1.1) + pg (1.0.0) + pry (0.11.3) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-rails (0.3.6) + pry (>= 0.10.4) + public_suffix (3.0.2) + puma (3.11.4) + rack (2.0.4) + rack-test (1.0.0) + rack (>= 1.0, < 3) + rails (5.1.6) + actioncable (= 5.1.6) + actionmailer (= 5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) + activemodel (= 5.1.6) + activerecord (= 5.1.6) + activesupport (= 5.1.6) + bundler (>= 1.3.0) + railties (= 5.1.6) + 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.1.6) + actionpack (= 5.1.6) + activesupport (= 5.1.6) + method_source + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (12.3.1) + rb-fsevent (0.10.3) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + ruby-progressbar (1.9.0) + ruby_dep (1.5.0) + rubyzip (1.2.1) + sass (3.4.25) + 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.11.0) + childprocess (~> 0.5) + rubyzip (~> 1.2) + 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.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-es6 (0.9.2) + babel-source (>= 5.8.11) + babel-transpiler + sprockets (>= 3.0.0) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + thor (0.20.0) + thread_safe (0.3.6) + tilt (2.0.8) + turbolinks (5.1.1) + turbolinks-source (~> 5.1) + turbolinks-source (5.1.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.1.9) + execjs (>= 0.3.0, < 3) + web-console (3.6.0) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + xpath (3.0.0) + nokogiri (~> 1.8) + +PLATFORMS + ruby + +DEPENDENCIES + better_errors + binding_of_caller + byebug + capybara (~> 2.13) + foundation-rails + jbuilder (~> 2.5) + jquery-rails + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + normalize-rails + pg (>= 0.18, < 2.0) + pry-rails + puma (~> 3.7) + rails (~> 5.1.6) + 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) + +BUNDLED WITH + 1.16.1 diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000000..e85f913914 --- /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 0000000000..b16e53d6d5 --- /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 0000000000..e69de29bb2 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000000..f04673be81 --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,20 @@ +// 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 jquery + +// +//= require rails-ujs +//= require foundation +//= require turbolinks +//= require_tree . + +$(function(){ $(document).foundation(); }); diff --git a/app/assets/javascripts/cable.js b/app/assets/javascripts/cable.js new file mode 100644 index 0000000000..739aa5f022 --- /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 0000000000..e69de29bb2 diff --git a/app/assets/stylesheets/_settings.scss b/app/assets/stylesheets/_settings.scss new file mode 100644 index 0000000000..26f74f9494 --- /dev/null +++ b/app/assets/stylesheets/_settings.scss @@ -0,0 +1,869 @@ +// Foundation for Sites Settings +// ----------------------------- +// +// Table of Contents: +// +// 1. Global +// 2. Breakpoints +// 3. The Grid +// 4. Base Typography +// 5. Typography Helpers +// 6. Abide +// 7. Accordion +// 8. Accordion Menu +// 9. Badge +// 10. Breadcrumbs +// 11. Button +// 12. Button Group +// 13. Callout +// 14. Card +// 15. Close Button +// 16. Drilldown +// 17. Dropdown +// 18. Dropdown Menu +// 19. Flexbox Utilities +// 20. Forms +// 21. Label +// 22. Media Object +// 23. Menu +// 24. Meter +// 25. Off-canvas +// 26. Orbit +// 27. Pagination +// 28. Progress Bar +// 29. Prototype Arrow +// 30. Prototype Border-Box +// 31. Prototype Border-None +// 32. Prototype Bordered +// 33. Prototype Display +// 34. Prototype Font-Styling +// 35. Prototype List-Style-Type +// 36. Prototype Overflow +// 37. Prototype Position +// 38. Prototype Rounded +// 39. Prototype Separator +// 40. Prototype Shadow +// 41. Prototype Sizing +// 42. Prototype Spacing +// 43. Prototype Text-Decoration +// 44. Prototype Text-Transformation +// 45. Prototype Text-Utilities +// 46. Responsive Embed +// 47. Reveal +// 48. Slider +// 49. Switch +// 50. Table +// 51. Tabs +// 52. Thumbnail +// 53. Title Bar +// 54. Tooltip +// 55. Top Bar +// 56. Xy Grid + +@import 'util/util'; + +// 1. Global +// --------- + +$global-font-size: 100%; +$global-width: rem-calc(1200); +$global-lineheight: 1.5; +$foundation-palette: ( + primary: #1779ba, + secondary: #767676, + success: #3adb76, + warning: #ffae00, + alert: #cc4b37, +); +$light-gray: #e6e6e6; +$medium-gray: #cacaca; +$dark-gray: #8a8a8a; +$black: #0a0a0a; +$white: #fefefe; +$body-background: $white; +$body-font-color: $black; +$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; +$body-antialiased: true; +$global-margin: 1rem; +$global-padding: 1rem; +$global-position: 1rem; +$global-weight-normal: normal; +$global-weight-bold: bold; +$global-radius: 0; +$global-menu-padding: 0.7rem 1rem; +$global-menu-nested-margin: 1rem; +$global-text-direction: ltr; +$global-flexbox: true; +$global-prototype-breakpoints: false; +$global-button-cursor: auto; +$global-color-pick-contrast-tolerance: 0; +$print-transparent-backgrounds: true; + +@include add-foundation-colors; + +// 2. Breakpoints +// -------------- + +$breakpoints: ( + small: 0, + medium: 640px, + large: 1024px, + xlarge: 1200px, + xxlarge: 1440px, +); +$print-breakpoint: large; +$breakpoint-classes: (small medium large); + +// 3. The Grid +// ----------- + +$grid-row-width: $global-width; +$grid-column-count: 12; +$grid-column-gutter: ( + small: 20px, + medium: 30px, +); +$grid-column-align-edge: true; +$grid-column-alias: 'columns'; +$block-grid-max: 8; + +// 4. Base Typography +// ------------------ + +$header-font-family: $body-font-family; +$header-font-weight: $global-weight-normal; +$header-font-style: normal; +$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace; +$header-color: inherit; +$header-lineheight: 1.4; +$header-margin-bottom: 0.5rem; +$header-styles: ( + small: ( + 'h1': ('font-size': 24), + 'h2': ('font-size': 20), + 'h3': ('font-size': 19), + 'h4': ('font-size': 18), + 'h5': ('font-size': 17), + 'h6': ('font-size': 16), + ), + medium: ( + 'h1': ('font-size': 48), + 'h2': ('font-size': 40), + 'h3': ('font-size': 31), + 'h4': ('font-size': 25), + 'h5': ('font-size': 20), + 'h6': ('font-size': 16), + ), +); +$header-text-rendering: optimizeLegibility; +$small-font-size: 80%; +$header-small-font-color: $medium-gray; +$paragraph-lineheight: 1.6; +$paragraph-margin-bottom: 1rem; +$paragraph-text-rendering: optimizeLegibility; +$code-color: $black; +$code-font-family: $font-family-monospace; +$code-font-weight: $global-weight-normal; +$code-background: $light-gray; +$code-border: 1px solid $medium-gray; +$code-padding: rem-calc(2 5 1); +$anchor-color: $primary-color; +$anchor-color-hover: scale-color($anchor-color, $lightness: -14%); +$anchor-text-decoration: none; +$anchor-text-decoration-hover: none; +$hr-width: $global-width; +$hr-border: 1px solid $medium-gray; +$hr-margin: rem-calc(20) auto; +$list-lineheight: $paragraph-lineheight; +$list-margin-bottom: $paragraph-margin-bottom; +$list-style-type: disc; +$list-style-position: outside; +$list-side-margin: 1.25rem; +$list-nested-side-margin: 1.25rem; +$defnlist-margin-bottom: 1rem; +$defnlist-term-weight: $global-weight-bold; +$defnlist-term-margin-bottom: 0.3rem; +$blockquote-color: $dark-gray; +$blockquote-padding: rem-calc(9 20 0 19); +$blockquote-border: 1px solid $medium-gray; +$cite-font-size: rem-calc(13); +$cite-color: $dark-gray; +$cite-pseudo-content: '\2014 \0020'; +$keystroke-font: $font-family-monospace; +$keystroke-color: $black; +$keystroke-background: $light-gray; +$keystroke-padding: rem-calc(2 4 0); +$keystroke-radius: $global-radius; +$abbr-underline: 1px dotted $black; + +// 5. Typography Helpers +// --------------------- + +$lead-font-size: $global-font-size * 1.25; +$lead-lineheight: 1.6; +$subheader-lineheight: 1.4; +$subheader-color: $dark-gray; +$subheader-font-weight: $global-weight-normal; +$subheader-margin-top: 0.2rem; +$subheader-margin-bottom: 0.5rem; +$stat-font-size: 2.5rem; + +// 6. Abide +// -------- + +$abide-inputs: true; +$abide-labels: true; +$input-background-invalid: get-color(alert); +$form-label-color-invalid: get-color(alert); +$input-error-color: get-color(alert); +$input-error-font-size: rem-calc(12); +$input-error-font-weight: $global-weight-bold; + +// 7. Accordion +// ------------ + +$accordion-background: $white; +$accordion-plusminus: true; +$accordion-title-font-size: rem-calc(12); +$accordion-item-color: $primary-color; +$accordion-item-background-hover: $light-gray; +$accordion-item-padding: 1.25rem 1rem; +$accordion-content-background: $white; +$accordion-content-border: 1px solid $light-gray; +$accordion-content-color: $body-font-color; +$accordion-content-padding: 1rem; + +// 8. Accordion Menu +// ----------------- + +$accordionmenu-padding: $global-menu-padding; +$accordionmenu-nested-margin: $global-menu-nested-margin; +$accordionmenu-submenu-padding: $accordionmenu-padding; +$accordionmenu-arrows: true; +$accordionmenu-arrow-color: $primary-color; +$accordionmenu-item-background: null; +$accordionmenu-border: null; +$accordionmenu-submenu-toggle-background: null; +$accordion-submenu-toggle-border: $accordionmenu-border; +$accordionmenu-submenu-toggle-width: 40px; +$accordionmenu-submenu-toggle-height: $accordionmenu-submenu-toggle-width; +$accordionmenu-arrow-size: 6px; + +// 9. Badge +// -------- + +$badge-background: $primary-color; +$badge-color: $white; +$badge-color-alt: $black; +$badge-palette: $foundation-palette; +$badge-padding: 0.3em; +$badge-minwidth: 2.1em; +$badge-font-size: 0.6rem; + +// 10. Breadcrumbs +// --------------- + +$breadcrumbs-margin: 0 0 $global-margin 0; +$breadcrumbs-item-font-size: rem-calc(11); +$breadcrumbs-item-color: $primary-color; +$breadcrumbs-item-color-current: $black; +$breadcrumbs-item-color-disabled: $medium-gray; +$breadcrumbs-item-margin: 0.75rem; +$breadcrumbs-item-uppercase: true; +$breadcrumbs-item-separator: true; +$breadcrumbs-item-separator-item: '/'; +$breadcrumbs-item-separator-item-rtl: '\\'; +$breadcrumbs-item-separator-color: $medium-gray; + +// 11. Button +// ---------- + +$button-font-family: inherit; +$button-padding: 0.85em 1em; +$button-margin: 0 0 $global-margin 0; +$button-fill: solid; +$button-background: $primary-color; +$button-background-hover: scale-color($button-background, $lightness: -15%); +$button-color: $white; +$button-color-alt: $black; +$button-radius: $global-radius; +$button-hollow-border-width: 1px; +$button-sizes: ( + tiny: 0.6rem, + small: 0.75rem, + default: 0.9rem, + large: 1.25rem, +); +$button-palette: $foundation-palette; +$button-opacity-disabled: 0.25; +$button-background-hover-lightness: -20%; +$button-hollow-hover-lightness: -50%; +$button-transition: background-color 0.25s ease-out, color 0.25s ease-out; + +// 12. Button Group +// ---------------- + +$buttongroup-margin: 1rem; +$buttongroup-spacing: 1px; +$buttongroup-child-selector: '.button'; +$buttongroup-expand-max: 6; +$buttongroup-radius-on-each: true; + +// 13. Callout +// ----------- + +$callout-background: $white; +$callout-background-fade: 85%; +$callout-border: 1px solid rgba($black, 0.25); +$callout-margin: 0 0 1rem 0; +$callout-padding: 1rem; +$callout-font-color: $body-font-color; +$callout-font-color-alt: $body-background; +$callout-radius: $global-radius; +$callout-link-tint: 30%; + +// 14. Card +// -------- + +$card-background: $white; +$card-font-color: $body-font-color; +$card-divider-background: $light-gray; +$card-border: 1px solid $light-gray; +$card-shadow: none; +$card-border-radius: $global-radius; +$card-padding: $global-padding; +$card-margin-bottom: $global-margin; + +// 15. Close Button +// ---------------- + +$closebutton-position: right top; +$closebutton-offset-horizontal: ( + small: 0.66rem, + medium: 1rem, +); +$closebutton-offset-vertical: ( + small: 0.33em, + medium: 0.5rem, +); +$closebutton-size: ( + small: 1.5em, + medium: 2em, +); +$closebutton-lineheight: 1; +$closebutton-color: $dark-gray; +$closebutton-color-hover: $black; + +// 16. Drilldown +// ------------- + +$drilldown-transition: transform 0.15s linear; +$drilldown-arrows: true; +$drilldown-padding: $global-menu-padding; +$drilldown-nested-margin: 0; +$drilldown-background: $white; +$drilldown-submenu-padding: $drilldown-padding; +$drilldown-submenu-background: $white; +$drilldown-arrow-color: $primary-color; +$drilldown-arrow-size: 6px; + +// 17. Dropdown +// ------------ + +$dropdown-padding: 1rem; +$dropdown-background: $body-background; +$dropdown-border: 1px solid $medium-gray; +$dropdown-font-size: 1rem; +$dropdown-width: 300px; +$dropdown-radius: $global-radius; +$dropdown-sizes: ( + tiny: 100px, + small: 200px, + large: 400px, +); + +// 18. Dropdown Menu +// ----------------- + +$dropdownmenu-arrows: true; +$dropdownmenu-arrow-color: $anchor-color; +$dropdownmenu-arrow-size: 6px; +$dropdownmenu-arrow-padding: 1.5rem; +$dropdownmenu-min-width: 200px; +$dropdownmenu-background: $white; +$dropdownmenu-submenu-background: $dropdownmenu-background; +$dropdownmenu-padding: $global-menu-padding; +$dropdownmenu-nested-margin: 0; +$dropdownmenu-submenu-padding: $dropdownmenu-padding; +$dropdownmenu-border: 1px solid $medium-gray; +$dropdown-menu-item-color-active: get-color(primary); +$dropdown-menu-item-background-active: transparent; + +// 19. Flexbox Utilities +// --------------------- + +$flex-source-ordering-count: 6; +$flexbox-responsive-breakpoints: true; + +// 20. Forms +// --------- + +$fieldset-border: 1px solid $medium-gray; +$fieldset-padding: rem-calc(20); +$fieldset-margin: rem-calc(18 0); +$legend-padding: rem-calc(0 3); +$form-spacing: rem-calc(16); +$helptext-color: $black; +$helptext-font-size: rem-calc(13); +$helptext-font-style: italic; +$input-prefix-color: $black; +$input-prefix-background: $light-gray; +$input-prefix-border: 1px solid $medium-gray; +$input-prefix-padding: 1rem; +$form-label-color: $black; +$form-label-font-size: rem-calc(14); +$form-label-font-weight: $global-weight-normal; +$form-label-line-height: 1.8; +$select-background: $white; +$select-triangle-color: $dark-gray; +$select-radius: $global-radius; +$input-color: $black; +$input-placeholder-color: $medium-gray; +$input-font-family: inherit; +$input-font-size: rem-calc(16); +$input-font-weight: $global-weight-normal; +$input-line-height: $global-lineheight; +$input-background: $white; +$input-background-focus: $white; +$input-background-disabled: $light-gray; +$input-border: 1px solid $medium-gray; +$input-border-focus: 1px solid $dark-gray; +$input-padding: $form-spacing / 2; +$input-shadow: inset 0 1px 2px rgba($black, 0.1); +$input-shadow-focus: 0 0 5px $medium-gray; +$input-cursor-disabled: not-allowed; +$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out; +$input-number-spinners: true; +$input-radius: $global-radius; +$form-button-radius: $global-radius; + +// 21. Label +// --------- + +$label-background: $primary-color; +$label-color: $white; +$label-color-alt: $black; +$label-palette: $foundation-palette; +$label-font-size: 0.8rem; +$label-padding: 0.33333rem 0.5rem; +$label-radius: $global-radius; + +// 22. Media Object +// ---------------- + +$mediaobject-margin-bottom: $global-margin; +$mediaobject-section-padding: $global-padding; +$mediaobject-image-width-stacked: 100%; + +// 23. Menu +// -------- + +$menu-margin: 0; +$menu-nested-margin: $global-menu-nested-margin; +$menu-items-padding: $global-menu-padding; +$menu-simple-margin: 1rem; +$menu-item-color-active: $white; +$menu-item-background-active: get-color(primary); +$menu-icon-spacing: 0.25rem; +$menu-item-background-hover: $light-gray; +$menu-state-back-compat: true; +$menu-centered-back-compat: true; +$menu-icons-back-compat: true; + +// 24. Meter +// --------- + +$meter-height: 1rem; +$meter-radius: $global-radius; +$meter-background: $medium-gray; +$meter-fill-good: $success-color; +$meter-fill-medium: $warning-color; +$meter-fill-bad: $alert-color; + +// 25. Off-canvas +// -------------- + +$offcanvas-sizes: ( + small: 250px, +); +$offcanvas-vertical-sizes: ( + small: 250px, +); +$offcanvas-background: $light-gray; +$offcanvas-shadow: 0 0 10px rgba($black, 0.7); +$offcanvas-inner-shadow-size: 20px; +$offcanvas-inner-shadow-color: rgba($black, 0.25); +$offcanvas-overlay-zindex: 11; +$offcanvas-push-zindex: 12; +$offcanvas-overlap-zindex: 13; +$offcanvas-reveal-zindex: 12; +$offcanvas-transition-length: 0.5s; +$offcanvas-transition-timing: ease; +$offcanvas-fixed-reveal: true; +$offcanvas-exit-background: rgba($white, 0.25); +$maincontent-class: 'off-canvas-content'; + +// 26. Orbit +// --------- + +$orbit-bullet-background: $medium-gray; +$orbit-bullet-background-active: $dark-gray; +$orbit-bullet-diameter: 1.2rem; +$orbit-bullet-margin: 0.1rem; +$orbit-bullet-margin-top: 0.8rem; +$orbit-bullet-margin-bottom: 0.8rem; +$orbit-caption-background: rgba($black, 0.5); +$orbit-caption-padding: 1rem; +$orbit-control-background-hover: rgba($black, 0.5); +$orbit-control-padding: 1rem; +$orbit-control-zindex: 10; + +// 27. Pagination +// -------------- + +$pagination-font-size: rem-calc(14); +$pagination-margin-bottom: $global-margin; +$pagination-item-color: $black; +$pagination-item-padding: rem-calc(3 10); +$pagination-item-spacing: rem-calc(1); +$pagination-radius: $global-radius; +$pagination-item-background-hover: $light-gray; +$pagination-item-background-current: $primary-color; +$pagination-item-color-current: $white; +$pagination-item-color-disabled: $medium-gray; +$pagination-ellipsis-color: $black; +$pagination-mobile-items: false; +$pagination-mobile-current-item: false; +$pagination-arrows: true; + +// 28. Progress Bar +// ---------------- + +$progress-height: 1rem; +$progress-background: $medium-gray; +$progress-margin-bottom: $global-margin; +$progress-meter-background: $primary-color; +$progress-radius: $global-radius; + +// 29. Prototype Arrow +// ------------------- + +$prototype-arrow-directions: ( + down, + up, + right, + left +); +$prototype-arrow-size: 0.4375rem; +$prototype-arrow-color: $black; + +// 30. Prototype Border-Box +// ------------------------ + +$prototype-border-box-breakpoints: $global-prototype-breakpoints; + +// 31. Prototype Border-None +// ------------------------- + +$prototype-border-none-breakpoints: $global-prototype-breakpoints; + +// 32. Prototype Bordered +// ---------------------- + +$prototype-bordered-breakpoints: $global-prototype-breakpoints; +$prototype-border-width: rem-calc(1); +$prototype-border-type: solid; +$prototype-border-color: $medium-gray; + +// 33. Prototype Display +// --------------------- + +$prototype-display-breakpoints: $global-prototype-breakpoints; +$prototype-display: ( + inline, + inline-block, + block, + table, + table-cell +); + +// 34. Prototype Font-Styling +// -------------------------- + +$prototype-font-breakpoints: $global-prototype-breakpoints; +$prototype-wide-letter-spacing: rem-calc(4); +$prototype-font-normal: $global-weight-normal; +$prototype-font-bold: $global-weight-bold; + +// 35. Prototype List-Style-Type +// ----------------------------- + +$prototype-list-breakpoints: $global-prototype-breakpoints; +$prototype-style-type-unordered: ( + disc, + circle, + square +); +$prototype-style-type-ordered: ( + decimal, + lower-alpha, + lower-latin, + lower-roman, + upper-alpha, + upper-latin, + upper-roman +); + +// 36. Prototype Overflow +// ---------------------- + +$prototype-overflow-breakpoints: $global-prototype-breakpoints; +$prototype-overflow: ( + visible, + hidden, + scroll +); + +// 37. Prototype Position +// ---------------------- + +$prototype-position-breakpoints: $global-prototype-breakpoints; +$prototype-position: ( + static, + relative, + absolute, + fixed +); +$prototype-position-z-index: 975; + +// 38. Prototype Rounded +// --------------------- + +$prototype-rounded-breakpoints: $global-prototype-breakpoints; +$prototype-border-radius: rem-calc(3); + +// 39. Prototype Separator +// ----------------------- + +$prototype-separator-breakpoints: $global-prototype-breakpoints; +$prototype-separator-align: center; +$prototype-separator-height: rem-calc(2); +$prototype-separator-width: 3rem; +$prototype-separator-background: $primary-color; +$prototype-separator-margin-top: $global-margin; + +// 40. Prototype Shadow +// -------------------- + +$prototype-shadow-breakpoints: $global-prototype-breakpoints; +$prototype-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16), + 0 2px 10px 0 rgba(0,0,0,.12); + +// 41. Prototype Sizing +// -------------------- + +$prototype-sizing-breakpoints: $global-prototype-breakpoints; +$prototype-sizing: ( + width, + height +); +$prototype-sizes: ( + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100% +); + +// 42. Prototype Spacing +// --------------------- + +$prototype-spacing-breakpoints: $global-prototype-breakpoints; +$prototype-spacers-count: 3; + +// 43. Prototype Text-Decoration +// ----------------------------- + +$prototype-decoration-breakpoints: $global-prototype-breakpoints; +$prototype-text-decoration: ( + overline, + underline, + line-through, +); + +// 44. Prototype Text-Transformation +// --------------------------------- + +$prototype-transformation-breakpoints: $global-prototype-breakpoints; +$prototype-text-transformation: ( + lowercase, + uppercase, + capitalize +); + +// 45. Prototype Text-Utilities +// ---------------------------- + +$prototype-utilities-breakpoints: $global-prototype-breakpoints; +$prototype-text-overflow: ellipsis; + +// 46. Responsive Embed +// -------------------- + +$responsive-embed-margin-bottom: rem-calc(16); +$responsive-embed-ratios: ( + default: 4 by 3, + widescreen: 16 by 9, +); + +// 47. Reveal +// ---------- + +$reveal-background: $white; +$reveal-width: 600px; +$reveal-max-width: $global-width; +$reveal-padding: $global-padding; +$reveal-border: 1px solid $medium-gray; +$reveal-radius: $global-radius; +$reveal-zindex: 1005; +$reveal-overlay-background: rgba($black, 0.45); + +// 48. Slider +// ---------- + +$slider-width-vertical: 0.5rem; +$slider-transition: all 0.2s ease-in-out; +$slider-height: 0.5rem; +$slider-background: $light-gray; +$slider-fill-background: $medium-gray; +$slider-handle-height: 1.4rem; +$slider-handle-width: 1.4rem; +$slider-handle-background: $primary-color; +$slider-opacity-disabled: 0.25; +$slider-radius: $global-radius; + +// 49. Switch +// ---------- + +$switch-background: $medium-gray; +$switch-background-active: $primary-color; +$switch-height: 2rem; +$switch-height-tiny: 1.5rem; +$switch-height-small: 1.75rem; +$switch-height-large: 2.5rem; +$switch-radius: $global-radius; +$switch-margin: $global-margin; +$switch-paddle-background: $white; +$switch-paddle-offset: 0.25rem; +$switch-paddle-radius: $global-radius; +$switch-paddle-transition: all 0.25s ease-out; + +// 50. Table +// --------- + +$table-background: $white; +$table-color-scale: 5%; +$table-border: 1px solid smart-scale($table-background, $table-color-scale); +$table-padding: rem-calc(8 10 10); +$table-hover-scale: 2%; +$table-row-hover: darken($table-background, $table-hover-scale); +$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale); +$table-is-striped: true; +$table-striped-background: smart-scale($table-background, $table-color-scale); +$table-stripe: even; +$table-head-background: smart-scale($table-background, $table-color-scale / 2); +$table-head-row-hover: darken($table-head-background, $table-hover-scale); +$table-foot-background: smart-scale($table-background, $table-color-scale); +$table-foot-row-hover: darken($table-foot-background, $table-hover-scale); +$table-head-font-color: $body-font-color; +$table-foot-font-color: $body-font-color; +$show-header-for-stacked: false; +$table-stack-breakpoint: medium; + +// 51. Tabs +// -------- + +$tab-margin: 0; +$tab-background: $white; +$tab-color: $primary-color; +$tab-background-active: $light-gray; +$tab-active-color: $primary-color; +$tab-item-font-size: rem-calc(12); +$tab-item-background-hover: $white; +$tab-item-padding: 1.25rem 1.5rem; +$tab-expand-max: 6; +$tab-content-background: $white; +$tab-content-border: $light-gray; +$tab-content-color: $body-font-color; +$tab-content-padding: 1rem; + +// 52. Thumbnail +// ------------- + +$thumbnail-border: solid 4px $white; +$thumbnail-margin-bottom: $global-margin; +$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2); +$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5); +$thumbnail-transition: box-shadow 200ms ease-out; +$thumbnail-radius: $global-radius; + +// 53. Title Bar +// ------------- + +$titlebar-background: $black; +$titlebar-color: $white; +$titlebar-padding: 0.5rem; +$titlebar-text-font-weight: bold; +$titlebar-icon-color: $white; +$titlebar-icon-color-hover: $medium-gray; +$titlebar-icon-spacing: 0.25rem; + +// 54. Tooltip +// ----------- + +$has-tip-cursor: help; +$has-tip-font-weight: $global-weight-bold; +$has-tip-border-bottom: dotted 1px $dark-gray; +$tooltip-background-color: $black; +$tooltip-color: $white; +$tooltip-padding: 0.75rem; +$tooltip-max-width: 10rem; +$tooltip-font-size: $small-font-size; +$tooltip-pip-width: 0.75rem; +$tooltip-pip-height: $tooltip-pip-width * 0.866; +$tooltip-radius: $global-radius; + +// 55. Top Bar +// ----------- + +$topbar-padding: 0.5rem; +$topbar-background: $light-gray; +$topbar-submenu-background: $topbar-background; +$topbar-title-spacing: 0.5rem 1rem 0.5rem 0; +$topbar-input-width: 200px; +$topbar-unstack-breakpoint: medium; + +// 56. Xy Grid +// ----------- + +$xy-grid: true; +$grid-container: $global-width; +$grid-columns: 12; +$grid-margin-gutters: ( + small: 20px, + medium: 30px +); +$grid-padding-gutters: $grid-margin-gutters; +$grid-container-padding: $grid-padding-gutters; +$grid-container-max: $global-width; +$xy-block-grid-max: 8; + diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000000..3a38418320 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,19 @@ +/* + * 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 normalize-rails + + * + *= require_tree . + *= require_self + *= require foundation_and_overrides + + */ diff --git a/app/assets/stylesheets/browserslist b/app/assets/stylesheets/browserslist new file mode 100644 index 0000000000..6019618a9a --- /dev/null +++ b/app/assets/stylesheets/browserslist @@ -0,0 +1,4 @@ +last 2 versions +ie >= 9 +Android >= 2.3 +ios >= 7 diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss new file mode 100644 index 0000000000..ed4c5a0ecf --- /dev/null +++ b/app/assets/stylesheets/foundation_and_overrides.scss @@ -0,0 +1,61 @@ +@charset 'utf-8'; + +@import 'settings'; +@import 'foundation'; + +// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package. +// +// @import 'motion-ui/motion-ui'; + +// We include everything by default. To slim your CSS, remove components you don't use. + +@include foundation-global-styles; +@include foundation-xy-grid-classes; +//@include foundation-grid; +//@include foundation-flex-grid; +@include foundation-flex-classes; +@include foundation-typography; +@include foundation-forms; +@include foundation-button; +@include foundation-accordion; +@include foundation-accordion-menu; +@include foundation-badge; +@include foundation-breadcrumbs; +@include foundation-button-group; +@include foundation-callout; +@include foundation-card; +@include foundation-close-button; +@include foundation-menu; +@include foundation-menu-icon; +@include foundation-drilldown-menu; +@include foundation-dropdown; +@include foundation-dropdown-menu; +@include foundation-responsive-embed; +@include foundation-label; +@include foundation-media-object; +@include foundation-off-canvas; +@include foundation-orbit; +@include foundation-pagination; +@include foundation-progress-bar; +@include foundation-slider; +@include foundation-sticky; +@include foundation-reveal; +@include foundation-switch; +@include foundation-table; +@include foundation-tabs; +@include foundation-thumbnail; +@include foundation-title-bar; +@include foundation-tooltip; +@include foundation-top-bar; +@include foundation-visibility-classes; +@include foundation-float-classes; + +// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package. +// +// @include motion-ui-transitions; +// @include motion-ui-animations; +@import 'motion-ui/motion-ui'; +@include motion-ui-transitions; +@include motion-ui-animations; + + diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 0000000000..d672697283 --- /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 0000000000..0ff5442f47 --- /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 0000000000..1c07694e9d --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery with: :exception +end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000000..de6be7945c --- /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 0000000000..a009ace51c --- /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 0000000000..286b2239d1 --- /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 0000000000..10a4cba84d --- /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 0000000000..e69de29bb2 diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000000..cd60004891 --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,19 @@ + + + + + + + <%= content_for?(:title) ? yield(:title) : "Untitled" %> + + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> + <%= csrf_meta_tags %> + + + + + <%= yield %> + + + diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000000..cbd34d2e9d --- /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 0000000000..37f0bddbd7 --- /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 0000000000..66e9889e8b --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000000..5badb2fde0 --- /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 0000000000..d87d5f5781 --- /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 0000000000..78c4e861dc --- /dev/null +++ b/bin/setup @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +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 0000000000..fb2ec2ebb4 --- /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 0000000000..a8e4462f20 --- /dev/null +++ b/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +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') + + 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 0000000000..c2bacef836 --- /dev/null +++ b/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +VENDOR_PATH = File.expand_path('..', __dir__) +Dir.chdir(VENDOR_PATH) do + begin + exec "yarnpkg #{ARGV.join(" ")}" + 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 0000000000..f7ba0b527b --- /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 0000000000..5f6ca0f9b2 --- /dev/null +++ b/config/application.rb @@ -0,0 +1,25 @@ +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 Betsy + 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.1 + + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000000..30f5120df6 --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,3 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 0000000000..3cba994bb2 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: redis://localhost:6379/1 + channel_prefix: betsy_production diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000000..6903bb6083 --- /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: betsy_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: betsy + + # 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: betsy_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: betsy_production + username: betsy + password: <%= ENV['BETSY_DATABASE_PASSWORD'] %> diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000000..426333bb46 --- /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 0000000000..5187e22186 --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,54 @@ +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. + 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.seconds.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # 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 + + # 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 0000000000..9284f84839 --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,91 @@ +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 + + # Attempt to read encrypted secrets from `config/secrets.yml.enc`. + # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or + # `config/secrets.yml.key`. + config.read_encrypted_secrets = 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 + + # 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 = "betsy_#{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 0000000000..8e5cbde533 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,42 @@ +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.seconds.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 + 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/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 0000000000..89d2efab2b --- /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 0000000000..4b828e80cb --- /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 0000000000..59385cdf37 --- /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/cookies_serializer.rb b/config/initializers/cookies_serializer.rb new file mode 100644 index 0000000000..5a6a32d371 --- /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 0000000000..4a994e1e7b --- /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 0000000000..ac033bf9dc --- /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 0000000000..dc1899682b --- /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 0000000000..bbfc3961bf --- /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 0000000000..decc5a8573 --- /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 0000000000..1e19380dcb --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,56 @@ +# 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. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +# preload_app! + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +# before_fork do +# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +# end + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted, this block will be run. If you are using the `preload_app!` +# option, you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, as Ruby +# cannot share connections between processes. +# +# on_worker_boot do +# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +# end +# + +# 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 0000000000..787824f888 --- /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/secrets.yml b/config/secrets.yml new file mode 100644 index 0000000000..179336ff23 --- /dev/null +++ b/config/secrets.yml @@ -0,0 +1,32 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key is used for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! + +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +# You can use `rails secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +# Shared secrets are available across all environments. + +# shared: +# api_key: a1B2c3D4e5F6 + +# Environmental secrets are only available for that specific environment. + +development: + secret_key_base: 147a9afc71e9272434bf1a899380a22ada6e19f31e7bc72d6cdda2eb7e9314b4417149fa46cca133717cd89b5d08e878bed800356f4620eca00a40cde8e068fc + +test: + secret_key_base: 19331df2ba4566119aafe1d5afb6363fa4e4dbe04069bae28395062ee29eaaa72db42fae835a73d64876a0dfe3d46f31112410e57a2de01b3d8b0d57ddebc729 + +# Do not keep production secrets in the unencrypted secrets file. +# Instead, either read values from the environment. +# Or, use `bin/rails secrets:setup` to configure encrypted secrets +# and move the `production:` environment over there. + +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 0000000000..c9119b40c0 --- /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/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000000..1beea2accd --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). +# +# Examples: +# +# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) +# Character.create(name: 'Luke', movie: movies.first) diff --git a/lib/assets/.keep b/lib/assets/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/tasks/.keep b/lib/tasks/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/log/.keep b/log/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package.json b/package.json new file mode 100644 index 0000000000..f874acf437 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "name": "betsy", + "private": true, + "dependencies": {} +} diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000000..2be3af26fc --- /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 0000000000..c08eac0d1d --- /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 0000000000..78a030af22 --- /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 0000000000..e69de29bb2 diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000000..37b576a4a0 --- /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/test/application_system_test_case.rb b/test/application_system_test_case.rb new file mode 100644 index 0000000000..d19212abd5 --- /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 0000000000..e69de29bb2 diff --git a/test/fixtures/.keep b/test/fixtures/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/helpers/.keep b/test/helpers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/integration/.keep b/test/integration/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/mailers/.keep b/test/mailers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/models/.keep b/test/models/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/system/.keep b/test/system/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000000..10594a3248 --- /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 0000000000..e69de29bb2 diff --git a/vendor/.keep b/vendor/.keep new file mode 100644 index 0000000000..e69de29bb2 From 089cf36ac9619b7427215d0c92c3732f0bceb147 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Wed, 18 Apr 2018 18:09:41 -0700 Subject: [PATCH 002/320] adds cart and user models. and associations --- app/models/cart.rb | 4 ++++ app/models/user.rb | 4 ++++ db/migrate/20180419010045_create_users.rb | 12 ++++++++++++ db/migrate/20180419010200_create_carts.rb | 10 ++++++++++ test/fixtures/carts.yml | 9 +++++++++ test/fixtures/users.yml | 13 +++++++++++++ test/models/cart_test.rb | 9 +++++++++ test/models/user_test.rb | 9 +++++++++ 8 files changed, 70 insertions(+) create mode 100644 app/models/cart.rb create mode 100644 app/models/user.rb create mode 100644 db/migrate/20180419010045_create_users.rb create mode 100644 db/migrate/20180419010200_create_carts.rb create mode 100644 test/fixtures/carts.yml create mode 100644 test/fixtures/users.yml create mode 100644 test/models/cart_test.rb create mode 100644 test/models/user_test.rb diff --git a/app/models/cart.rb b/app/models/cart.rb new file mode 100644 index 0000000000..95d3abe178 --- /dev/null +++ b/app/models/cart.rb @@ -0,0 +1,4 @@ +class Cart < ApplicationRecord + has_many :order_items + belongs_to :user +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000000..dbb90c74cf --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,4 @@ +class User < ApplicationRecord + belongs_to :cart + has_many :products +end diff --git a/db/migrate/20180419010045_create_users.rb b/db/migrate/20180419010045_create_users.rb new file mode 100644 index 0000000000..90a2bbdb9a --- /dev/null +++ b/db/migrate/20180419010045_create_users.rb @@ -0,0 +1,12 @@ +class CreateUsers < ActiveRecord::Migration[5.1] + def change + create_table :users do |t| + t.string :name + t.string :email + t.integer :uid + t.string :provider + + t.timestamps + end + end +end diff --git a/db/migrate/20180419010200_create_carts.rb b/db/migrate/20180419010200_create_carts.rb new file mode 100644 index 0000000000..5004883d30 --- /dev/null +++ b/db/migrate/20180419010200_create_carts.rb @@ -0,0 +1,10 @@ +class CreateCarts < ActiveRecord::Migration[5.1] + def change + create_table :carts do |t| + t.integer :user_id + t.string :status + + t.timestamps + end + end +end diff --git a/test/fixtures/carts.yml b/test/fixtures/carts.yml new file mode 100644 index 0000000000..a0701a550c --- /dev/null +++ b/test/fixtures/carts.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + user_id: 1 + status: MyString + +two: + user_id: 1 + status: MyString diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000000..168a2e2888 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + email: MyString + uid: 1 + provider: MyString + +two: + name: MyString + email: MyString + uid: 1 + provider: MyString diff --git a/test/models/cart_test.rb b/test/models/cart_test.rb new file mode 100644 index 0000000000..f2c5bd6f62 --- /dev/null +++ b/test/models/cart_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Cart do + let(:cart) { Cart.new } + + it "must be valid" do + value(cart).must_be :valid? + end +end diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 0000000000..cc862ac2d9 --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe User do + let(:user) { User.new } + + it "must be valid" do + value(user).must_be :valid? + end +end From 9da3dac5ca5aa4f7166a727557aefd0fd50448bb Mon Sep 17 00:00:00 2001 From: Phoebe Date: Wed, 18 Apr 2018 18:10:47 -0700 Subject: [PATCH 003/320] migrated models --- db/schema.rb | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 db/schema.rb diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..a22c970122 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,34 @@ +# 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: 20180419010200) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "carts", force: :cascade do |t| + t.integer "user_id" + t.string "status" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "users", force: :cascade do |t| + t.string "name" + t.string "email" + t.integer "uid" + t.string "provider" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + +end From 3dbd9d86e172d1ac84edff830b8a865d46b1e34a Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Wed, 18 Apr 2018 18:16:21 -0700 Subject: [PATCH 004/320] adds migrations for products and category models and product category join table, adds relationships between the two --- app/models/category.rb | 3 ++ app/models/product.rb | 3 ++ db/migrate/20180419010108_create_products.rb | 11 +++++++ .../20180419010419_create_categories.rb | 9 ++++++ ...9011245_create_products_categories_join.rb | 6 ++++ db/schema.rb | 32 +++++++++++++++++++ test/fixtures/categories.yml | 7 ++++ test/fixtures/products.yml | 11 +++++++ test/models/category_test.rb | 9 ++++++ test/models/product_test.rb | 9 ++++++ 10 files changed, 100 insertions(+) create mode 100644 app/models/category.rb create mode 100644 app/models/product.rb create mode 100644 db/migrate/20180419010108_create_products.rb create mode 100644 db/migrate/20180419010419_create_categories.rb create mode 100644 db/migrate/20180419011245_create_products_categories_join.rb create mode 100644 db/schema.rb create mode 100644 test/fixtures/categories.yml create mode 100644 test/fixtures/products.yml create mode 100644 test/models/category_test.rb create mode 100644 test/models/product_test.rb diff --git a/app/models/category.rb b/app/models/category.rb new file mode 100644 index 0000000000..00426a6f32 --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,3 @@ +class Category < ApplicationRecord + has_many_and_belongs_to :products +end diff --git a/app/models/product.rb b/app/models/product.rb new file mode 100644 index 0000000000..ce64f64012 --- /dev/null +++ b/app/models/product.rb @@ -0,0 +1,3 @@ +class Product < ApplicationRecord + has_many_and_belongs_to :categories +end diff --git a/db/migrate/20180419010108_create_products.rb b/db/migrate/20180419010108_create_products.rb new file mode 100644 index 0000000000..ecaeb35719 --- /dev/null +++ b/db/migrate/20180419010108_create_products.rb @@ -0,0 +1,11 @@ +class CreateProducts < ActiveRecord::Migration[5.1] + def change + create_table :products do |t| + t.string :name + t.float :price + t.string :description + + t.timestamps + end + end +end diff --git a/db/migrate/20180419010419_create_categories.rb b/db/migrate/20180419010419_create_categories.rb new file mode 100644 index 0000000000..5bef4913b8 --- /dev/null +++ b/db/migrate/20180419010419_create_categories.rb @@ -0,0 +1,9 @@ +class CreateCategories < ActiveRecord::Migration[5.1] + def change + create_table :categories do |t| + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20180419011245_create_products_categories_join.rb b/db/migrate/20180419011245_create_products_categories_join.rb new file mode 100644 index 0000000000..31db10a96c --- /dev/null +++ b/db/migrate/20180419011245_create_products_categories_join.rb @@ -0,0 +1,6 @@ +class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] + def change + create_table :products_categories do |t| + end + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..942ab702d1 --- /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: 20180419010419) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "categories", force: :cascade do |t| + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "products", force: :cascade do |t| + t.string "name" + t.float "price" + t.string "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + +end diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml new file mode 100644 index 0000000000..56066c68af --- /dev/null +++ b/test/fixtures/categories.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + +two: + name: MyString diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml new file mode 100644 index 0000000000..f049a8bba9 --- /dev/null +++ b/test/fixtures/products.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + price: 1.5 + description: MyString + +two: + name: MyString + price: 1.5 + description: MyString diff --git a/test/models/category_test.rb b/test/models/category_test.rb new file mode 100644 index 0000000000..781320ad8e --- /dev/null +++ b/test/models/category_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Category do + let(:category) { Category.new } + + it "must be valid" do + value(category).must_be :valid? + end +end diff --git a/test/models/product_test.rb b/test/models/product_test.rb new file mode 100644 index 0000000000..a618b0a156 --- /dev/null +++ b/test/models/product_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Product do + let(:product) { Product.new } + + it "must be valid" do + value(product).must_be :valid? + end +end From 4a08633f57493b69b07df1c4c546b63a9d6f9f8a Mon Sep 17 00:00:00 2001 From: Phoebe Date: Wed, 18 Apr 2018 18:20:58 -0700 Subject: [PATCH 005/320] adds validations to user model --- app/models/cart.rb | 1 + app/models/user.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/models/cart.rb b/app/models/cart.rb index 95d3abe178..a2f2e36f91 100644 --- a/app/models/cart.rb +++ b/app/models/cart.rb @@ -1,4 +1,5 @@ class Cart < ApplicationRecord has_many :order_items belongs_to :user + end diff --git a/app/models/user.rb b/app/models/user.rb index dbb90c74cf..530babf1b6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,6 @@ class User < ApplicationRecord belongs_to :cart has_many :products + + validates :name, presence: true, uniquness: true end From 552034670a4172292fe0e59c535f1f8de92304ab Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 18 Apr 2018 21:43:04 -0700 Subject: [PATCH 006/320] order_item controller, model, and routes --- app/assets/javascripts/order_items.js | 2 ++ app/assets/stylesheets/order_items.scss | 3 +++ app/controllers/order_items_controller.rb | 3 +++ app/helpers/order_items_helper.rb | 2 ++ app/models/order_item.rb | 9 +++++++ config/routes.rb | 2 ++ .../20180419035721_create_order_items.rb | 11 ++++++++ db/schema.rb | 26 +++++++++++++++++++ .../order_items_controller_test.rb | 7 +++++ test/fixtures/order_items.yml | 11 ++++++++ test/models/order_item_test.rb | 9 +++++++ 11 files changed, 85 insertions(+) create mode 100644 app/assets/javascripts/order_items.js create mode 100644 app/assets/stylesheets/order_items.scss create mode 100644 app/controllers/order_items_controller.rb create mode 100644 app/helpers/order_items_helper.rb create mode 100644 app/models/order_item.rb create mode 100644 db/migrate/20180419035721_create_order_items.rb create mode 100644 db/schema.rb create mode 100644 test/controllers/order_items_controller_test.rb create mode 100644 test/fixtures/order_items.yml create mode 100644 test/models/order_item_test.rb diff --git a/app/assets/javascripts/order_items.js b/app/assets/javascripts/order_items.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/order_items.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/order_items.scss b/app/assets/stylesheets/order_items.scss new file mode 100644 index 0000000000..c02e2068ea --- /dev/null +++ b/app/assets/stylesheets/order_items.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the order_items 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/order_items_controller.rb b/app/controllers/order_items_controller.rb new file mode 100644 index 0000000000..ce0a71dd3d --- /dev/null +++ b/app/controllers/order_items_controller.rb @@ -0,0 +1,3 @@ +class OrderItemsController < ApplicationController + resources :order_item +end diff --git a/app/helpers/order_items_helper.rb b/app/helpers/order_items_helper.rb new file mode 100644 index 0000000000..e197528ae1 --- /dev/null +++ b/app/helpers/order_items_helper.rb @@ -0,0 +1,2 @@ +module OrderItemsHelper +end diff --git a/app/models/order_item.rb b/app/models/order_item.rb new file mode 100644 index 0000000000..def277c1b1 --- /dev/null +++ b/app/models/order_item.rb @@ -0,0 +1,9 @@ +class OrderItem < ApplicationRecord + belongs_to :order, :items + validates :order_id, :item_id, presence: true + + # I am not sure if this is correct + # haven't written the model tests yet + # I am h oping to to validate for unique combos of order_id and item_id to prevent repeat orders + validates_uniqueness_of :order_item, :scope => {:order_id, :item_id} +end diff --git a/config/routes.rb b/config/routes.rb index 787824f888..a5206b759b 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 :order_item end diff --git a/db/migrate/20180419035721_create_order_items.rb b/db/migrate/20180419035721_create_order_items.rb new file mode 100644 index 0000000000..1db1bd91fe --- /dev/null +++ b/db/migrate/20180419035721_create_order_items.rb @@ -0,0 +1,11 @@ +class CreateOrderItems < ActiveRecord::Migration[5.1] + def change + create_table :order_items do |t| + t.integer :order_id + t.integer :product_id + t.integer :quantity + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..0d5a9ffd42 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,26 @@ +# 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: 20180419035721) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "order_items", force: :cascade do |t| + t.integer "order_id" + t.integer "product_id" + t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + +end diff --git a/test/controllers/order_items_controller_test.rb b/test/controllers/order_items_controller_test.rb new file mode 100644 index 0000000000..96e3063c9c --- /dev/null +++ b/test/controllers/order_items_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe OrderItemsController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end diff --git a/test/fixtures/order_items.yml b/test/fixtures/order_items.yml new file mode 100644 index 0000000000..d509a9685b --- /dev/null +++ b/test/fixtures/order_items.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + order_id: 1 + product_id: 1 + quantity: 1 + +two: + order_id: 1 + product_id: 1 + quantity: 1 diff --git a/test/models/order_item_test.rb b/test/models/order_item_test.rb new file mode 100644 index 0000000000..19a9bf8f58 --- /dev/null +++ b/test/models/order_item_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe OrderItem do + let(:order_item) { OrderItem.new } + + it "must be valid" do + value(order_item).must_be :valid? + end +end From 9cccfb83a5e296bea09727f61ddba63917da0bda Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 18 Apr 2018 22:04:16 -0700 Subject: [PATCH 007/320] controller methods for new/show, fixtures created for order_item --- app/controllers/order_items_controller.rb | 28 ++++++++++++++++++++++- test/fixtures/order_items.yml | 16 ++++++------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index ce0a71dd3d..3b6b4c8142 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -1,3 +1,29 @@ class OrderItemsController < ApplicationController - resources :order_item + def index + @order_items = OrderItem.all + end + + def new + @order_item = OrderItem.new + end + + def create + end + + def edit + end + + def update + end + + def destroy + end + + def show + end + + private + + #params + end diff --git a/test/fixtures/order_items.yml b/test/fixtures/order_items.yml index d509a9685b..0c6bb7257e 100644 --- a/test/fixtures/order_items.yml +++ b/test/fixtures/order_items.yml @@ -1,11 +1,11 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - order_id: 1 - product_id: 1 - quantity: 1 +fruit_salad: + order_id: spring + product_id: fruit + quantity: 3 -two: - order_id: 1 - product_id: 1 - quantity: 1 +watermelon_salad: + order_id: summer + product_id: watermelon + quantity: 2 From 5b524e72acf2d2cc34262b6b03b5497f682471a1 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 08:54:42 -0700 Subject: [PATCH 008/320] adds controller methods for products and controllers --- app/assets/javascripts/categories.js | 2 + app/assets/javascripts/products.js | 2 + app/assets/stylesheets/categories.scss | 3 ++ app/assets/stylesheets/products.scss | 3 ++ app/controllers/categories_controller.rb | 22 ++++++++++ app/controllers/products_controller.rb | 22 ++++++++++ app/helpers/categories_helper.rb | 2 + app/helpers/products_helper.rb | 2 + app/models/product.rb | 3 ++ app/views/categories/create.html.erb | 2 + app/views/categories/destroy.html.erb | 2 + app/views/categories/edit.html.erb | 2 + app/views/categories/index.html.erb | 2 + app/views/categories/new.html.erb | 2 + app/views/categories/show.html.erb | 2 + app/views/categories/update.html.erb | 2 + app/views/products/create.html.erb | 2 + app/views/products/destroy.html.erb | 2 + app/views/products/edit.html.erb | 2 + app/views/products/index.html.erb | 2 + app/views/products/new.html.erb | 2 + app/views/products/show.html.erb | 2 + app/views/products/update.html.erb | 2 + config/routes.rb | 28 ++++++++++++ .../controllers/categories_controller_test.rb | 44 +++++++++++++++++++ test/controllers/products_controller_test.rb | 39 ++++++++++++++++ 26 files changed, 200 insertions(+) create mode 100644 app/assets/javascripts/categories.js create mode 100644 app/assets/javascripts/products.js create mode 100644 app/assets/stylesheets/categories.scss create mode 100644 app/assets/stylesheets/products.scss create mode 100644 app/controllers/categories_controller.rb create mode 100644 app/controllers/products_controller.rb create mode 100644 app/helpers/categories_helper.rb create mode 100644 app/helpers/products_helper.rb create mode 100644 app/views/categories/create.html.erb create mode 100644 app/views/categories/destroy.html.erb create mode 100644 app/views/categories/edit.html.erb create mode 100644 app/views/categories/index.html.erb create mode 100644 app/views/categories/new.html.erb create mode 100644 app/views/categories/show.html.erb create mode 100644 app/views/categories/update.html.erb create mode 100644 app/views/products/create.html.erb create mode 100644 app/views/products/destroy.html.erb create mode 100644 app/views/products/edit.html.erb create mode 100644 app/views/products/index.html.erb create mode 100644 app/views/products/new.html.erb create mode 100644 app/views/products/show.html.erb create mode 100644 app/views/products/update.html.erb create mode 100644 test/controllers/categories_controller_test.rb create mode 100644 test/controllers/products_controller_test.rb diff --git a/app/assets/javascripts/categories.js b/app/assets/javascripts/categories.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/categories.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/javascripts/products.js b/app/assets/javascripts/products.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/products.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/categories.scss b/app/assets/stylesheets/categories.scss new file mode 100644 index 0000000000..42976cbc11 --- /dev/null +++ b/app/assets/stylesheets/categories.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Categories controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss new file mode 100644 index 0000000000..bff386e55a --- /dev/null +++ b/app/assets/stylesheets/products.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Products 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/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000000..5b402f2721 --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,22 @@ +class CategoriesController < ApplicationController + def index + end + + def show + end + + def new + end + + def create + end + + def edit + end + + def update + end + + def destroy + end +end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000000..9a98430cd7 --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,22 @@ +class ProductsController < ApplicationController + def index + end + + def new + end + + def create + end + + def edit + end + + def update + end + + def show + end + + def destroy + end +end diff --git a/app/helpers/categories_helper.rb b/app/helpers/categories_helper.rb new file mode 100644 index 0000000000..e06f31554c --- /dev/null +++ b/app/helpers/categories_helper.rb @@ -0,0 +1,2 @@ +module CategoriesHelper +end diff --git a/app/helpers/products_helper.rb b/app/helpers/products_helper.rb new file mode 100644 index 0000000000..ab5c42b325 --- /dev/null +++ b/app/helpers/products_helper.rb @@ -0,0 +1,2 @@ +module ProductsHelper +end diff --git a/app/models/product.rb b/app/models/product.rb index ce64f64012..4f37ab6da7 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,3 +1,6 @@ class Product < ApplicationRecord has_many_and_belongs_to :categories + belongs_to :user + has_many :reviews + end diff --git a/app/views/categories/create.html.erb b/app/views/categories/create.html.erb new file mode 100644 index 0000000000..63069b0005 --- /dev/null +++ b/app/views/categories/create.html.erb @@ -0,0 +1,2 @@ +

Categories#create

+

Find me in app/views/categories/create.html.erb

diff --git a/app/views/categories/destroy.html.erb b/app/views/categories/destroy.html.erb new file mode 100644 index 0000000000..a6ac971f4c --- /dev/null +++ b/app/views/categories/destroy.html.erb @@ -0,0 +1,2 @@ +

Categories#destroy

+

Find me in app/views/categories/destroy.html.erb

diff --git a/app/views/categories/edit.html.erb b/app/views/categories/edit.html.erb new file mode 100644 index 0000000000..3b8dca3af4 --- /dev/null +++ b/app/views/categories/edit.html.erb @@ -0,0 +1,2 @@ +

Categories#edit

+

Find me in app/views/categories/edit.html.erb

diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000000..a5d0d54736 --- /dev/null +++ b/app/views/categories/index.html.erb @@ -0,0 +1,2 @@ +

Categories#index

+

Find me in app/views/categories/index.html.erb

diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb new file mode 100644 index 0000000000..7e5c27307e --- /dev/null +++ b/app/views/categories/new.html.erb @@ -0,0 +1,2 @@ +

Categories#new

+

Find me in app/views/categories/new.html.erb

diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb new file mode 100644 index 0000000000..60e06c3d7b --- /dev/null +++ b/app/views/categories/show.html.erb @@ -0,0 +1,2 @@ +

Categories#show

+

Find me in app/views/categories/show.html.erb

diff --git a/app/views/categories/update.html.erb b/app/views/categories/update.html.erb new file mode 100644 index 0000000000..13b85657ff --- /dev/null +++ b/app/views/categories/update.html.erb @@ -0,0 +1,2 @@ +

Categories#update

+

Find me in app/views/categories/update.html.erb

diff --git a/app/views/products/create.html.erb b/app/views/products/create.html.erb new file mode 100644 index 0000000000..d546021001 --- /dev/null +++ b/app/views/products/create.html.erb @@ -0,0 +1,2 @@ +

Products#create

+

Find me in app/views/products/create.html.erb

diff --git a/app/views/products/destroy.html.erb b/app/views/products/destroy.html.erb new file mode 100644 index 0000000000..d5c678b499 --- /dev/null +++ b/app/views/products/destroy.html.erb @@ -0,0 +1,2 @@ +

Products#destroy

+

Find me in app/views/products/destroy.html.erb

diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb new file mode 100644 index 0000000000..279b066f30 --- /dev/null +++ b/app/views/products/edit.html.erb @@ -0,0 +1,2 @@ +

Products#edit

+

Find me in app/views/products/edit.html.erb

diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb new file mode 100644 index 0000000000..f8eeb82674 --- /dev/null +++ b/app/views/products/index.html.erb @@ -0,0 +1,2 @@ +

Products#index

+

Find me in app/views/products/index.html.erb

diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb new file mode 100644 index 0000000000..a14e0d91b6 --- /dev/null +++ b/app/views/products/new.html.erb @@ -0,0 +1,2 @@ +

Products#new

+

Find me in app/views/products/new.html.erb

diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb new file mode 100644 index 0000000000..5f44ec44d2 --- /dev/null +++ b/app/views/products/show.html.erb @@ -0,0 +1,2 @@ +

Products#show

+

Find me in app/views/products/show.html.erb

diff --git a/app/views/products/update.html.erb b/app/views/products/update.html.erb new file mode 100644 index 0000000000..039889ac02 --- /dev/null +++ b/app/views/products/update.html.erb @@ -0,0 +1,2 @@ +

Products#update

+

Find me in app/views/products/update.html.erb

diff --git a/config/routes.rb b/config/routes.rb index 787824f888..f79fdf2270 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,31 @@ Rails.application.routes.draw do + get 'categories/index' + + get 'categories/new' + + get 'categories/create' + + get 'categories/edit' + + get 'categories/update' + + get 'categories/show' + + get 'categories/destroy' + + get 'products/index' + + get 'products/new' + + get 'products/create' + + get 'products/edit' + + get 'products/update' + + get 'products/show' + + get 'products/destroy' + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb new file mode 100644 index 0000000000..622fda404a --- /dev/null +++ b/test/controllers/categories_controller_test.rb @@ -0,0 +1,44 @@ +require "test_helper" + +describe CategoriesController do + it "should get index" do + get categories_index_url + value(response).must_be :success? + end + + it "should get show" do + get categories_show_url + value(response).must_be :success? + end + + it "should get new" do + get categories_new_url + value(response).must_be :success? + end + + it "should get create" do + get categories_create_url + value(response).must_be :success? + end + + it "should get edit" do + get categories_edit_url + value(response).must_be :success? + end + + it "should get update" do + get categories_update_url + value(response).must_be :success? + end + + it "should get show" do + get categories_show_url + value(response).must_be :success? + end + + it "should get destroy" do + get categories_destroy_url + value(response).must_be :success? + end + +end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb new file mode 100644 index 0000000000..513dcdf522 --- /dev/null +++ b/test/controllers/products_controller_test.rb @@ -0,0 +1,39 @@ +require "test_helper" + +describe ProductsController do + it "should get index" do + get products_index_url + value(response).must_be :success? + end + + it "should get new" do + get products_new_url + value(response).must_be :success? + end + + it "should get create" do + get products_create_url + value(response).must_be :success? + end + + it "should get edit" do + get products_edit_url + value(response).must_be :success? + end + + it "should get update" do + get products_update_url + value(response).must_be :success? + end + + it "should get show" do + get products_show_url + value(response).must_be :success? + end + + it "should get destroy" do + get products_destroy_url + value(response).must_be :success? + end + +end From d686fc67244699a63c5ef250848742be03ac69f0 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 09:14:36 -0700 Subject: [PATCH 009/320] Generates reviews model, adds reviews relationship and validations --- app/helpers/application_helper.rb | 1 + app/models/review.rb | 8 ++++++++ db/migrate/20180419155031_create_reviews.rb | 11 +++++++++++ test/fixtures/reviews.yml | 11 +++++++++++ test/models/review_test.rb | 9 +++++++++ 5 files changed, 40 insertions(+) create mode 100644 app/models/review.rb create mode 100644 db/migrate/20180419155031_create_reviews.rb create mode 100644 test/fixtures/reviews.yml create mode 100644 test/models/review_test.rb diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be7945c..a2f487023f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,3 @@ module ApplicationHelper + end diff --git a/app/models/review.rb b/app/models/review.rb new file mode 100644 index 0000000000..5690f0d921 --- /dev/null +++ b/app/models/review.rb @@ -0,0 +1,8 @@ +class Review < ApplicationRecord + + belongs_to :products + + validates :rating, pressence: true + validates :rating, numericality: { only_integer: true } + validates :rating, inclusion: { in: 1..5} +end diff --git a/db/migrate/20180419155031_create_reviews.rb b/db/migrate/20180419155031_create_reviews.rb new file mode 100644 index 0000000000..37e7773acc --- /dev/null +++ b/db/migrate/20180419155031_create_reviews.rb @@ -0,0 +1,11 @@ +class CreateReviews < ActiveRecord::Migration[5.1] + def change + create_table :reviews do |t| + t.integer :product_id + t.integer :rating + t.string :text_review + + t.timestamps + end + end +end diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml new file mode 100644 index 0000000000..0cfa53ee6f --- /dev/null +++ b/test/fixtures/reviews.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + product_id: 1 + rating: 1 + text_review: MyString + +two: + product_id: 1 + rating: 1 + text_review: MyString diff --git a/test/models/review_test.rb b/test/models/review_test.rb new file mode 100644 index 0000000000..ce8378a033 --- /dev/null +++ b/test/models/review_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe Review do + let(:review) { Review.new } + + it "must be valid" do + value(review).must_be :valid? + end +end From 22bb95e203c59a872a06cdfd0932acab4b3d9b8e Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 09:43:01 -0700 Subject: [PATCH 010/320] controller changes --- app/controllers/products_controller.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 9a98430cd7..6a1f391c5c 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -19,4 +19,10 @@ def show def destroy end + + private + + def product_params + return params.require(:product).permit(:name, :description, :price, category_ids: []) + end end From 9fca14e301a690d0f3eb1d0f83accfe2eee17c84 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 09:50:27 -0700 Subject: [PATCH 011/320] refactored validations for review --- app/models/review.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/review.rb b/app/models/review.rb index 5690f0d921..5c6bd9d97a 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -2,7 +2,9 @@ class Review < ApplicationRecord belongs_to :products - validates :rating, pressence: true - validates :rating, numericality: { only_integer: true } - validates :rating, inclusion: { in: 1..5} + validates :rating, { + pressence: true, + numericality: { only_integer: true }, + inclusion: { in: 1..5} + } end From f4f4189055ce2339a13af74728a3c92365b5f70e Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 09:55:16 -0700 Subject: [PATCH 012/320] migrated reviews model --- db/schema.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 db/schema.rb diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..c5f4b453a8 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,26 @@ +# 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: 20180419155031) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "reviews", force: :cascade do |t| + t.integer "product_id" + t.integer "rating" + t.string "text_review" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + +end From ccaf4a9b2d4588a274d5553e8e4bdffa23dd5e58 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 19 Apr 2018 09:57:28 -0700 Subject: [PATCH 013/320] attempting to merge --- db/schema.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index ca8fc4668d..6169bc0664 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -15,12 +15,6 @@ # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - create_table "order_items", force: :cascade do |t| - t.integer "order_id" - t.integer "product_id" - t.integer "quantity" - end - create_table "carts", force: :cascade do |t| t.integer "user_id" t.string "status" @@ -28,6 +22,12 @@ t.datetime "updated_at", null: false end + create_table "order_items", force: :cascade do |t| + t.integer "order_id" + t.integer "product_id" + t.integer "quantity" + end + create_table "users", force: :cascade do |t| t.string "name" t.string "email" From f6acb2b967aa1cb54faa0502b8924353039492a2 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 10:00:13 -0700 Subject: [PATCH 014/320] schema conflicts --- db/schema.rb | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 095b1e49ff..03c9459a41 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,52 +10,47 @@ # # It's strongly recommended that you check this file into your version control system. -<<<<<<< HEAD -<<<<<<< HEAD -ActiveRecord::Schema.define(version: 20180419010419) do -======= -ActiveRecord::Schema.define(version: 20180419010200) do ->>>>>>> 4a08633f57493b69b07df1c4c546b63a9d6f9f8a -======= + ActiveRecord::Schema.define(version: 20180419035721) do ->>>>>>> f2036e4c7a0235667f1ca1b94cb4964e3c388de4 # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" -<<<<<<< HEAD -<<<<<<< HEAD create_table "categories", force: :cascade do |t| t.string "name" -======= -======= + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "order_items", force: :cascade do |t| t.integer "order_id" t.integer "product_id" t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end ->>>>>>> f2036e4c7a0235667f1ca1b94cb4964e3c388de4 + create_table "carts", force: :cascade do |t| t.integer "user_id" t.string "status" ->>>>>>> 4a08633f57493b69b07df1c4c546b63a9d6f9f8a t.datetime "created_at", null: false t.datetime "updated_at", null: false end -<<<<<<< HEAD create_table "products", force: :cascade do |t| t.string "name" t.float "price" t.string "description" -======= + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "users", force: :cascade do |t| t.string "name" t.string "email" t.integer "uid" t.string "provider" ->>>>>>> 4a08633f57493b69b07df1c4c546b63a9d6f9f8a t.datetime "created_at", null: false t.datetime "updated_at", null: false end From 7df9c3cc18d8ad4da45aecd10b02c6497b823982 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 10:06:12 -0700 Subject: [PATCH 015/320] schema change --- db/schema.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index 03c9459a41..0407c8a300 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -30,7 +30,6 @@ t.datetime "updated_at", null: false end - create_table "carts", force: :cascade do |t| t.integer "user_id" t.string "status" From 4bf146231c28d98be4243c3e170ffa434f683db8 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 10:07:00 -0700 Subject: [PATCH 016/320] another schema change --- db/schema.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 48d872fae0..ded1cd98fe 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,11 +9,7 @@ # 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. -<<<<<<< HEAD -======= - ->>>>>>> f6acb2b967aa1cb54faa0502b8924353039492a2 ActiveRecord::Schema.define(version: 20180419035721) do From 644de5f5c27e612a39bb668b9b4632f7b654b125 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 10:08:25 -0700 Subject: [PATCH 017/320] adds join table info --- ...9011245_create_products_categories_join.rb | 2 + db/schema.rb | 50 ++++++++++--------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/db/migrate/20180419011245_create_products_categories_join.rb b/db/migrate/20180419011245_create_products_categories_join.rb index 31db10a96c..3af322f986 100644 --- a/db/migrate/20180419011245_create_products_categories_join.rb +++ b/db/migrate/20180419011245_create_products_categories_join.rb @@ -1,6 +1,8 @@ class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] def change create_table :products_categories do |t| + t.belongs_to :product, index: true + t.belongs_to :category, index: true end end end diff --git a/db/schema.rb b/db/schema.rb index 095b1e49ff..06430a691b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,52 +10,56 @@ # # It's strongly recommended that you check this file into your version control system. -<<<<<<< HEAD -<<<<<<< HEAD -ActiveRecord::Schema.define(version: 20180419010419) do -======= -ActiveRecord::Schema.define(version: 20180419010200) do ->>>>>>> 4a08633f57493b69b07df1c4c546b63a9d6f9f8a -======= -ActiveRecord::Schema.define(version: 20180419035721) do ->>>>>>> f2036e4c7a0235667f1ca1b94cb4964e3c388de4 +ActiveRecord::Schema.define(version: 20180419155031) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" -<<<<<<< HEAD -<<<<<<< HEAD + create_table "carts", force: :cascade do |t| + t.integer "user_id" + t.string "status" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "categories", force: :cascade do |t| t.string "name" -======= -======= + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "order_items", force: :cascade do |t| t.integer "order_id" t.integer "product_id" t.integer "quantity" - end - ->>>>>>> f2036e4c7a0235667f1ca1b94cb4964e3c388de4 - create_table "carts", force: :cascade do |t| - t.integer "user_id" - t.string "status" ->>>>>>> 4a08633f57493b69b07df1c4c546b63a9d6f9f8a t.datetime "created_at", null: false t.datetime "updated_at", null: false end -<<<<<<< HEAD create_table "products", force: :cascade do |t| t.string "name" t.float "price" t.string "description" -======= + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "products_categories", force: :cascade do |t| + end + + create_table "reviews", force: :cascade do |t| + t.integer "product_id" + t.integer "rating" + t.string "text_review" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "users", force: :cascade do |t| t.string "name" t.string "email" t.integer "uid" t.string "provider" ->>>>>>> 4a08633f57493b69b07df1c4c546b63a9d6f9f8a t.datetime "created_at", null: false t.datetime "updated_at", null: false end From 7f7bffea4720bd5dca1dacd286443cda47004b99 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 13:41:06 -0700 Subject: [PATCH 018/320] attempting to commit Changes --- db/schema.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index ce97833fc7..c4fa8c4cad 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,14 +9,9 @@ # 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. -<<<<<<< HEAD -======= - ->>>>>>> f6acb2b967aa1cb54faa0502b8924353039492a2 ActiveRecord::Schema.define(version: 20180419035721) do - # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" From 30b9dd2988c28310f19f2b547f547aa9222048e5 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 14:00:45 -0700 Subject: [PATCH 019/320] Adds reviews controller and controller actions --- app/assets/javascripts/review.js | 2 ++ app/assets/stylesheets/review.scss | 3 +++ app/controllers/review_controller.rb | 9 +++++++++ app/helpers/review_helper.rb | 2 ++ test/controllers/review_controller_test.rb | 7 +++++++ 5 files changed, 23 insertions(+) create mode 100644 app/assets/javascripts/review.js create mode 100644 app/assets/stylesheets/review.scss create mode 100644 app/controllers/review_controller.rb create mode 100644 app/helpers/review_helper.rb create mode 100644 test/controllers/review_controller_test.rb diff --git a/app/assets/javascripts/review.js b/app/assets/javascripts/review.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/review.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/review.scss b/app/assets/stylesheets/review.scss new file mode 100644 index 0000000000..f2ecbaa286 --- /dev/null +++ b/app/assets/stylesheets/review.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Review 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/review_controller.rb b/app/controllers/review_controller.rb new file mode 100644 index 0000000000..32142ff452 --- /dev/null +++ b/app/controllers/review_controller.rb @@ -0,0 +1,9 @@ +class ReviewController < ApplicationController + + def new + end + + def create + end + +end diff --git a/app/helpers/review_helper.rb b/app/helpers/review_helper.rb new file mode 100644 index 0000000000..30a319261d --- /dev/null +++ b/app/helpers/review_helper.rb @@ -0,0 +1,2 @@ +module ReviewHelper +end diff --git a/test/controllers/review_controller_test.rb b/test/controllers/review_controller_test.rb new file mode 100644 index 0000000000..02dca22c8e --- /dev/null +++ b/test/controllers/review_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe ReviewController do + # it "must be a real test" do + # flunk "Need real tests" + # end +end From 31c95037943335559d95a98f79106fb16bd6c45b Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 14:08:06 -0700 Subject: [PATCH 020/320] Refactors review controlle to plural --- app/assets/javascripts/{review.js => reviews.js} | 0 .../stylesheets/{review.scss => reviews.scss} | 2 +- app/controllers/review_controller.rb | 9 --------- app/controllers/reviews_controller.rb | 7 +++++++ app/helpers/review_helper.rb | 2 -- app/helpers/reviews_helper.rb | 2 ++ app/views/reviews/create.html.erb | 2 ++ app/views/reviews/new.html.erb | 2 ++ config/routes.rb | 4 ++++ test/controllers/review_controller_test.rb | 7 ------- test/controllers/reviews_controller_test.rb | 14 ++++++++++++++ 11 files changed, 32 insertions(+), 19 deletions(-) rename app/assets/javascripts/{review.js => reviews.js} (100%) rename app/assets/stylesheets/{review.scss => reviews.scss} (64%) delete mode 100644 app/controllers/review_controller.rb create mode 100644 app/controllers/reviews_controller.rb delete mode 100644 app/helpers/review_helper.rb create mode 100644 app/helpers/reviews_helper.rb create mode 100644 app/views/reviews/create.html.erb create mode 100644 app/views/reviews/new.html.erb delete mode 100644 test/controllers/review_controller_test.rb create mode 100644 test/controllers/reviews_controller_test.rb diff --git a/app/assets/javascripts/review.js b/app/assets/javascripts/reviews.js similarity index 100% rename from app/assets/javascripts/review.js rename to app/assets/javascripts/reviews.js diff --git a/app/assets/stylesheets/review.scss b/app/assets/stylesheets/reviews.scss similarity index 64% rename from app/assets/stylesheets/review.scss rename to app/assets/stylesheets/reviews.scss index f2ecbaa286..11bbb12cd5 100644 --- a/app/assets/stylesheets/review.scss +++ b/app/assets/stylesheets/reviews.scss @@ -1,3 +1,3 @@ -// Place all the styles related to the Review controller here. +// Place all the styles related to the Reviews 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/review_controller.rb b/app/controllers/review_controller.rb deleted file mode 100644 index 32142ff452..0000000000 --- a/app/controllers/review_controller.rb +++ /dev/null @@ -1,9 +0,0 @@ -class ReviewController < ApplicationController - - def new - end - - def create - end - -end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..102b3bb888 --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,7 @@ +class ReviewsController < ApplicationController + def new + end + + def create + end +end diff --git a/app/helpers/review_helper.rb b/app/helpers/review_helper.rb deleted file mode 100644 index 30a319261d..0000000000 --- a/app/helpers/review_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module ReviewHelper -end diff --git a/app/helpers/reviews_helper.rb b/app/helpers/reviews_helper.rb new file mode 100644 index 0000000000..682b7b1abc --- /dev/null +++ b/app/helpers/reviews_helper.rb @@ -0,0 +1,2 @@ +module ReviewsHelper +end diff --git a/app/views/reviews/create.html.erb b/app/views/reviews/create.html.erb new file mode 100644 index 0000000000..44bf11c2ed --- /dev/null +++ b/app/views/reviews/create.html.erb @@ -0,0 +1,2 @@ +

Reviews#create

+

Find me in app/views/reviews/create.html.erb

diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb new file mode 100644 index 0000000000..9cc9d7f56b --- /dev/null +++ b/app/views/reviews/new.html.erb @@ -0,0 +1,2 @@ +

Reviews#new

+

Find me in app/views/reviews/new.html.erb

diff --git a/config/routes.rb b/config/routes.rb index 15af09e2b4..bae68b9933 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,9 @@ Rails.application.routes.draw do + get 'reviews/new' + + get 'reviews/create' + resources :product resources :category diff --git a/test/controllers/review_controller_test.rb b/test/controllers/review_controller_test.rb deleted file mode 100644 index 02dca22c8e..0000000000 --- a/test/controllers/review_controller_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "test_helper" - -describe ReviewController do - # it "must be a real test" do - # flunk "Need real tests" - # end -end diff --git a/test/controllers/reviews_controller_test.rb b/test/controllers/reviews_controller_test.rb new file mode 100644 index 0000000000..a0a226d82d --- /dev/null +++ b/test/controllers/reviews_controller_test.rb @@ -0,0 +1,14 @@ +require "test_helper" + +describe ReviewsController do + it "should get new" do + get reviews_new_url + value(response).must_be :success? + end + + it "should get create" do + get reviews_create_url + value(response).must_be :success? + end + +end From d7c6bb1cd9e67e6ee2818c27b307bf9ae09a233a Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 14:12:48 -0700 Subject: [PATCH 021/320] changes cart to order for model name --- app/models/user.rb | 2 +- .../20180419210802_change_carts_to_orders.rb | 5 +++++ db/schema.rb | 17 +++++++---------- 3 files changed, 13 insertions(+), 11 deletions(-) create mode 100644 db/migrate/20180419210802_change_carts_to_orders.rb diff --git a/app/models/user.rb b/app/models/user.rb index 530babf1b6..d64b70d9f8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,5 @@ class User < ApplicationRecord - belongs_to :cart + belongs_to :order has_many :products validates :name, presence: true, uniquness: true diff --git a/db/migrate/20180419210802_change_carts_to_orders.rb b/db/migrate/20180419210802_change_carts_to_orders.rb new file mode 100644 index 0000000000..2dd331e6b7 --- /dev/null +++ b/db/migrate/20180419210802_change_carts_to_orders.rb @@ -0,0 +1,5 @@ +class ChangeCartsToOrders < ActiveRecord::Migration[5.1] + def change + rename_table :carts, :orders + end +end diff --git a/db/schema.rb b/db/schema.rb index f97ca15d58..884e52aab0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,19 +10,11 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180419035721) do +ActiveRecord::Schema.define(version: 20180419210802) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - create_table "carts", force: :cascade do |t| - t.integer "user_id" - t.string "status" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - create_table "categories", force: :cascade do |t| t.string "name" t.datetime "created_at", null: false @@ -37,6 +29,12 @@ t.datetime "updated_at", null: false end + create_table "orders", force: :cascade do |t| + t.integer "user_id" + t.string "status" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end create_table "products", force: :cascade do |t| t.string "name" @@ -47,7 +45,6 @@ end create_table "products_categories", force: :cascade do |t| - end create_table "reviews", force: :cascade do |t| From 77a746e90f812f0e58f1a7418c74bf31e1128ad0 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 19 Apr 2018 14:23:16 -0700 Subject: [PATCH 022/320] created fixtures that all relate to each other, follow fruit theme. missing product categories --- test/fixtures/carts.yml | 12 ++++++------ test/fixtures/categories.yml | 8 ++++---- test/fixtures/order_items.yml | 11 ++++++++--- test/fixtures/products.yml | 23 +++++++++++++++-------- test/fixtures/reviews.yml | 14 +++++++------- test/fixtures/users.yml | 20 ++++++++++---------- test/models/order_item_test.rb | 4 ++++ 7 files changed, 54 insertions(+), 38 deletions(-) diff --git a/test/fixtures/carts.yml b/test/fixtures/carts.yml index a0701a550c..e95b7cbeff 100644 --- a/test/fixtures/carts.yml +++ b/test/fixtures/carts.yml @@ -1,9 +1,9 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - user_id: 1 - status: MyString +cart1: + user_id: beyonce + status: shipped -two: - user_id: 1 - status: MyString +cart2: + user_id: hermonie + status: paid diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml index 56066c68af..0ec843cca5 100644 --- a/test/fixtures/categories.yml +++ b/test/fixtures/categories.yml @@ -1,7 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - name: MyString +category1: + name: summer fruit -two: - name: MyString +category2: + name: fruit salad diff --git a/test/fixtures/order_items.yml b/test/fixtures/order_items.yml index 0c6bb7257e..b1d2264a64 100644 --- a/test/fixtures/order_items.yml +++ b/test/fixtures/order_items.yml @@ -1,11 +1,16 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html fruit_salad: - order_id: spring - product_id: fruit + order_id: cart1 + product_id: cherry quantity: 3 watermelon_salad: - order_id: summer + order_id: cart2 product_id: watermelon quantity: 2 + +citris_salad: + order_id: cart2 + product_id: orange + quantity: 2 diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index f049a8bba9..ce83af5c88 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -1,11 +1,18 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html +# summer +cherries: + name: cherries + price: 3.0 + description: 1kg ranier cherries -one: - name: MyString - price: 1.5 - description: MyString +#summer +watermelon: + name: watermelon + price: 4.0 + description: seedless -two: - name: MyString - price: 1.5 - description: MyString +#fruit salad +orange: + name: orange + price: 1.0 + description: single orange diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml index 0cfa53ee6f..91bbd13a5d 100644 --- a/test/fixtures/reviews.yml +++ b/test/fixtures/reviews.yml @@ -1,11 +1,11 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - product_id: 1 +rating1: + product_id: cherries rating: 1 - text_review: MyString + text_review: too sour -two: - product_id: 1 - rating: 1 - text_review: MyString +rating2: + product_id: watermelon + rating: 5 + text_review: perfect diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 168a2e2888..fe1fd218b3 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -1,13 +1,13 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -one: - name: MyString - email: MyString - uid: 1 - provider: MyString +beyonce: + name: beyonce + email: beyonce@github.com + uid: 101 + provider: github -two: - name: MyString - email: MyString - uid: 1 - provider: MyString +hermonie: + name: hermonie + email: hermonie@github.com + uid: 100 + provider: github diff --git a/test/models/order_item_test.rb b/test/models/order_item_test.rb index 19a9bf8f58..3c7a08b4b2 100644 --- a/test/models/order_item_test.rb +++ b/test/models/order_item_test.rb @@ -4,6 +4,10 @@ let(:order_item) { OrderItem.new } it "must be valid" do + @test = order_item + @test.product = + @test.order = + @test.save value(order_item).must_be :valid? end end From 55291edc4cd1c81e69d0f6b083164e23b15c99ce Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 14:25:11 -0700 Subject: [PATCH 023/320] added root path --- app/controllers/reviews_controller.rb | 1 + config/routes.rb | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 102b3bb888..ada1bfa0d5 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,5 +1,6 @@ class ReviewsController < ApplicationController def new + end def create diff --git a/config/routes.rb b/config/routes.rb index bae68b9933..0cc3f5e194 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,6 @@ Rails.application.routes.draw do - get 'reviews/new' - - get 'reviews/create' + root 'products#index' resources :product @@ -12,7 +10,7 @@ resources :review - resources :user + resources :user resources :order_item end From a10125630919eae7eed616f477e02dd4972124c7 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 19 Apr 2018 14:29:06 -0700 Subject: [PATCH 024/320] created migration to add category id to column to product model --- db/migrate/20180419212546_add_category_id_to_products.rb | 5 +++++ db/schema.rb | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20180419212546_add_category_id_to_products.rb diff --git a/db/migrate/20180419212546_add_category_id_to_products.rb b/db/migrate/20180419212546_add_category_id_to_products.rb new file mode 100644 index 0000000000..a0346911fe --- /dev/null +++ b/db/migrate/20180419212546_add_category_id_to_products.rb @@ -0,0 +1,5 @@ +class AddCategoryIdToProducts < ActiveRecord::Migration[5.1] + def change + add_column :products, :category_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 884e52aab0..7dd09ed626 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: 20180419210802) do +ActiveRecord::Schema.define(version: 20180419212546) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -25,8 +25,6 @@ t.integer "order_id" t.integer "product_id" t.integer "quantity" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false end create_table "orders", force: :cascade do |t| @@ -42,9 +40,14 @@ t.string "description" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "category_id" end create_table "products_categories", force: :cascade do |t| + t.bigint "product_id" + t.bigint "category_id" + t.index ["category_id"], name: "index_products_categories_on_category_id" + t.index ["product_id"], name: "index_products_categories_on_product_id" end create_table "reviews", force: :cascade do |t| From 50044fac470ef8342aae26f08db97e4a205b2401 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 19 Apr 2018 14:35:09 -0700 Subject: [PATCH 025/320] added category_id to products fixtures --- test/fixtures/products.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index ce83af5c88..e3d9ef0021 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -1,18 +1,18 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -# summer cherries: name: cherries price: 3.0 description: 1kg ranier cherries + category: summer -#summer watermelon: name: watermelon price: 4.0 description: seedless + category: summer -#fruit salad orange: name: orange price: 1.0 description: single orange + category: fruit From ec9cfc58cc51b1ef9f6a87a945ffb9571bb5febe Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 14:57:19 -0700 Subject: [PATCH 026/320] adds OAuth gems, files, etc --- .gitignore | 1 + Gemfile | 4 ++ Gemfile.lock | 28 +++++++++++++ app/assets/javascripts/sessions.js | 2 + app/assets/stylesheets/sessions.scss | 3 ++ app/controllers/products_controller.rb | 2 + app/controllers/sessions_controller.rb | 23 ++++++++++ app/helpers/sessions_helper.rb | 2 + app/views/sessions/create.html.erb | 2 + app/views/sessions/destroy.html.erb | 2 + app/views/sessions/edit.html.erb | 2 + app/views/sessions/index.html.erb | 2 + app/views/sessions/new.html.erb | 2 + app/views/sessions/show.html.erb | 2 + app/views/sessions/update.html.erb | 2 + config/initializers/omniauth.rb | 3 ++ config/routes.rb | 17 ++++---- test/controllers/sessions_controller_test.rb | 44 ++++++++++++++++++++ 18 files changed, 136 insertions(+), 7 deletions(-) create mode 100644 app/assets/javascripts/sessions.js create mode 100644 app/assets/stylesheets/sessions.scss create mode 100644 app/controllers/sessions_controller.rb create mode 100644 app/helpers/sessions_helper.rb create mode 100644 app/views/sessions/create.html.erb create mode 100644 app/views/sessions/destroy.html.erb create mode 100644 app/views/sessions/edit.html.erb create mode 100644 app/views/sessions/index.html.erb create mode 100644 app/views/sessions/new.html.erb create mode 100644 app/views/sessions/show.html.erb create mode 100644 app/views/sessions/update.html.erb create mode 100644 config/initializers/omniauth.rb create mode 100644 test/controllers/sessions_controller_test.rb diff --git a/.gitignore b/.gitignore index 82701fedc8..fd7861badf 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ /yarn-error.log .byebug_history +.env diff --git a/Gemfile b/Gemfile index 8490d0efb5..6d82ec12e2 100644 --- a/Gemfile +++ b/Gemfile @@ -64,9 +64,13 @@ end group :development do gem 'better_errors' gem 'binding_of_caller' + gem 'dotenv-rails' end group :test do gem 'minitest-rails' gem 'minitest-reporters' end + +gem "omniauth" +gem "omniauth-github" diff --git a/Gemfile.lock b/Gemfile.lock index d528acb17a..436e28411f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,8 +68,14 @@ GEM concurrent-ruby (1.0.5) crass (1.0.4) debug_inspector (0.0.3) + dotenv (2.2.2) + dotenv-rails (2.2.2) + dotenv (= 2.2.2) + railties (>= 3.2, < 6.0) erubi (1.7.1) execjs (2.7.0) + faraday (0.12.2) + multipart-post (>= 1.2, < 3) ffi (1.9.23) foundation-rails (6.4.3.0) railties (>= 3.1.0) @@ -77,6 +83,7 @@ GEM sprockets-es6 (>= 0.9.0) globalid (0.4.1) activesupport (>= 4.2.0) + hashie (3.5.7) i18n (1.0.1) concurrent-ruby (~> 1.0) jbuilder (2.7.0) @@ -89,6 +96,7 @@ GEM jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks + jwt (1.5.6) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -111,10 +119,27 @@ GEM minitest (>= 5.0) ruby-progressbar multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) nio4r (2.3.0) nokogiri (1.8.2) mini_portile2 (~> 2.3.0) normalize-rails (4.1.1) + oauth2 (1.4.0) + faraday (>= 0.8, < 0.13) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.8.1) + hashie (>= 3.4.6, < 3.6.0) + rack (>= 1.6.2, < 3) + omniauth-github (1.3.0) + omniauth (~> 1.5) + omniauth-oauth2 (>= 1.4.0, < 2.0) + omniauth-oauth2 (1.5.0) + oauth2 (~> 1.1) + omniauth (~> 1.2) pg (1.0.0) pry (0.11.3) coderay (~> 1.1.0) @@ -211,6 +236,7 @@ DEPENDENCIES binding_of_caller byebug capybara (~> 2.13) + dotenv-rails foundation-rails jbuilder (~> 2.5) jquery-rails @@ -219,6 +245,8 @@ DEPENDENCIES minitest-rails minitest-reporters normalize-rails + omniauth + omniauth-github pg (>= 0.18, < 2.0) pry-rails puma (~> 3.7) diff --git a/app/assets/javascripts/sessions.js b/app/assets/javascripts/sessions.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/sessions.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/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000000..ccb1ed25b2 --- /dev/null +++ b/app/assets/stylesheets/sessions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Sessions 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/products_controller.rb b/app/controllers/products_controller.rb index 6a1f391c5c..a1253df7e6 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,8 +1,10 @@ class ProductsController < ApplicationController def index + end def new + end def create diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000000..c38d619434 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,23 @@ +class SessionsController < ApplicationController + def index + end + + def show + end + + def new + @user = User.new + end + + def create + end + + def edit + end + + def update + end + + def destroy + end +end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb new file mode 100644 index 0000000000..309f8b2eb3 --- /dev/null +++ b/app/helpers/sessions_helper.rb @@ -0,0 +1,2 @@ +module SessionsHelper +end diff --git a/app/views/sessions/create.html.erb b/app/views/sessions/create.html.erb new file mode 100644 index 0000000000..c251174fea --- /dev/null +++ b/app/views/sessions/create.html.erb @@ -0,0 +1,2 @@ +

Sessions#create

+

Find me in app/views/sessions/create.html.erb

diff --git a/app/views/sessions/destroy.html.erb b/app/views/sessions/destroy.html.erb new file mode 100644 index 0000000000..d75237d982 --- /dev/null +++ b/app/views/sessions/destroy.html.erb @@ -0,0 +1,2 @@ +

Sessions#destroy

+

Find me in app/views/sessions/destroy.html.erb

diff --git a/app/views/sessions/edit.html.erb b/app/views/sessions/edit.html.erb new file mode 100644 index 0000000000..071265e062 --- /dev/null +++ b/app/views/sessions/edit.html.erb @@ -0,0 +1,2 @@ +

Sessions#edit

+

Find me in app/views/sessions/edit.html.erb

diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb new file mode 100644 index 0000000000..62cbf379e3 --- /dev/null +++ b/app/views/sessions/index.html.erb @@ -0,0 +1,2 @@ +

Sessions#index

+

Find me in app/views/sessions/index.html.erb

diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb new file mode 100644 index 0000000000..b39a3bc951 --- /dev/null +++ b/app/views/sessions/new.html.erb @@ -0,0 +1,2 @@ +

Sessions#new

+

Find me in app/views/sessions/new.html.erb

diff --git a/app/views/sessions/show.html.erb b/app/views/sessions/show.html.erb new file mode 100644 index 0000000000..1225c86bfd --- /dev/null +++ b/app/views/sessions/show.html.erb @@ -0,0 +1,2 @@ +

Sessions#show

+

Find me in app/views/sessions/show.html.erb

diff --git a/app/views/sessions/update.html.erb b/app/views/sessions/update.html.erb new file mode 100644 index 0000000000..057db622ad --- /dev/null +++ b/app/views/sessions/update.html.erb @@ -0,0 +1,2 @@ +

Sessions#update

+

Find me in app/views/sessions/update.html.erb

diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 0000000000..fd4416122a --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,3 @@ +Rails.application.config.middleware.use OmniAuth::Builder do + provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user:email" +end diff --git a/config/routes.rb b/config/routes.rb index 0cc3f5e194..d88b8d5f6c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,16 +1,19 @@ Rails.application.routes.draw do - root 'products#index' + get "/auth/:provider/callback", to: "sessions#create", as: "auth_callback" + get '/auth/github', as: 'github_login' - resources :product + resources :sessions - resources :category + resources :products - resources :cart + resources :categories - resources :review + resources :carts - resources :user + resources :reviews - resources :order_item + resources :users + + resources :order_items end diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb new file mode 100644 index 0000000000..ca71d28cf7 --- /dev/null +++ b/test/controllers/sessions_controller_test.rb @@ -0,0 +1,44 @@ +require "test_helper" + +describe SessionsController do + it "should get index" do + get sessions_index_url + value(response).must_be :success? + end + + it "should get show" do + get sessions_show_url + value(response).must_be :success? + end + + it "should get new" do + get sessions_new_url + value(response).must_be :success? + end + + it "should get create" do + get sessions_create_url + value(response).must_be :success? + end + + it "should get edit" do + get sessions_edit_url + value(response).must_be :success? + end + + it "should get update" do + get sessions_update_url + value(response).must_be :success? + end + + it "should get show" do + get sessions_show_url + value(response).must_be :success? + end + + it "should get destroy" do + get sessions_destroy_url + value(response).must_be :success? + end + +end From 5b3d12b1b9c2fa9939cf13fee25ff90eda5b6dfd Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 15:09:41 -0700 Subject: [PATCH 027/320] adds reivew form as partial --- app/views/products/show.html.erb | 2 ++ app/views/reviews/_form.html.erb | 8 ++++++++ app/views/reviews/new.html.erb | 2 -- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 app/views/reviews/_form.html.erb diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 5f44ec44d2..79df266c7f 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,2 +1,4 @@

Products#show

Find me in app/views/products/show.html.erb

+ +<%= render partial: "form" %> diff --git a/app/views/reviews/_form.html.erb b/app/views/reviews/_form.html.erb new file mode 100644 index 0000000000..16cdbcee67 --- /dev/null +++ b/app/views/reviews/_form.html.erb @@ -0,0 +1,8 @@ +<%= form review do |f| %> + <%= f.label :rating %> + <%= f.select :rating, 1..5, :prompt => "Select One" %> + + <%= f.label :text_review %> + <%= f.text_field :text_review %> + <%= f.submit %> +<% end %> diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb index 9cc9d7f56b..e69de29bb2 100644 --- a/app/views/reviews/new.html.erb +++ b/app/views/reviews/new.html.erb @@ -1,2 +0,0 @@ -

Reviews#new

-

Find me in app/views/reviews/new.html.erb

From 0cc12cd7f62f704f8aa90ab5920454c266d424f3 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 19 Apr 2018 15:10:52 -0700 Subject: [PATCH 028/320] added migration order_item status --- app/models/category.rb | 2 +- app/models/order_item.rb | 2 +- db/migrate/20180419220917_add_order_status_to_order_item.rb | 5 +++++ db/schema.rb | 3 ++- test/models/cart_test.rb | 4 ++-- 5 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20180419220917_add_order_status_to_order_item.rb diff --git a/app/models/category.rb b/app/models/category.rb index 00426a6f32..f3218758f1 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,3 +1,3 @@ class Category < ApplicationRecord - has_many_and_belongs_to :products + has_and_belongs_to_many :products end diff --git a/app/models/order_item.rb b/app/models/order_item.rb index def277c1b1..e58b1223eb 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -5,5 +5,5 @@ class OrderItem < ApplicationRecord # I am not sure if this is correct # haven't written the model tests yet # I am h oping to to validate for unique combos of order_id and item_id to prevent repeat orders - validates_uniqueness_of :order_item, :scope => {:order_id, :item_id} + validates :order_item, uniqueness: { :scope [:order_id, :item_id] } end diff --git a/db/migrate/20180419220917_add_order_status_to_order_item.rb b/db/migrate/20180419220917_add_order_status_to_order_item.rb new file mode 100644 index 0000000000..6f00645d35 --- /dev/null +++ b/db/migrate/20180419220917_add_order_status_to_order_item.rb @@ -0,0 +1,5 @@ +class AddOrderStatusToOrderItem < ActiveRecord::Migration[5.1] + def change + add_column :order_items, :status, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 7dd09ed626..e96398d7cb 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: 20180419212546) do +ActiveRecord::Schema.define(version: 20180419220917) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -25,6 +25,7 @@ t.integer "order_id" t.integer "product_id" t.integer "quantity" + t.string "status" end create_table "orders", force: :cascade do |t| diff --git a/test/models/cart_test.rb b/test/models/cart_test.rb index f2c5bd6f62..48dae906b2 100644 --- a/test/models/cart_test.rb +++ b/test/models/cart_test.rb @@ -1,9 +1,9 @@ require "test_helper" describe Cart do - let(:cart) { Cart.new } + let(:cart) { carts(:cart1)} it "must be valid" do - value(cart).must_be :valid? + cart.valid?.must_equal true end end From 7a9cbaf5d8296bb8760a18ad84c6ea2be3c8c1ac Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 19 Apr 2018 15:12:19 -0700 Subject: [PATCH 029/320] added status to order_item yml --- test/fixtures/order_items.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/fixtures/order_items.yml b/test/fixtures/order_items.yml index b1d2264a64..4ebc678ba0 100644 --- a/test/fixtures/order_items.yml +++ b/test/fixtures/order_items.yml @@ -1,16 +1,20 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html +# I am unsure of what to call the status fruit_salad: order_id: cart1 product_id: cherry quantity: 3 + status: paid watermelon_salad: order_id: cart2 product_id: watermelon quantity: 2 + status: paid citris_salad: order_id: cart2 product_id: orange quantity: 2 + status: paid From 3a758d0cf0cc13d8d8293d80e314ea9853cd0c92 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 15:30:43 -0700 Subject: [PATCH 030/320] product validations --- app/models/category.rb | 2 ++ app/models/product.rb | 4 ++++ db/migrate/20180419221855_add_imageto_products.rb | 5 +++++ db/schema.rb | 9 ++++----- 4 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20180419221855_add_imageto_products.rb diff --git a/app/models/category.rb b/app/models/category.rb index f3218758f1..ba7c56788e 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,3 +1,5 @@ class Category < ApplicationRecord has_and_belongs_to_many :products + + end diff --git a/app/models/product.rb b/app/models/product.rb index 4f37ab6da7..e48b82bb31 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -3,4 +3,8 @@ class Product < ApplicationRecord belongs_to :user has_many :reviews + validates :name, presence: true + validates :name, length:{ minimum: 1 } + validates :price, presence: true + end diff --git a/db/migrate/20180419221855_add_imageto_products.rb b/db/migrate/20180419221855_add_imageto_products.rb new file mode 100644 index 0000000000..3a33167f4d --- /dev/null +++ b/db/migrate/20180419221855_add_imageto_products.rb @@ -0,0 +1,5 @@ +class AddImagetoProducts < ActiveRecord::Migration[5.1] + def change + add_column :products, :image, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index e96398d7cb..5595995694 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: 20180419220917) do +ActiveRecord::Schema.define(version: 20180419221855) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -25,6 +25,8 @@ t.integer "order_id" t.integer "product_id" t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "status" end @@ -42,13 +44,10 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "category_id" + t.string "image" end create_table "products_categories", force: :cascade do |t| - t.bigint "product_id" - t.bigint "category_id" - t.index ["category_id"], name: "index_products_categories_on_category_id" - t.index ["product_id"], name: "index_products_categories_on_product_id" end create_table "reviews", force: :cascade do |t| From 18a6b6600f89a4cdde4692a769ed7b761820d0ce Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 15:36:21 -0700 Subject: [PATCH 031/320] adds nav bar --- app/views/layouts/application.html.erb | 11 ++++++++++- config/routes.rb | 2 ++ db/schema.rb | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index cd60004891..32e9813880 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -4,7 +4,7 @@ - <%= content_for?(:title) ? yield(:title) : "Untitled" %> + <%= content_for?(:title) ? yield(:title) : "FruEtsy" %> <%= stylesheet_link_tag "application" %> <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> @@ -13,6 +13,15 @@ +
+ +
+ <%= yield %> diff --git a/config/routes.rb b/config/routes.rb index d88b8d5f6c..9d1446cb67 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,8 @@ get "/auth/:provider/callback", to: "sessions#create", as: "auth_callback" get '/auth/github', as: 'github_login' + root 'products#index' + resources :sessions resources :products diff --git a/db/schema.rb b/db/schema.rb index e96398d7cb..fe70d4a142 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -25,6 +25,8 @@ t.integer "order_id" t.integer "product_id" t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "status" end From f6366f124465bead8f9c49b9ce807e8f5b90822e Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 15:39:44 -0700 Subject: [PATCH 032/320] up to date schema --- config/routes.rb | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index d88b8d5f6c..ebc84810bd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,17 +3,20 @@ get "/auth/:provider/callback", to: "sessions#create", as: "auth_callback" get '/auth/github', as: 'github_login' - resources :sessions - - resources :products - - resources :categories - - resources :carts - - resources :reviews - - resources :users - - resources :order_items + # resources :sessions + # + # resources :products + # + # resources :categories + # + # resources :carts + # + # resources :reviews + + resources :users do + resources :orders + resources :products + end + + # resources :order_items end From ddc13c6eabd22aa06e326e5e53b9392ac784bc3d Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 15:47:06 -0700 Subject: [PATCH 033/320] products categories looks right --- db/migrate/20180419223203_add_quantityto_products.rb | 5 +++++ db/migrate/20180419224116_dropproducts_categories.rb | 5 +++++ ...rb => 20180419224513_create_products_categories_join.rb} | 4 ++-- db/schema.rb | 6 +++++- 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20180419223203_add_quantityto_products.rb create mode 100644 db/migrate/20180419224116_dropproducts_categories.rb rename db/migrate/{20180419011245_create_products_categories_join.rb => 20180419224513_create_products_categories_join.rb} (62%) diff --git a/db/migrate/20180419223203_add_quantityto_products.rb b/db/migrate/20180419223203_add_quantityto_products.rb new file mode 100644 index 0000000000..9e92707732 --- /dev/null +++ b/db/migrate/20180419223203_add_quantityto_products.rb @@ -0,0 +1,5 @@ +class AddQuantitytoProducts < ActiveRecord::Migration[5.1] + def change + add_column :products, :quantity, :integer + end +end diff --git a/db/migrate/20180419224116_dropproducts_categories.rb b/db/migrate/20180419224116_dropproducts_categories.rb new file mode 100644 index 0000000000..b363e1edc0 --- /dev/null +++ b/db/migrate/20180419224116_dropproducts_categories.rb @@ -0,0 +1,5 @@ +class DropproductsCategories < ActiveRecord::Migration[5.1] + def change + drop_table :products_categories + end +end diff --git a/db/migrate/20180419011245_create_products_categories_join.rb b/db/migrate/20180419224513_create_products_categories_join.rb similarity index 62% rename from db/migrate/20180419011245_create_products_categories_join.rb rename to db/migrate/20180419224513_create_products_categories_join.rb index 3af322f986..0f22d815e5 100644 --- a/db/migrate/20180419011245_create_products_categories_join.rb +++ b/db/migrate/20180419224513_create_products_categories_join.rb @@ -1,8 +1,8 @@ class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] def change create_table :products_categories do |t| - t.belongs_to :product, index: true - t.belongs_to :category, index: true + t.belongs_to :products, index: true + t.belongs_to :categories, index: true end end end diff --git a/db/schema.rb b/db/schema.rb index 5595995694..bd47d6ae54 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: 20180419221855) do +ActiveRecord::Schema.define(version: 20180419224513) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -48,6 +48,10 @@ end create_table "products_categories", force: :cascade do |t| + t.bigint "products_id" + t.bigint "categories_id" + t.index ["categories_id"], name: "index_products_categories_on_categories_id" + t.index ["products_id"], name: "index_products_categories_on_products_id" end create_table "reviews", force: :cascade do |t| From b8fa8314499c8c589835aa71cb33fe86cce3a92d Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 15:51:38 -0700 Subject: [PATCH 034/320] Adds user controler --- app/assets/javascripts/users.js | 2 ++ app/assets/stylesheets/users.scss | 3 ++ app/controllers/reviews_controller.rb | 4 --- app/controllers/users_controller.rb | 19 +++++++++++++ app/helpers/users_helper.rb | 2 ++ app/views/users/create.html.erb | 2 ++ app/views/users/edit.html.erb | 2 ++ app/views/users/index.html.erb | 2 ++ app/views/users/new.html.erb | 2 ++ app/views/users/show.html.erb | 2 ++ app/views/users/update.html.erb | 2 ++ config/routes.rb | 12 ++++++++ test/controllers/users_controller_test.rb | 34 +++++++++++++++++++++++ 13 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/users.js create mode 100644 app/assets/stylesheets/users.scss create mode 100644 app/controllers/users_controller.rb create mode 100644 app/helpers/users_helper.rb create mode 100644 app/views/users/create.html.erb create mode 100644 app/views/users/edit.html.erb create mode 100644 app/views/users/index.html.erb create mode 100644 app/views/users/new.html.erb create mode 100644 app/views/users/show.html.erb create mode 100644 app/views/users/update.html.erb create mode 100644 test/controllers/users_controller_test.rb diff --git a/app/assets/javascripts/users.js b/app/assets/javascripts/users.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/users.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/users.scss b/app/assets/stylesheets/users.scss new file mode 100644 index 0000000000..31a2eacb84 --- /dev/null +++ b/app/assets/stylesheets/users.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Users 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/reviews_controller.rb b/app/controllers/reviews_controller.rb index ada1bfa0d5..8a899b6208 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,8 +1,4 @@ class ReviewsController < ApplicationController - def new - - end - def create end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000000..456c01589a --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,19 @@ +class UsersController < ApplicationController + def index + end + + def show + end + + def new + end + + def create + end + + def edit + end + + def update + end +end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb new file mode 100644 index 0000000000..2310a240d7 --- /dev/null +++ b/app/helpers/users_helper.rb @@ -0,0 +1,2 @@ +module UsersHelper +end diff --git a/app/views/users/create.html.erb b/app/views/users/create.html.erb new file mode 100644 index 0000000000..48ea02e600 --- /dev/null +++ b/app/views/users/create.html.erb @@ -0,0 +1,2 @@ +

Users#create

+

Find me in app/views/users/create.html.erb

diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb new file mode 100644 index 0000000000..1881fbdba0 --- /dev/null +++ b/app/views/users/edit.html.erb @@ -0,0 +1,2 @@ +

Users#edit

+

Find me in app/views/users/edit.html.erb

diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb new file mode 100644 index 0000000000..51968c88d2 --- /dev/null +++ b/app/views/users/index.html.erb @@ -0,0 +1,2 @@ +

Users#index

+

Find me in app/views/users/index.html.erb

diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb new file mode 100644 index 0000000000..c21a1adf19 --- /dev/null +++ b/app/views/users/new.html.erb @@ -0,0 +1,2 @@ +

Users#new

+

Find me in app/views/users/new.html.erb

diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb new file mode 100644 index 0000000000..e5fa3adf14 --- /dev/null +++ b/app/views/users/show.html.erb @@ -0,0 +1,2 @@ +

Users#show

+

Find me in app/views/users/show.html.erb

diff --git a/app/views/users/update.html.erb b/app/views/users/update.html.erb new file mode 100644 index 0000000000..cabbde176a --- /dev/null +++ b/app/views/users/update.html.erb @@ -0,0 +1,2 @@ +

Users#update

+

Find me in app/views/users/update.html.erb

diff --git a/config/routes.rb b/config/routes.rb index 9d1446cb67..8dce58002e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,17 @@ Rails.application.routes.draw do + get 'users/index' + + get 'users/show' + + get 'users/new' + + get 'users/create' + + get 'users/edit' + + get 'users/update' + get "/auth/:provider/callback", to: "sessions#create", as: "auth_callback" get '/auth/github', as: 'github_login' diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb new file mode 100644 index 0000000000..eff93b9ed7 --- /dev/null +++ b/test/controllers/users_controller_test.rb @@ -0,0 +1,34 @@ +require "test_helper" + +describe UsersController do + it "should get index" do + get users_index_url + value(response).must_be :success? + end + + it "should get show" do + get users_show_url + value(response).must_be :success? + end + + it "should get new" do + get users_new_url + value(response).must_be :success? + end + + it "should get create" do + get users_create_url + value(response).must_be :success? + end + + it "should get edit" do + get users_edit_url + value(response).must_be :success? + end + + it "should get update" do + get users_update_url + value(response).must_be :success? + end + +end From 0a4bea54ae5c1bd925347e6946793048ed01330b Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 15:55:24 -0700 Subject: [PATCH 035/320] resloved merge conflicts in routes --- config/routes.rb | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 65f7d37ba8..88b52d889c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,21 +1,10 @@ Rails.application.routes.draw do - get 'users/index' - - get 'users/show' - - get 'users/new' - - get 'users/create' - - get 'users/edit' - - get 'users/update' + root 'products#index' get "/auth/:provider/callback", to: "sessions#create", as: "auth_callback" get '/auth/github', as: 'github_login' -<<<<<<< HEAD # resources :sessions # # resources :products @@ -32,21 +21,5 @@ end # resources :order_items -======= - root 'products#index' - - resources :sessions - - resources :products - - resources :categories - - resources :carts - - resources :reviews - - resources :users - resources :order_items ->>>>>>> a05701ef1fbecdcf3166ea3ca454ab3b3286871d end From ea99a276659eae6c67cf0fb76271832e06779847 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 16:17:20 -0700 Subject: [PATCH 036/320] git issues --- app/models/product.rb | 6 ++++-- test/models/order_item_test.rb | 7 ++----- test/models/product_test.rb | 10 +++++++++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/models/product.rb b/app/models/product.rb index e48b82bb31..b2d07253e8 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -5,6 +5,8 @@ class Product < ApplicationRecord validates :name, presence: true validates :name, length:{ minimum: 1 } - validates :price, presence: true - + validates :name, presence: true + validates :price, uniquness: true + validates :price, numericality: true + end diff --git a/test/models/order_item_test.rb b/test/models/order_item_test.rb index 3c7a08b4b2..3df9360b54 100644 --- a/test/models/order_item_test.rb +++ b/test/models/order_item_test.rb @@ -4,10 +4,7 @@ let(:order_item) { OrderItem.new } it "must be valid" do - @test = order_item - @test.product = - @test.order = - @test.save - value(order_item).must_be :valid? + salad = order_items(fruit_salad) + value(salad).must_be :valid? end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index a618b0a156..6f80a50608 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -4,6 +4,14 @@ let(:product) { Product.new } it "must be valid" do - value(product).must_be :valid? + cherries = products(cherries) + value(cherries).must_be :valid? + end + + it "must have a name of length > 1" do + cherries = products(cherries) + value(cherries).must_be :valid? + + end end From e032b85143398ea2f2838fe7b2bd04831ea48b67 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 19 Apr 2018 16:25:29 -0700 Subject: [PATCH 037/320] broke and semifixed model test for order_item --- app/models/order_item.rb | 13 ++++++++++--- app/models/product.rb | 2 +- test/models/order_item_test.rb | 20 ++++++++++---------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/app/models/order_item.rb b/app/models/order_item.rb index e58b1223eb..2baafe8e45 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -1,9 +1,16 @@ class OrderItem < ApplicationRecord - belongs_to :order, :items - validates :order_id, :item_id, presence: true + belongs_to :order + belongs_to :product + + validates :order_id, :product_id, presence: true + + # quantity must be greater than 0 + # must be an integer + # # I am not sure if this is correct # haven't written the model tests yet # I am h oping to to validate for unique combos of order_id and item_id to prevent repeat orders - validates :order_item, uniqueness: { :scope [:order_id, :item_id] } + + validates_uniqueness_of :order_item, :scope => [:order_id, :product_id] end diff --git a/app/models/product.rb b/app/models/product.rb index 4f37ab6da7..d15871d341 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,5 +1,5 @@ class Product < ApplicationRecord - has_many_and_belongs_to :categories + has_and_belongs_to_many :categories belongs_to :user has_many :reviews diff --git a/test/models/order_item_test.rb b/test/models/order_item_test.rb index 3c7a08b4b2..f3cdf4134f 100644 --- a/test/models/order_item_test.rb +++ b/test/models/order_item_test.rb @@ -1,13 +1,13 @@ -require "test_helper" +require 'test_helper' +require 'pry' describe OrderItem do - let(:order_item) { OrderItem.new } - - it "must be valid" do - @test = order_item - @test.product = - @test.order = - @test.save - value(order_item).must_be :valid? - end + # # let(:order_item) {order_items(:fruit_salad) } + # before do + # binding.pry + # @order_item = order_items(:fruit_salad) + # end + # it "must be valid" do + # @order_item.valid?.must_equal true + # end end From 0fed57b5c3c698191a492c6d5d610a023db223c1 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 16:25:32 -0700 Subject: [PATCH 038/320] routes --- config/routes.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index d88b8d5f6c..e5694d3bf1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,12 +8,13 @@ resources :products resources :categories + # + resources :orders - resources :carts + resources :users do + resources :products, except: [:delete] + resources :orders, only: [:index, :show] + resources :order_items, only: [:index] + end - resources :reviews - - resources :users - - resources :order_items end From 4defcedcc405def47de8cf8d5411e7cc1c632420 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 16:25:40 -0700 Subject: [PATCH 039/320] adds user id and quantity to products --- .../20180419232140_add_user_i_dto_products.rb | 5 +++++ .../20180419232327_add_quantityto_products.rb | 5 +++++ db/schema.rb | 16 +++++++++++----- 3 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20180419232140_add_user_i_dto_products.rb create mode 100644 db/migrate/20180419232327_add_quantityto_products.rb diff --git a/db/migrate/20180419232140_add_user_i_dto_products.rb b/db/migrate/20180419232140_add_user_i_dto_products.rb new file mode 100644 index 0000000000..bde24efa31 --- /dev/null +++ b/db/migrate/20180419232140_add_user_i_dto_products.rb @@ -0,0 +1,5 @@ +class AddUserIDtoProducts < ActiveRecord::Migration[5.1] + def change + add_column :products, :user_id, :integer + end +end diff --git a/db/migrate/20180419232327_add_quantityto_products.rb b/db/migrate/20180419232327_add_quantityto_products.rb new file mode 100644 index 0000000000..9e92707732 --- /dev/null +++ b/db/migrate/20180419232327_add_quantityto_products.rb @@ -0,0 +1,5 @@ +class AddQuantitytoProducts < ActiveRecord::Migration[5.1] + def change + add_column :products, :quantity, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 7dd09ed626..47359621bb 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: 20180419212546) do +ActiveRecord::Schema.define(version: 20180419232327) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -25,6 +25,9 @@ t.integer "order_id" t.integer "product_id" t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "status" end create_table "orders", force: :cascade do |t| @@ -41,13 +44,16 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "category_id" + t.string "image" + t.integer "user_id" + t.integer "quantity" end create_table "products_categories", force: :cascade do |t| - t.bigint "product_id" - t.bigint "category_id" - t.index ["category_id"], name: "index_products_categories_on_category_id" - t.index ["product_id"], name: "index_products_categories_on_product_id" + t.bigint "products_id" + t.bigint "categories_id" + t.index ["categories_id"], name: "index_products_categories_on_categories_id" + t.index ["products_id"], name: "index_products_categories_on_products_id" end create_table "reviews", force: :cascade do |t| From 216fbe5848a168a15c8c67d98428c5450b87a0dc Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 16:27:05 -0700 Subject: [PATCH 040/320] routes change --- config/routes.rb | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index b8024987bb..eb79564f9a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,10 @@ Rails.application.routes.draw do + root 'products#index' get "/auth/:provider/callback", to: "sessions#create", as: "auth_callback" get '/auth/github', as: 'github_login' -<<<<<<< HEAD + # resources :sessions # # resources :products @@ -18,23 +19,3 @@ resources :orders resources :products end - - # resources :order_items -======= - root 'products#index' - - resources :sessions - - resources :products - - resources :categories - - resources :carts - - resources :reviews - - resources :users - - resources :order_items ->>>>>>> a05701ef1fbecdcf3166ea3ca454ab3b3286871d -end From f01568e6fa5ff4ea48b010f1d75343b0081210bc Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 16:30:55 -0700 Subject: [PATCH 041/320] renames cart model to order model --- app/models/{cart.rb => order.rb} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename app/models/{cart.rb => order.rb} (60%) diff --git a/app/models/cart.rb b/app/models/order.rb similarity index 60% rename from app/models/cart.rb rename to app/models/order.rb index a2f2e36f91..d9f7bbf7ec 100644 --- a/app/models/cart.rb +++ b/app/models/order.rb @@ -1,4 +1,4 @@ -class Cart < ApplicationRecord +class Order < ApplicationRecord has_many :order_items belongs_to :user From 24993196524688303f96a69a311f1e5814b1818e Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 16:36:48 -0700 Subject: [PATCH 042/320] fixes model validations typos --- app/models/product.rb | 2 +- app/models/review.rb | 2 +- app/models/user.rb | 2 +- db/migrate/20180419223203_add_quantityto_products.rb | 5 ----- db/schema.rb | 4 ---- 5 files changed, 3 insertions(+), 12 deletions(-) delete mode 100644 db/migrate/20180419223203_add_quantityto_products.rb diff --git a/app/models/product.rb b/app/models/product.rb index 4b9c2d25aa..fd448a146a 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -6,7 +6,7 @@ class Product < ApplicationRecord validates :name, presence: true validates :name, length:{ minimum: 1 } validates :name, presence: true - validates :price, uniquness: true + validates :price, uniqueness: true validates :price, numericality: true end diff --git a/app/models/review.rb b/app/models/review.rb index 5c6bd9d97a..f14963c24c 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -3,7 +3,7 @@ class Review < ApplicationRecord belongs_to :products validates :rating, { - pressence: true, + presence: true, numericality: { only_integer: true }, inclusion: { in: 1..5} } diff --git a/app/models/user.rb b/app/models/user.rb index d64b70d9f8..fd6d2a8b8b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,5 +2,5 @@ class User < ApplicationRecord belongs_to :order has_many :products - validates :name, presence: true, uniquness: true + validates :name, presence: true, uniqueness: true end diff --git a/db/migrate/20180419223203_add_quantityto_products.rb b/db/migrate/20180419223203_add_quantityto_products.rb deleted file mode 100644 index 9e92707732..0000000000 --- a/db/migrate/20180419223203_add_quantityto_products.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddQuantitytoProducts < ActiveRecord::Migration[5.1] - def change - add_column :products, :quantity, :integer - end -end diff --git a/db/schema.rb b/db/schema.rb index 9ab8b9bc68..47359621bb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -<<<<<<< HEAD -ActiveRecord::Schema.define(version: 20180419224513) do -======= ActiveRecord::Schema.define(version: 20180419232327) do ->>>>>>> mary_thursday # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" From 3b2954eaa02a433e90f2912720c6125ed2863943 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 16:37:37 -0700 Subject: [PATCH 043/320] nested-routes --- app/models/order.rb | 5 +++++ config/routes.rb | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 app/models/order.rb diff --git a/app/models/order.rb b/app/models/order.rb new file mode 100644 index 0000000000..d9f7bbf7ec --- /dev/null +++ b/app/models/order.rb @@ -0,0 +1,5 @@ +class Order < ApplicationRecord + has_many :order_items + belongs_to :user + +end diff --git a/config/routes.rb b/config/routes.rb index e5694d3bf1..9f5a2f4001 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,8 +8,8 @@ resources :products resources :categories - # - resources :orders + + # resources :orders resources :users do resources :products, except: [:delete] From 0518df569a4a96c5ef4ba12d7dbe1cce0b909aa4 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 17:10:48 -0700 Subject: [PATCH 044/320] attempting to commit --- app/views/layouts/application.html.erb | 2 +- db/schema.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 32e9813880..eee8af6812 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -16,7 +16,7 @@
diff --git a/db/schema.rb b/db/schema.rb index bd47d6ae54..0de9235690 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -45,6 +45,7 @@ t.datetime "updated_at", null: false t.integer "category_id" t.string "image" + t.integer "quantity" end create_table "products_categories", force: :cascade do |t| From dc5ad0dcf880b318a2ede854f2d1c00e16c8d235 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 17:25:14 -0700 Subject: [PATCH 045/320] working on tests --- app/models/category.rb | 4 ++-- app/models/product.rb | 4 +--- test/fixtures/categories.yml | 4 ++-- test/fixtures/{carts.yml => orders.yml} | 0 test/fixtures/products.yml | 6 +++--- test/models/cart_test.rb | 6 +++--- test/models/product_test.rb | 7 +------ 7 files changed, 12 insertions(+), 19 deletions(-) rename test/fixtures/{carts.yml => orders.yml} (100%) diff --git a/app/models/category.rb b/app/models/category.rb index ba7c56788e..9c5816f400 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,5 +1,5 @@ class Category < ApplicationRecord - has_and_belongs_to_many :products + has_and_belongs_to_many :products, join_table: :products_categories + - end diff --git a/app/models/product.rb b/app/models/product.rb index fd448a146a..ebeae0bcba 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,12 +1,10 @@ class Product < ApplicationRecord - has_and_belongs_to_many :categories + has_and_belongs_to_many :categories, join_table: :products_categories belongs_to :user has_many :reviews validates :name, presence: true validates :name, length:{ minimum: 1 } - validates :name, presence: true - validates :price, uniqueness: true validates :price, numericality: true end diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml index 0ec843cca5..f39b38cfe4 100644 --- a/test/fixtures/categories.yml +++ b/test/fixtures/categories.yml @@ -1,7 +1,7 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -category1: +summer: name: summer fruit -category2: +fruit: name: fruit salad diff --git a/test/fixtures/carts.yml b/test/fixtures/orders.yml similarity index 100% rename from test/fixtures/carts.yml rename to test/fixtures/orders.yml diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index e3d9ef0021..6508b74340 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -3,16 +3,16 @@ cherries: name: cherries price: 3.0 description: 1kg ranier cherries - category: summer + watermelon: name: watermelon price: 4.0 description: seedless - category: summer + orange: name: orange price: 1.0 description: single orange - category: fruit + diff --git a/test/models/cart_test.rb b/test/models/cart_test.rb index 48dae906b2..a1de67f4db 100644 --- a/test/models/cart_test.rb +++ b/test/models/cart_test.rb @@ -1,9 +1,9 @@ require "test_helper" -describe Cart do - let(:cart) { carts(:cart1)} +describe Order do + it "must be valid" do - cart.valid?.must_equal true + order.valid?.must_equal true end end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 6f80a50608..8d87f158c8 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -4,14 +4,9 @@ let(:product) { Product.new } it "must be valid" do - cherries = products(cherries) + cherries = products(:cherries) value(cherries).must_be :valid? end - it "must have a name of length > 1" do - cherries = products(cherries) - value(cherries).must_be :valid? - - end end From 636a94f3fe18deff6ee4d7922529e7236b582877 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 17:40:04 -0700 Subject: [PATCH 046/320] adds seeds for category, merchant and products --- db/Categoryseed.csv | 6 ++++++ db/MerchantSeed.csv | 5 +++++ db/ProductSeed.csv | 21 +++++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 db/Categoryseed.csv create mode 100644 db/MerchantSeed.csv create mode 100644 db/ProductSeed.csv diff --git a/db/Categoryseed.csv b/db/Categoryseed.csv new file mode 100644 index 0000000000..4bff8612f4 --- /dev/null +++ b/db/Categoryseed.csv @@ -0,0 +1,6 @@ +Category +Bunches +Citrus +Pome +Pits +Edible skin \ No newline at end of file diff --git a/db/MerchantSeed.csv b/db/MerchantSeed.csv new file mode 100644 index 0000000000..351017b9cc --- /dev/null +++ b/db/MerchantSeed.csv @@ -0,0 +1,5 @@ +name,email,UID,provider +Joe Schmo,Joe@Schmo.com,234134,github +Margo Tenenbaum,margot@tenenbaum.com,34363838,github +Tabitha Baker,tabitha@baker.com,24354325,github +Lucy Sanders,lucy@sanders.com,2635467,github \ No newline at end of file diff --git a/db/ProductSeed.csv b/db/ProductSeed.csv new file mode 100644 index 0000000000..b809b675b8 --- /dev/null +++ b/db/ProductSeed.csv @@ -0,0 +1,21 @@ +Product,price,description,merchant_id,quantity +Honey Crisp Apple,1.00,"Their creamy white flesh is exceptionally crisp and aromatic. A balanced content of sugar and acid gives Honeycrisp apples a pleasant sweet-tart flavor that varies in strength depending upon the maturity of the apple.",1,30 +Banana,0.25,"Bananas are rich in potassium, riboflavin, niacin, and dietary fibre. They also have high energy value and are really good for growing children and athletes. They are also excellent for low-salt, low-fat, and cholesterol-free diets. Hundreds of different varieties of banana flourish in the tropics, from sweet yellow pygmy to large fibrous plantains and green bananas, which can only be used for cooking.",1,50 +Rainier Cherries,2.99,Sweet and juicy,1,30 +Green Grapes,2.00,"A great energy source because of their natural fruit sugar content",1,300 +Grapefruit,1.00,"One of the largest citrus fruit, grapefruits are a cross between the pomelo and the shaddock. High in vitamin C, grapefruits are best eaten raw, a traditional breakfast fruit. The best way to eat is to cut them in half and scoop out the flesh with a spoon.",1,10 +Kumquat,0.50,"The name means ""golden orange"" in Chinese. Kumquats are often preserved in sweet syrup and used for marmalade and garnishes, but fresh ones are delicious in fruit salads or for eating just as they are.",1,80 +Lemon,0.25,"Rarely eaten on its own, lemons are an indispensable ingredient in the kitchen. Lemon juice can be used instead of vinegar in sauces, for seasoning in vinaigrette and as instant dressing for fish and shellfish. The best way to store lemon is in the vegetable crisper in the fridge you can put lemons in fruit bowl for a shorter, check them often - if one starts to spoil, the rest will quickly follow.",1,15 +Pineapple,3.00,"Derived from the Spanish word 'pina' meaning pine cone. Pineapples have a juicy, sweet-but sometimes slightly tart-fragrant flavour. They are best eaten fresh, serve pineapple flesh in slices, wedges or chunks. It is also available in cans, dried and glace. A good source of vitamin C.",1,14 +Plums,1.25,"Plums contain more antioxidant than any other fruit. Plums are delicate so make sure that the one you buy are unblemished, and they should be plump and firm. The small sugar plum is dried to make prunes. Delicious stewed, plums are also ideal for making chutneys.",1,16 +Start Apple,1.15,"The star apple fruits are green to purple with a smooth skin. When sliced horizontally the flesh is translucent white with the seeds forming a star shape. It is best eaten ripe, scooped straight from the skin. It is ripe when soft and should be eaten immediately, but it is still alright to refrigerate for a few days.",1,45 +Strawberry,2.78,"A unique fruit, the seeds grow around the outside of the fruit rather than inside it. Comes in many different sizes, colours and shapes, ranging from cone-like, to oval, or heart-shaped. Best to eat on their own or with natural yoghurt. Use strawberries in desserts, fruit salads, preserves, or in milkshakes.",2,26 +Watermelon,5.00,"The high water content of watermelons means that they are low in calories. They contain some vitamins B and C. Watermelon is excellent juiced, chopped up into a fruit salad, or just eaten in chunky slices.",2,43 +Tamarillo,1.65,"these are related to tomatoes and sometimes called ""tree tomatoes."" They are the size of an egg tomato, with dark red skin. The fruit has a strong, sweet flavour that makes it suitable for both sweet or savoury dishes. It can also be used in jams, chutneys, and sorbets.",2,12 +Rambutan,3.40,"The rambutan fruit grows in clusters, with a deep crimson outer skin. The flesh is translucent, and the pale seed is edible when young. Related to lychees and are sometimes known as ""hairy lychees"".(about 5cm / 2inches in diameter) and look quite different but have a similar texture. They can be added to salads, made into jams or jellies, but they are best eaten on their own.",2,3 +Peach,2.25,"Or pawpaw, a large tropical fruit whose ripe flesh can be juicy, creamy, orange-red, or yellow. In the centre is a mass of large peppery black seeds, which are edible and sometimes crushed and used as a spice. Ripe papaya is eaten as a breakfast fruit or as a dessert. It can also be pureed for ice cream, sorbets and iced drinks.",2,9 +Fig,0.50,"Figs are oval or pear-shaped and can be eaten fresh or dried. They are well known for their laxative and digestive properties. Their high, natural sugar content makes them the sweetest of all fruits. The flavour varies, depending on where they were grown and how ripe they are.",3,24 +Lime,0.25,"Limes are only green because they are picked unripe but if left to ripen they turn yellow. Limes can be used like lemons but as juice, it is more acidic, so usually less is needed. To make the juice flow more, you can microwave the limes for 2-3 seconds before squeezing. Mostly used in drinks (lime cordials) and cooking.",3,65 +Passionfruit,3.00,"The most popular variety is the purple passionfruit about the size of a chicken egg. It has a highly fragrant, sweet, but slightly tart, tasting fruit that can be spooned out and eaten fresh or added to fruit salad, pavlova, and it makes a very popular drink, ice cream and sorbets and a flavouring for all kinds of desserts.",3,43 +Nectarine,1.25,"The nectarine flesh is rich, sweet and juicy and is well suited for eating fresh and for using in ice cream, pies and fruit salads. Colour ranges from silvery white or yellowy orange to pinkish red. The white-fleshed varieties are considered the best and usually the most expensive. Nectarines are often described as a cross between a peach and a plum, but nectarines are actually a variety of smooth-skinned peach.",3,2 +Mangosteen,1.15,"Contrary to its name, the mangosteen doesn't resemble or taste like the mango. It resemble an apple, having a short stem and four thick leaf-like bracts which form a rosette encasing the brownish-purple fruit.",3,7 From 349874acb462dc9c1a6d0b7bc1277c509cf27bc0 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 17:41:18 -0700 Subject: [PATCH 047/320] created seed.rb file --- db/seeds.rb | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/db/seeds.rb b/db/seeds.rb index 1beea2accd..0f078f742a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,3 +5,122 @@ # # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) + +require 'csv' + +USER_FILE = Rails.root.join('db', 'user_seeds.csv') +puts "Loading user data from #{USER_FILE}" + +user_failures = [] +CSV.foreach(USER_FILE, :headers => true) do |row| + user = User.new + user.name = row['name'] + user.email = row['email'] + user.uid = row['uid'] + user.provider = row['provider'] + + successful = user.save + if !successful + user_failures << user + puts "Failed to save user: #{user.inspect}" + else + puts "Created user: #{user.inspect}" + end +end + +# REVIEW_FILE = Rails.root.join('db', 'review_seeds.csv') +# puts "Loading review data from #{REVIEW_FILE}" +# +# review_failures = [] +# CSV.foreach(REVIEW_FILE, :headers => true) do |row| +# review = Review.new +# review.rating = row['rating'] +# review.text_review = row['text_review'] +# review.product_id = row['product_id'] +# +# successful = review.save +# if !successful +# review_failures << review +# puts "Failed to save review: #{review.inspect}" +# else +# puts "Created review: #{review.inspect}" +# end +# end + +PRODUCT_FILE = Rails.root.join('db', 'product_seeds.csv') +puts "Loading product data from #{PRODUCT_FILE}" + +product_failures = [] +CSV.foreach(PRODUCT_FILE, :headers => true) do |row| + product = Product.new + product.name = row['name'] + product.price = row['price'] + product.description = row['description'] + product.category_id = row['category_id'] + product.image = row['image'] + product.user_id = row['user_id'] + product.quantity = row['quantity'] + + successful = product.save + if !successful + product_failures << product + puts "Failed to save product: #{product.inspect}" + else + puts "Created product: #{product.inspect}" + end +end + +CATEGORY_FILE = Rails.root.join('db', 'category_seeds.csv') +puts "Loading category data from #{CATEGORY_FILE}" + +category_failures = [] +CSV.foreach(CATEGORY_FILE, :headers => true) do |row| + category = Category.new + category.name = row['name'] + + successful = category.save + if !successful + category_failures << category + puts "Failed to save category: #{category.inspect}" + else + puts "Created category: #{category.inspect}" + end +end + +# ORDER_FILE = Rails.root.join('db', 'order_seeds.csv') +# puts "Loading order data from #{ORDER_FILE}" +# +# order_failures = [] +# CSV.foreach(ORDER_FILE, :headers => true) do |row| +# order = Order.new +# order.user_id = row['user_id'] +# order.status = row['status'] +# +# successful = order.save +# if !successful +# order_failures << order +# puts "Failed to save order: #{order.inspect}" +# else +# puts "Created order: #{order.inspect}" +# end +# end + +# ORDER_ITEM_FILE = Rails.root.join('db', 'order_item_seeds.csv') +# puts "Loading order_item data from #{ORDER_ITEM_FILE}" +# +# order_item_failures = [] +# CSV.foreach(ORDER_ITEM_FILE, :headers => true) do |row| +# order_item = Order_item.new +# order_item.order_id = row['order_id'] +# order_item.product_id = row['product_id'] +# order_item.quantity = row['quantity'] +# order_item.status = row['status'] +# +# successful = order_item.save +# if !successful +# order_item_failures << order_item +# puts "Failed to save order_item: #{order_item.inspect}" +# else +# puts "Created order_item: #{order_item.inspect}" +# end +# end From fb21f19b2caf03347c28e3dfa5b79667f6c99285 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 19 Apr 2018 17:45:28 -0700 Subject: [PATCH 048/320] refactors seed file to match csv file --- db/seeds.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index 0f078f742a..6e6794c814 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -8,7 +8,7 @@ require 'csv' -USER_FILE = Rails.root.join('db', 'user_seeds.csv') +USER_FILE = Rails.root.join('db', 'MerchantSeed.csv') puts "Loading user data from #{USER_FILE}" user_failures = [] @@ -16,7 +16,7 @@ user = User.new user.name = row['name'] user.email = row['email'] - user.uid = row['uid'] + user.uid = row['UID'] user.provider = row['provider'] successful = user.save @@ -47,18 +47,18 @@ # end # end -PRODUCT_FILE = Rails.root.join('db', 'product_seeds.csv') +PRODUCT_FILE = Rails.root.join('db', 'ProductSeed.csv') puts "Loading product data from #{PRODUCT_FILE}" product_failures = [] CSV.foreach(PRODUCT_FILE, :headers => true) do |row| product = Product.new - product.name = row['name'] + product.name = row['Product'] product.price = row['price'] product.description = row['description'] - product.category_id = row['category_id'] + # product.category_id = row['category_id'] product.image = row['image'] - product.user_id = row['user_id'] + product.user_id = row['merchant_id'] product.quantity = row['quantity'] successful = product.save @@ -70,13 +70,13 @@ end end -CATEGORY_FILE = Rails.root.join('db', 'category_seeds.csv') +CATEGORY_FILE = Rails.root.join('db', 'Categoryseed.csv') puts "Loading category data from #{CATEGORY_FILE}" category_failures = [] CSV.foreach(CATEGORY_FILE, :headers => true) do |row| category = Category.new - category.name = row['name'] + category.name = row['Category'] successful = category.save if !successful From c6c4073760656933b588ed7d46a62b5f0a86e014 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 18:15:57 -0700 Subject: [PATCH 049/320] MORE schema changes fml --- ...0180419224513_create_products_categories_join.rb | 8 -------- db/migrate/20180420005014_remove_columns.rb | 5 +++++ db/migrate/20180420011146_drop_installs.rb | 5 +++++ ...0180420011411_create_products_categories_join.rb | 8 ++++++++ db/schema.rb | 13 ++++++------- test/fixtures/products.yml | 2 +- test/models/product_test.rb | 5 +++++ 7 files changed, 30 insertions(+), 16 deletions(-) delete mode 100644 db/migrate/20180419224513_create_products_categories_join.rb create mode 100644 db/migrate/20180420005014_remove_columns.rb create mode 100644 db/migrate/20180420011146_drop_installs.rb create mode 100644 db/migrate/20180420011411_create_products_categories_join.rb diff --git a/db/migrate/20180419224513_create_products_categories_join.rb b/db/migrate/20180419224513_create_products_categories_join.rb deleted file mode 100644 index 0f22d815e5..0000000000 --- a/db/migrate/20180419224513_create_products_categories_join.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] - def change - create_table :products_categories do |t| - t.belongs_to :products, index: true - t.belongs_to :categories, index: true - end - end -end diff --git a/db/migrate/20180420005014_remove_columns.rb b/db/migrate/20180420005014_remove_columns.rb new file mode 100644 index 0000000000..bd3418a505 --- /dev/null +++ b/db/migrate/20180420005014_remove_columns.rb @@ -0,0 +1,5 @@ +class RemoveColumns < ActiveRecord::Migration[5.1] + def change + remove_column :products, :category_id + end +end diff --git a/db/migrate/20180420011146_drop_installs.rb b/db/migrate/20180420011146_drop_installs.rb new file mode 100644 index 0000000000..b0b445e1eb --- /dev/null +++ b/db/migrate/20180420011146_drop_installs.rb @@ -0,0 +1,5 @@ +class DropInstalls < ActiveRecord::Migration[5.1] + def change + drop_table :products_categories + end +end diff --git a/db/migrate/20180420011411_create_products_categories_join.rb b/db/migrate/20180420011411_create_products_categories_join.rb new file mode 100644 index 0000000000..a226c63542 --- /dev/null +++ b/db/migrate/20180420011411_create_products_categories_join.rb @@ -0,0 +1,8 @@ +class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] + def change + create_table :products_categories_joins do |t| + t.belongs_to :product, index: true + t.belongs_to :category, index: true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 47359621bb..e3f5f63d5b 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: 20180419232327) do +ActiveRecord::Schema.define(version: 20180420011411) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -43,17 +43,16 @@ t.string "description" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "category_id" t.string "image" t.integer "user_id" t.integer "quantity" end - create_table "products_categories", force: :cascade do |t| - t.bigint "products_id" - t.bigint "categories_id" - t.index ["categories_id"], name: "index_products_categories_on_categories_id" - t.index ["products_id"], name: "index_products_categories_on_products_id" + create_table "products_categories_joins", force: :cascade do |t| + t.bigint "product_id" + t.bigint "category_id" + t.index ["category_id"], name: "index_products_categories_joins_on_category_id" + t.index ["product_id"], name: "index_products_categories_joins_on_product_id" end create_table "reviews", force: :cascade do |t| diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 6508b74340..cdaf92c769 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -3,6 +3,7 @@ cherries: name: cherries price: 3.0 description: 1kg ranier cherries + user_id: beyonce.id watermelon: @@ -15,4 +16,3 @@ orange: name: orange price: 1.0 description: single orange - diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 8d87f158c8..228ebc7a0a 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -5,8 +5,13 @@ it "must be valid" do cherries = products(:cherries) + value(cherries).must_be :valid? + end + it "must have an array of categories" do + products(:cherries).categories.must_equal [] + end end From 080a55e05c7f3826fb647ea2f69da7fb03d1ee5b Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 19 Apr 2018 18:23:56 -0700 Subject: [PATCH 050/320] omg the join table --- .../20180420011411_create_products_categories_join.rb | 8 -------- db/migrate/20180420012112_droptable.rb | 6 ++++++ .../20180420012158_create_products_categories_join.rb | 10 ++++++++++ db/schema.rb | 8 ++++---- 4 files changed, 20 insertions(+), 12 deletions(-) delete mode 100644 db/migrate/20180420011411_create_products_categories_join.rb create mode 100644 db/migrate/20180420012112_droptable.rb create mode 100644 db/migrate/20180420012158_create_products_categories_join.rb diff --git a/db/migrate/20180420011411_create_products_categories_join.rb b/db/migrate/20180420011411_create_products_categories_join.rb deleted file mode 100644 index a226c63542..0000000000 --- a/db/migrate/20180420011411_create_products_categories_join.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] - def change - create_table :products_categories_joins do |t| - t.belongs_to :product, index: true - t.belongs_to :category, index: true - end - end -end diff --git a/db/migrate/20180420012112_droptable.rb b/db/migrate/20180420012112_droptable.rb new file mode 100644 index 0000000000..1058fe4cb6 --- /dev/null +++ b/db/migrate/20180420012112_droptable.rb @@ -0,0 +1,6 @@ +class Droptable < ActiveRecord::Migration[5.1] + def change + drop_table :products_categories_joins + + end +end diff --git a/db/migrate/20180420012158_create_products_categories_join.rb b/db/migrate/20180420012158_create_products_categories_join.rb new file mode 100644 index 0000000000..b14ff3db92 --- /dev/null +++ b/db/migrate/20180420012158_create_products_categories_join.rb @@ -0,0 +1,10 @@ +class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] + def change + create_table :products_categories do |t| + + t.belongs_to :product, index: true + t.belongs_to :category, index: true + + end + end +end diff --git a/db/schema.rb b/db/schema.rb index e3f5f63d5b..729be30d7b 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: 20180420011411) do +ActiveRecord::Schema.define(version: 20180420012158) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -48,11 +48,11 @@ t.integer "quantity" end - create_table "products_categories_joins", force: :cascade do |t| + create_table "products_categories", force: :cascade do |t| t.bigint "product_id" t.bigint "category_id" - t.index ["category_id"], name: "index_products_categories_joins_on_category_id" - t.index ["product_id"], name: "index_products_categories_joins_on_product_id" + t.index ["category_id"], name: "index_products_categories_on_category_id" + t.index ["product_id"], name: "index_products_categories_on_product_id" end create_table "reviews", force: :cascade do |t| From a51ad296e1001e417614bec00a1d2c73dbac97f5 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 19 Apr 2018 19:04:00 -0700 Subject: [PATCH 051/320] removed unique price validation from product and other bug fixes --- app/models/product.rb | 1 - app/models/user.rb | 2 +- app/views/layouts/application.html.erb | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/models/product.rb b/app/models/product.rb index fd448a146a..6b74d09358 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -6,7 +6,6 @@ class Product < ApplicationRecord validates :name, presence: true validates :name, length:{ minimum: 1 } validates :name, presence: true - validates :price, uniqueness: true validates :price, numericality: true end diff --git a/app/models/user.rb b/app/models/user.rb index fd6d2a8b8b..881c4dc379 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,5 @@ class User < ApplicationRecord - belongs_to :order + has_many :order has_many :products validates :name, presence: true, uniqueness: true diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index eee8af6812..8ae940000e 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -15,7 +15,7 @@
+
+ <% flash.each do |name, message| %> +

+ <%= message %> +

+ <% end %> +
+ <%= yield %> diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index d63a69fb54..91d235a84e 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -1,2 +1,4 @@ + +

Orders#index

Find me in app/views/orders/index.html.erb

diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index f6b45c4fce..0e375b475b 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -11,3 +11,11 @@ +
+ <%= form_with url: order_path do |form| %> + <%= form.label 'quantity' %> + <%= form.number_field 'quantity' %> + <%= form.hidden_field :product_id, value: @product.id %> + <%= form.submit "Add to Order" %> + <% end %> +
diff --git a/app/views/reviews/_form.html.erb b/app/views/reviews/_form.html.erb index 16cdbcee67..aeb90d3ab4 100644 --- a/app/views/reviews/_form.html.erb +++ b/app/views/reviews/_form.html.erb @@ -4,5 +4,5 @@ <%= f.label :text_review %> <%= f.text_field :text_review %> - <%= f.submit %> + <%= f.submit "Add to Order" %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index d70a5f52e1..255f199996 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,14 +2,17 @@ root 'products#index' - get '/order', to: 'orders#index', as: 'order' + # get '/order', to: 'orders#index', as: 'order' + # post '/order', to: 'orders#create', as: 'add_to_order' get "/auth/:provider/callback", to: "users#create", as: "auth_callback" get '/auth/github', as: 'github_login' delete '/logout', to: "users#destroy", as: "logout" - resources :sessions + # resources :sessions + get '/order', to: 'sessions#index', as: 'order' + post '/order', to: 'sessions#create', as: 'add_to_order' resources :products From 5a9afdc0fcabd89e62524859b4026164ec2f5945 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Sat, 21 Apr 2018 14:59:28 -0700 Subject: [PATCH 083/320] product : review nested route, create and new methods in treview controller --- app/controllers/products_controller.rb | 4 ++++ app/controllers/reviews_controller.rb | 26 ++++++++++++++++++++++++++ app/models/product.rb | 1 + app/models/review.rb | 11 +++++++++++ app/views/products/show.html.erb | 11 +++++++++-- app/views/reviews/_form.html.erb | 3 ++- app/views/reviews/create.html.erb | 2 -- app/views/reviews/new.html.erb | 2 ++ config/routes.rb | 5 ++++- 9 files changed, 59 insertions(+), 6 deletions(-) delete mode 100644 app/views/reviews/create.html.erb diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index a2182e668c..690f6e73da 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -28,6 +28,10 @@ def show def destroy end + # def review_rating + # return Review.average_rating(product_reviews) + # end + private def product_params diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 8a899b6208..5dddccdf7d 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,4 +1,30 @@ class ReviewsController < ApplicationController + + def new + @review = Review.new + end + def create + @review = Review.new(review_params) + @product = Product.find(@review.product_id) + if @product.save + flash[:status] = :success + flash[:result_text] = "Successfully reviewed #{@product.name}" + redirect_to new_product_review_path(@product.id) + else + flash[:status] = :failure + flash[:result_text] = "Could not review #{@product.name}" + flash[:messages] = @work.errors.messages + render :new, status: :bad_request + end + end + + def index + end + + private + def review_params + params.require(:review).permit(:rating, :text_review, :product_id) end + end diff --git a/app/models/product.rb b/app/models/product.rb index da2161ee02..01a90aaed0 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -14,4 +14,5 @@ class Product < ApplicationRecord numericality: { greater_than: 0 } } + end diff --git a/app/models/review.rb b/app/models/review.rb index 8efa56b3bd..f6a2b99616 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -7,4 +7,15 @@ class Review < ApplicationRecord numericality: { only_integer: true }, inclusion: { in: 1..5} } + + # should this be in product or in reviews model? + # def self.average_rating(reviews) + # total = 0 + # reviews.each do |rating| + # total += rating + # end + # + # return total/(reviews.count).round(1) + # end + end diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 76058f6fb2..aa6a1badf2 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,5 +1,7 @@

<%= @product.name %>

- +
+ <%= link_to "Review #{@product.name}", new_product_review_path(@product.id) %> +
fruit! @@ -9,5 +11,10 @@
- +

Reviews

+
    + <% @product.reviews.each do |review| %> +
  • <%= review.text_review %>
  • + <% end %> +
diff --git a/app/views/reviews/_form.html.erb b/app/views/reviews/_form.html.erb index 16cdbcee67..66f06f500b 100644 --- a/app/views/reviews/_form.html.erb +++ b/app/views/reviews/_form.html.erb @@ -1,8 +1,9 @@ -<%= form review do |f| %> +<%= form_for @review, url: {action: "create"} do |f| %> <%= f.label :rating %> <%= f.select :rating, 1..5, :prompt => "Select One" %> <%= f.label :text_review %> <%= f.text_field :text_review %> + <%= f.submit %> <% end %> diff --git a/app/views/reviews/create.html.erb b/app/views/reviews/create.html.erb deleted file mode 100644 index 44bf11c2ed..0000000000 --- a/app/views/reviews/create.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

Reviews#create

-

Find me in app/views/reviews/create.html.erb

diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb index e69de29bb2..6f9b1ca0ad 100644 --- a/app/views/reviews/new.html.erb +++ b/app/views/reviews/new.html.erb @@ -0,0 +1,2 @@ +

Add Review

+<%= render partial: "form" %> diff --git a/config/routes.rb b/config/routes.rb index f78af722ac..ece5284cc3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,10 +8,13 @@ resources :sessions - resources :products + resources :products do + resources :reviews + end resources :categories + # resources :orders resources :users do From ae9a36182eb82405355d6156795dc25d5abb9cc0 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Sat, 21 Apr 2018 15:02:38 -0700 Subject: [PATCH 084/320] problem with params method in review controller, show page has link to new review form --- app/controllers/reviews_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 5dddccdf7d..9f1f40366c 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -6,8 +6,8 @@ def new def create @review = Review.new(review_params) - @product = Product.find(@review.product_id) - if @product.save + @product = Product.find_by(review_params :product_id) + if @review.save flash[:status] = :success flash[:result_text] = "Successfully reviewed #{@product.name}" redirect_to new_product_review_path(@product.id) From d010cbad4fa726ad927271fdd93684ea887b2dce Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Sat, 21 Apr 2018 15:11:51 -0700 Subject: [PATCH 085/320] model testing cont --- app/models/category.rb | 5 +++++ app/models/order_item.rb | 2 +- test/models/category_test.rb | 31 ++++++++++++++++++++++++++++--- test/models/order_item_test.rb | 3 ++- test/models/review_test.rb | 2 +- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/models/category.rb b/app/models/category.rb index 9c5816f400..a5a0cf961b 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,5 +1,10 @@ class Category < ApplicationRecord has_and_belongs_to_many :products, join_table: :products_categories + validates :name, { + presence: true, + uniqueness: true, + length: { minimum: 1 } + } end diff --git a/app/models/order_item.rb b/app/models/order_item.rb index 0bb292c707..888ef85753 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -6,7 +6,7 @@ class OrderItem < ApplicationRecord validates :quantity, { presence: true, - numericality: {greater_than: 0} + numericality: true } diff --git a/test/models/category_test.rb b/test/models/category_test.rb index 781320ad8e..3fdb004a00 100644 --- a/test/models/category_test.rb +++ b/test/models/category_test.rb @@ -1,9 +1,34 @@ require "test_helper" describe Category do - let(:category) { Category.new } + let(:category) { categories(:summer) } - it "must be valid" do - value(category).must_be :valid? + + it "must have a name" do + category.valid?.must_equal true + category.name = nil + category.valid?.must_equal false + end + + it "must have a name of length > 1" do + category.name = "" + category.valid?.must_equal false + end + + it "must have a unique name" do + fruit = categories(:fruit) + fruit.name = "summer fruit" + fruit.valid?.must_equal false + end + + it "can have zero products" do + category.products.must_equal [] + end + + it "can have many products" do + category.products << products(:cherries) + category.products << products(:watermelon) + + category.products.count.must_equal 2 end end diff --git a/test/models/order_item_test.rb b/test/models/order_item_test.rb index ce9d8039b4..bed50fe8c1 100644 --- a/test/models/order_item_test.rb +++ b/test/models/order_item_test.rb @@ -5,8 +5,9 @@ let(:order_item) { OrderItem.new } it "must be valid" do - salad = order_items(fruit_salad) + salad = order_items(:fruit_salad) value(salad).must_be :valid? end + end diff --git a/test/models/review_test.rb b/test/models/review_test.rb index d3a0950dd7..01e0b5da79 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -1,7 +1,7 @@ require "test_helper" describe Review do - let(:review) { Review.new rating: 4, text_review: "very fresh!" } + let(:review) { Review.create rating: 4, text_review: "very fresh!" } it "must be valid" do product = Product.create(name: "green apple", price: 2) From 7f7fdf351c7f81b0a4208a092966ab6fe20b4a80 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Sat, 21 Apr 2018 15:18:00 -0700 Subject: [PATCH 086/320] adds logic to update product db after adding to cart --- app/controllers/sessions_controller.rb | 6 +++++- app/views/layouts/application.html.erb | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index f40657b438..23479c6bc6 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -15,6 +15,9 @@ def create @product = Product.find_by(id: product_id) if @product.quantity >= quantity.to_i # decrement product.quantity in db + + new_quantity = @product.quantity - quantity.to_i + @product.update(quantity: new_quantity) # add to sessions # binding.pry # session[:order] @@ -22,7 +25,8 @@ def create redirect_to order_path else # flash message that the quantity is too high - flash[:error] = "The quantity entered is too high" + flash.now[:alert] = "The quantity entered is too high" + # binding.pry render 'products/show' end # binding.pry diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 4f76c5ab4d..7f0c5ff330 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -30,16 +30,18 @@
+
-
- <% flash.each do |name, message| %> -

- <%= message %> -

- <% end %> -
+
+ <% flash.each do |name, message| %> +

+ <%= message %> +

+ <% end %> +
- <%= yield %> + <%= yield %> +
From 5e5fd8831257b157186e02b82a99544b6d6634b0 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Sat, 21 Apr 2018 15:22:39 -0700 Subject: [PATCH 087/320] added a flash notification on the app main view page, create method for review fails for products that do exist in the db --- app/controllers/reviews_controller.rb | 6 +- app/views/layouts/application.html.erb | 80 ++++++++++++++++---------- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 9f1f40366c..b1fec9b4f1 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -6,7 +6,7 @@ def new def create @review = Review.new(review_params) - @product = Product.find_by(review_params :product_id) + @product = Product.find_by(review_params[:product_id]) if @review.save flash[:status] = :success flash[:result_text] = "Successfully reviewed #{@product.name}" @@ -14,7 +14,7 @@ def create else flash[:status] = :failure flash[:result_text] = "Could not review #{@product.name}" - flash[:messages] = @work.errors.messages + flash[:messages] = @review.errors.messages render :new, status: :bad_request end end @@ -24,7 +24,7 @@ def index private def review_params - params.require(:review).permit(:rating, :text_review, :product_id) + params.require(:review).permit(:product_id, :text_review, :rating) end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index fd90897261..5b4ed8b5dd 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,37 +1,55 @@ - - - - - <%= content_for?(:title) ? yield(:title) : "FruEtsy" %> - - <%= stylesheet_link_tag "application" %> - <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> - <%= csrf_meta_tags %> - - - - -
-

Welcome to FruEtsy

-

for all your syrup-less fruit salad needs

- -
- - <%= yield %> + <%= yield %> - + From 0e455106ecb780932817487ed24ca70181402dbd Mon Sep 17 00:00:00 2001 From: Abiaina Date: Sat, 21 Apr 2018 15:38:19 -0700 Subject: [PATCH 088/320] can review product, flash notifies success, redirect is wrong --- app/controllers/reviews_controller.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index b1fec9b4f1..3dd0817e29 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -6,7 +6,10 @@ def new def create @review = Review.new(review_params) - @product = Product.find_by(review_params[:product_id]) + + @product = Product.find(params[:product_id].to_i) + + @review.product_id = @product.id if @review.save flash[:status] = :success flash[:result_text] = "Successfully reviewed #{@product.name}" @@ -24,7 +27,7 @@ def index private def review_params - params.require(:review).permit(:product_id, :text_review, :rating) + params.require(:review).permit(:rating, :text_review) end end From 1ba65e05568b0870ed621a9166540553f6675878 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Sat, 21 Apr 2018 16:04:56 -0700 Subject: [PATCH 089/320] adds products stored in session to table on order show page. --- app/controllers/sessions_controller.rb | 14 ++++++++------ app/helpers/sessions_helper.rb | 3 +++ app/views/products/index.html.erb | 1 + app/views/sessions/index.html.erb | 26 ++++++++++++++++++++++++-- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 23479c6bc6..c38718c334 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -13,24 +13,26 @@ def create quantity = params[:quantity] product_id = params[:product_id] @product = Product.find_by(id: product_id) + if @product.quantity >= quantity.to_i # decrement product.quantity in db - new_quantity = @product.quantity - quantity.to_i @product.update(quantity: new_quantity) # add to sessions - # binding.pry - # session[:order] + # check if session[:order] is empty + if session[:order].nil? + session[:order] = { @product.id => quantity.to_i } + else + session[:order].merge!(@product.id => quantity.to_i) + # session[:order][@product.id] = quantity.to_i + end # redirect redirect_to order_path else # flash message that the quantity is too high flash.now[:alert] = "The quantity entered is too high" - # binding.pry render 'products/show' end - # binding.pry - # render product_path() end def edit diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 309f8b2eb3..6e8b1f0799 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -1,2 +1,5 @@ module SessionsHelper + def calculate_total + + end end diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 5d9d2aa5d5..89eec80f2b 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,3 +1,4 @@ + <% if @user.nil? %>

FruEtsy Goodies

<% products = @products.sample(12) %> diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 62cbf379e3..e1ced5d286 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,2 +1,24 @@ -

Sessions#index

-

Find me in app/views/sessions/index.html.erb

+

Current Order

+ + + + + + + + + + + <% session[:order].each do |key, val| %> + <% product = Product.find_by(id: key.to_i) %> + + + + + + + <% end %> + +
ProductDescriptionPriceQuantity
<%= product.name %><%= product.description %>$<%= product.price %><%= val %>
+ +

Total: <%= calculate_total %>

From 2f363622b731d9e79012504375c88cd912322716 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Sat, 21 Apr 2018 16:07:53 -0700 Subject: [PATCH 090/320] adds subtotal to order page --- app/helpers/sessions_helper.rb | 8 +++++++- app/views/sessions/index.html.erb | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 6e8b1f0799..134ed199f4 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -1,5 +1,11 @@ module SessionsHelper def calculate_total - + total = 0 + session[:order].each do |key, val| + product = Product.find_by(id: key.to_i) + subtotal = product.price * val + total += subtotal + end + return total end end diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index e1ced5d286..1ea0fd45f0 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -21,4 +21,4 @@ -

Total: <%= calculate_total %>

+

Total: $<%= calculate_total %>

From 020faef07bb7f32e0be024f57c85ab6380ecf48c Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Sat, 21 Apr 2018 17:02:24 -0700 Subject: [PATCH 091/320] user model tests passing --- test/fixtures/orders.yml | 82 +++++++++++++++++++++--- test/fixtures/products.yml | 12 ++-- test/models/review_test.rb | 17 ++--- test/models/user_test.rb | 126 ++++++++++++++++++------------------- 4 files changed, 147 insertions(+), 90 deletions(-) diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml index 09319ed236..9ec5809c47 100644 --- a/test/fixtures/orders.yml +++ b/test/fixtures/orders.yml @@ -1,25 +1,91 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html cart1: - user_id: beyonce + user: beyonce status: shipped + name: bey + card_number: 1234123412341234 + email: bey@github.com + street: malden + city: seattle + state: wa + zip: 12345 + date_year: 18 + date_month: 5 + date_day: 3 + cvv: 123 cart2: - user_id: beyonce + user: beyonce status: shipped + name: bey + card_number: 1234123412341234 + email: bey@github.com + street: malden + city: seattle + state: wa + zip: 12345 + date_year: 18 + date_month: 5 + date_day: 3 + cvv: 123 cart3: - user_id: hermonie + user: hermonie status: paid + name: bey + card_number: 1234123412341234 + email: bey@github.com + street: malden + city: seattle + state: wa + zip: 12345 + date_year: 18 + date_month: 5 + date_day: 3 + cvv: 123 cart4: - user_id: mcgonagall + user: mcgonagall status: paid + name: beyyy + card_number: 1234123412341234 + email: bey@github.com + street: malden + city: seattle + state: wa + zip: 12345 + date_year: 18 + date_month: 5 + date_day: 3 + cvv: 123 -cart4: - user_id: snape +cart5: + user: snape status: paid + name: bey + card_number: 1234123412341234 + email: bey@github.com + street: malden + city: seattle + state: wa + zip: 12345 + date_year: 18 + date_month: 5 + date_day: 3 + cvv: 123 -cart4: - user_id: snape +cart6: + user: snape status: paid + name: bey + card_number: 1234123412341234 + email: bey@github.com + street: malden + city: seattle + state: wa + zip: 12345 + date_year: 18 + date_month: 5 + date_day: 3 + cvv: 123 diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml index 60bb263cdd..5e464c353d 100644 --- a/test/fixtures/products.yml +++ b/test/fixtures/products.yml @@ -3,35 +3,35 @@ cherries: name: cherries price: 3.0 description: 1kg ranier cherries - user_id: beyonce + user: beyonce watermelon: name: watermelon price: 4.0 description: seedless - user_id: hermonie + user: hermonie orange: name: orange price: 1.0 description: single orange - user_id: hermonie + user: hermonie blood_orange: name: blood orange price: 1.0 description: single blood orange with magical properties - user_id: mcgonagall + user: mcgonagall gillyweed: name: gillyweed price: 1.0 description: not a fruit, allows for increased aquaability - user_id: snape + user: beyonce veritberry: name: verit berry price: 1.0 description: bitter berry used for veritaserum - user_id: snape + user: snape diff --git a/test/models/review_test.rb b/test/models/review_test.rb index 01e0b5da79..50ba66373a 100644 --- a/test/models/review_test.rb +++ b/test/models/review_test.rb @@ -4,36 +4,31 @@ let(:review) { Review.create rating: 4, text_review: "very fresh!" } it "must be valid" do - product = Product.create(name: "green apple", price: 2) - # why is this not updating into the review product_id? - review.product_id = product.id - review.save + review = reviews(:rating1) value(review).must_be :valid? end it "is invalid when missing a rating" do review.rating = nil - review.save review.valid?.must_equal false end it "is invalid when a rating greater than 5" do review.rating = 6 - review.save review.valid?.must_equal false end it "is invalid when a rating less than 1" do review.rating = 0 - review.save review.valid?.must_equal false end + it "must have a product" do + review.valid?.must_equal false + review.product = products(:cherries) - describe "relations" do - it "belongs to products" do - - end + review.valid?.must_equal true end + end diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 450316f7ff..e042864e11 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -1,87 +1,83 @@ require "test_helper" describe User do - let(:user) { User.new name: "Bey", email: "bey@yonce.com", uid: 2231, provider: "yonce"} + let(:user) { User.create name: "Bey", email: "bey@yonce.com", uid: 2231, provider: "yonce"} it "must be valid" do - user.save + value(user).must_be :valid? end it "is invalid when missing a name" do user.name = nil - user.save + user.valid?.must_equal false end it "is invalid when given a non-unique name" do user.name = "Bey" - user.save + dup_user_name = User.new dup_user_name.name = "Bey" dup_user_name.save dup_user_name.valid?.must_equal false end - # describe "relations" do - # describe "order" do - # it "can have an order" do - # user1 = users(:hermonie) - # user1.save - # user1.orders.count.must_equal 1 - # end - # - # it "can have multiple orders" do - # user1 = users(:beyonce) - # user1.save - # user1.orders.count.must_equal 2 - # end - # - # it "can have no orders" do - # user1 = users(:ron) - # user1.save - # user1.orders.count.must_equal 0 - # end - # end - # - # describe "products" do - # it "can have a product" do - # user1 = users(:beyonce) - # user1.save - # user1.products.count.must_equal 1 - # end - # - # it "can have multiple products" do - # user1 = users(:hermonie) - # user1.save - # user1.products.count.must_equal 2 - # end - # - # it "can have no products" do - # user1 = users(:ron) - # user1.save - # user1.products.count.must_equal 0 - # end - # end - # - # describe "order and products" do - # it "can have no products and no orders" do - # user = users(:ron) - # user.orders.count.must_equal 0 - # user.products.count.must_equal 0 - # end - # - # it "can have multiple products and orders" do - # user = users :snape - # user.orders.count.must_equal 2 - # user.products.count.must_equal 2 - # end - # - # it "can have one products and one orders" do - # user = users :mcgonagall - # user.orders.count.must_equal 1 - # user.products.count.must_equal 1 - # end - # end - # end + describe "relations" do + describe "order" do + it "can have an order" do + user1 = users(:hermonie) + user1.orders.count.must_equal 1 + end + + it "can have multiple orders" do + user1 = users(:beyonce) + user1.orders.count.must_equal 2 + end + + it "can have no orders" do + user1 = users(:ron) + user1.orders.count.must_equal 0 + end + end + + describe "products" do + it "can have a product" do + user1 = users(:mcgonagall) + user1.products.count.must_equal 1 + end + + it "can have multiple products" do + user1 = users(:hermonie) + user1.products.count.must_equal 2 + end + + it "can have no products" do + user1 = users(:ron) + user1.products.count.must_equal 0 + end + end + + describe "order and products" do + it "can have no products and no orders" do + user = users(:ron) + user.orders.count.must_equal 0 + user.products.count.must_equal 0 + end + + it "can have multiple products and orders" do + user = users(:beyonce) + + user.orders.count.must_equal 2 + + user.products.count.must_equal 2 + end + + it "can have one products and one orders" do + user = users(:mcgonagall) + user.orders.count.must_equal 1 + user.products.count.must_equal 1 + end + end + end end From efd75bf473f577db328e9e73317ec67751db8696 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Sat, 21 Apr 2018 17:11:03 -0700 Subject: [PATCH 092/320] sucessful review redirects to product detail page, all reviews and ratings are listed --- app/controllers/reviews_controller.rb | 5 ++++- app/views/products/show.html.erb | 13 ++++++++----- app/views/reviews/new.html.erb | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index 3dd0817e29..e18455c152 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -1,6 +1,9 @@ class ReviewsController < ApplicationController def new + @product = Product.find(params[:product_id].to_i) + + # why does this only work with @product is defined first? @review = Review.new end @@ -13,7 +16,7 @@ def create if @review.save flash[:status] = :success flash[:result_text] = "Successfully reviewed #{@product.name}" - redirect_to new_product_review_path(@product.id) + redirect_to product_path(@product.id) else flash[:status] = :failure flash[:result_text] = "Could not review #{@product.name}" diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index aa6a1badf2..677f7da04c 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -4,17 +4,20 @@
-fruit! -<%= @product.price %> -<%= @product.quantity %> -<%= @product.description %> + fruit! + <%= @product.price %> + <%= @product.quantity %> + <%= @product.description %>

Reviews

    <% @product.reviews.each do |review| %> -
  • <%= review.text_review %>
  • +
  • Review: <%= review.text_review %> +
  • +
  • Rating: <%= review.rating %> +
  • <% end %>
diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb index 6f9b1ca0ad..80161bbdf4 100644 --- a/app/views/reviews/new.html.erb +++ b/app/views/reviews/new.html.erb @@ -1,2 +1,2 @@ -

Add Review

+

Review <%= @product.name %>

<%= render partial: "form" %> From 80a6abdbb107129971783d47ac0fe96a40dc326b Mon Sep 17 00:00:00 2001 From: Abiaina Date: Sat, 21 Apr 2018 17:48:45 -0700 Subject: [PATCH 093/320] users can review products, products reviews are listed on product detail page --- app/models/review.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/models/review.rb b/app/models/review.rb index f6a2b99616..453fff7a51 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -8,6 +8,15 @@ class Review < ApplicationRecord inclusion: { in: 1..5} } + # validate that the product --> product.user_id --> doesn't match the login session id of user + # def no_self_reviews + # product = Product.find(session[:product_id]) + # user = User.find(product.user_id) + # + # if user.id == sessions[:user_id] + # + # end + # should this be in product or in reviews model? # def self.average_rating(reviews) # total = 0 From e02e7c4e896cb7ce46f9797d9edfbd43ccb5af72 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Sat, 21 Apr 2018 17:51:37 -0700 Subject: [PATCH 094/320] order model tests passing --- app/models/order.rb | 4 ++ test/fixtures/order_items.yml | 12 ++-- test/models/cart_test.rb | 112 +++++++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 7 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index 051a5124fb..01457b3d41 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -2,8 +2,12 @@ class Order < ApplicationRecord has_many :order_items belongs_to :user + validates :order_items, length: { minimum: 1 } + validates :name, :card_number, :email, :street, :city, :state, :zip, :date_year, :date_month, :date_day, :cvv, presence: true + validates :name, length: { minimum: 1 } + validates :card_number, :zip, :date_year, :date_day, :date_month, :cvv, numericality: { only_integer: true } validates :card_number, length: { is: 16 } diff --git a/test/fixtures/order_items.yml b/test/fixtures/order_items.yml index 4ebc678ba0..e3923c2b29 100644 --- a/test/fixtures/order_items.yml +++ b/test/fixtures/order_items.yml @@ -2,19 +2,19 @@ # I am unsure of what to call the status fruit_salad: - order_id: cart1 - product_id: cherry + order: cart1 + product: cherry quantity: 3 status: paid watermelon_salad: - order_id: cart2 - product_id: watermelon + order: cart2 + product: watermelon quantity: 2 status: paid citris_salad: - order_id: cart2 - product_id: orange + order: cart2 + product: orange quantity: 2 status: paid diff --git a/test/models/cart_test.rb b/test/models/cart_test.rb index a1de67f4db..0d6156327a 100644 --- a/test/models/cart_test.rb +++ b/test/models/cart_test.rb @@ -1,9 +1,119 @@ require "test_helper" describe Order do - + let(:order) { orders(:cart2)} it "must be valid" do order.valid?.must_equal true end + + it "must have a name" do + order.name = nil + order.valid?.must_equal false + end + + it "must have a name with a length > 0" do + order.name = "" + order.valid?.must_equal false + end + + it "must have a card number" do + order.card_number = nil + order.valid?.must_equal false + end + + it "must have a integer card number of length 16" do + order.card_number = "aa fe" + order.valid?.must_equal false + + order.card_number = 12354552 + order.valid?.must_equal false + + end + + it "must have an integer zip" do + order.zip = "g vukj" + order.valid?.must_equal false + end + + it "must have an integer date day" do + order.date_day = 5.8 + order.valid?.must_equal false + order.date_day = "ahfkj" + order.valid?.must_equal false + + end + + it "must have an integer date month" do + order.date_month = 5.8 + order.valid?.must_equal false + order.date_month = "ahfkj" + order.valid?.must_equal false + end + + it "must have an integer date year" do + order.date_year = 5.8 + order.valid?.must_equal false + order.date_year = "ahfkj" + order.valid?.must_equal false + end + + it "must have an integer cvv" do + order.cvv = "2348" + order.valid?.must_equal false + order.cvv = 2.67 + order.valid?.must_equal false + end + + it "must have a cvv with length 3" do + order.cvv = 3456 + order.valid?.must_equal false + end + + it "must have a zip with length 5" do + order.zip = 123 + order.valid?.must_equal false + end + + it "must have an email" do + order.email = nil + order.valid?.must_equal false + end + + it "must have proper email format" do + order.email = "aiesfn@" + order.valid?.must_equal false + order.email = 23485 + order.valid?.must_equal false + end + + it "must have a street" do + order.street = nil + order.valid?.must_equal false + end + + it "must have a city" do + order.city = nil + order.valid?.must_equal false + end + + it "must have a state" do + order.state = nil + order.valid?.must_equal false + end + + it "must have at least one order item" do + order.order_items = [] + order.valid?.must_equal false + end + + it "can have many order items" do + + order.order_items.count.must_equal 2 + end + + it "must have a user" do + order.user = nil + order.valid?.must_equal false + end end From ad5e65b96ef288d94baf338422306556a29de79d Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Sat, 21 Apr 2018 18:09:11 -0700 Subject: [PATCH 095/320] finishes model testing except order items --- app/assets/images/watermelon.jpg | Bin 0 -> 170362 bytes app/assets/stylesheets/application.css | 1 + 2 files changed, 1 insertion(+) create mode 100644 app/assets/images/watermelon.jpg diff --git a/app/assets/images/watermelon.jpg b/app/assets/images/watermelon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..76018ad7542006d8f1ba1a967451634be36fb50b GIT binary patch literal 170362 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

BinWHPmS%SE$Tuig) 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ï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 z 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

e?_H5jjSE4|2(20w43f%XuUX0Y%Arw8=Vk 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 Date: Sat, 21 Apr 2018 19:22:13 -0700 Subject: [PATCH 096/320] more attempts to browse by category, cannot add products to categories --- app/controllers/categories_controller.rb | 2 +- app/controllers/normalize.css | 341 +++++++++++++++++++++++ app/views/categories/show.html.erb | 10 +- 3 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 app/controllers/normalize.css diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 75b4858282..3e1f2616b2 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -4,7 +4,7 @@ def index end def show - + @category = Category.find_by(id: params[:id]) end def new diff --git a/app/controllers/normalize.css b/app/controllers/normalize.css new file mode 100644 index 0000000000..47b010e477 --- /dev/null +++ b/app/controllers/normalize.css @@ -0,0 +1,341 @@ +/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 60e06c3d7b..d894ca1009 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -1,2 +1,8 @@ -

Categories#show

-

Find me in app/views/categories/show.html.erb

+

<%= @category.name %>

+
    + <% @category.products.each do |product| %> +
  • + <%= link_to product.title, product_path(product.id) %> +
  • + <% end %> +
From 906ec17ecf58f23c8707766f402ea5d28c827537 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Sat, 21 Apr 2018 19:26:16 -0700 Subject: [PATCH 097/320] completes update functionality for cart --- app/controllers/sessions_controller.rb | 34 +++++++++++++++- app/helpers/sessions_helper.rb | 14 ++++--- app/views/products/show.html.erb | 2 +- app/views/sessions/index.html.erb | 54 +++++++++++++++----------- config/routes.rb | 6 ++- 5 files changed, 78 insertions(+), 32 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index c38718c334..0161e5706b 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -36,11 +36,41 @@ def create end def edit + end def update + product_id = params[:id].to_i + old_quantity = session[:order][product_id.to_s] + new_quantity = params[:quantity].to_i + product = Product.find_by(id: product_id) + if new_quantity == 0 + update_quantity = product.quantity + old_quantity + product.update(quantity: update_quantity) + session[:order].delete(product_id.to_s) + flash[:success] = "Item removed from Order" + redirect_to order_path + elsif new_quantity < 0 + flash.now[:alert] = "Invalid number" + render :index + elsif (product.quantity - new_quantity) < 0 + flash.now[:alert] = "Not enough in stock" + render :index + else + diff = old_quantity - new_quantity + update_quantity = product.quantity + diff + product.update(quantity: update_quantity) + session[:order][product_id.to_s] = new_quantity + flash[:success] = "Item quantity updated" + redirect_to order_path + end end - def destroy - end + # def destroy + # product_id = params[:id] + # session[:order].delete(product_id) + # binding.pry + # flash.now[:success] = "Item Removed from Order" + # render :index + # end end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 134ed199f4..ddc8c97df8 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -1,11 +1,15 @@ module SessionsHelper def calculate_total total = 0 - session[:order].each do |key, val| - product = Product.find_by(id: key.to_i) - subtotal = product.price * val - total += subtotal + if session[:order].nil? + return total + else + session[:order].each do |key, val| + product = Product.find_by(id: key.to_i) + subtotal = product.price * val + total += subtotal + end + return total end - return total end end diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 0e375b475b..201b29c6a9 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -12,7 +12,7 @@
- <%= form_with url: order_path do |form| %> + <%= form_with url: add_to_order_path do |form| %> <%= form.label 'quantity' %> <%= form.number_field 'quantity' %> <%= form.hidden_field :product_id, value: @product.id %> diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 1ea0fd45f0..c110964148 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,24 +1,34 @@

Current Order

- - - - - - - - - - - <% session[:order].each do |key, val| %> - <% product = Product.find_by(id: key.to_i) %> - - - - - - - <% end %> - -
ProductDescriptionPriceQuantity
<%= product.name %><%= product.description %>$<%= product.price %><%= val %>
- +<% if session[:order].nil? || session[:order] == {} %> +

No Items in the Order

+<% else %> + + + + + + + + + + + + + <% session[:order].each do |key, val| %> + <% @product = Product.find_by(id: key.to_i) %> + <% params[:id] = key %> + + + + + <%= form_tag('/order', method: :patch) do %> + + <%= hidden_field_tag 'id', "#{key}" %> + + <% end %> + + <% end %> + +
ProductDescriptionPriceQuantity
<%= @product.name %><%= @product.description %>$<%= @product.price %><%= number_field_tag 'quantity', "#{val}" %><%= button_tag "Update" %>
+<% end %>

Total: $<%= calculate_total %>

diff --git a/config/routes.rb b/config/routes.rb index 255f199996..ae0378ae9c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,8 +11,10 @@ # resources :sessions - get '/order', to: 'sessions#index', as: 'order' - post '/order', to: 'sessions#create', as: 'add_to_order' + get '/order' , to: 'sessions#index', as: 'order' + post '/order' , to: 'sessions#create', as: 'add_to_order' + patch '/order' , to: 'sessions#update', as: 'update_order_item' + delete '/order' , to: 'sessions#destroy', as: 'delete_order_item' resources :products From e22d6d885737805d348f5fb3086ed9a1a395d936 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Sat, 21 Apr 2018 19:28:48 -0700 Subject: [PATCH 098/320] adds checkout button --- app/views/sessions/index.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index c110964148..c642a88e94 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -30,5 +30,6 @@ <% end %> +

Total: $<%= calculate_total %>

+ <%= link_to "Checkout" %> <% end %> -

Total: $<%= calculate_total %>

From 9df2bed2f52d8b98f564f893a5e78210d2f3fcfc Mon Sep 17 00:00:00 2001 From: Phoebe Date: Sat, 21 Apr 2018 19:32:02 -0700 Subject: [PATCH 099/320] adds order button to nav --- app/views/layouts/application.html.erb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 7f0c5ff330..4fb5abbad1 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -19,11 +19,12 @@ From 6cdfef8c9783c86bd4b8087302268cb6d20b063a Mon Sep 17 00:00:00 2001 From: marikoja Date: Sun, 22 Apr 2018 00:30:31 -0700 Subject: [PATCH 102/320] browsing refactors --- app/assets/stylesheets/application.css | 4 +++ app/views/layouts/application.html.erb | 36 ++++++++++++++------------ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 72b95edd74..e40487eb31 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -36,3 +36,7 @@ nav .button.right { float: right; margin: 1em; } + +ul li { + list-style-type: none; +} diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a6e6658f55..dcac5e24e8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -26,25 +26,27 @@ + + +
-
- <% flash.each do |name, message| %> -

- <%= message %> -

- <% end %> -
+
+ <% flash.each do |name, message| %> +

+ <%= message %> +

+ <% end %> +
- <%= yield %> -
- + <%= yield %> + + From 7661bfa003fce83670c22c151e048e60450991e6 Mon Sep 17 00:00:00 2001 From: marikoja Date: Sun, 22 Apr 2018 13:05:23 -0700 Subject: [PATCH 114/320] show logic --- app/views/users/index.html.erb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 0a8a7572d6..7def25391a 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,8 +1,10 @@

All Users

    <% @users.each do |user| %> -
  • - <%= link_to user.name, user_products_path(user.id) %> -
  • + <% if !user.uid.nil? %> +
  • + <%= link_to user.name, user_products_path(user.id) %> +
  • + <% end %> <% end %>
From 13df5756faaf75b498ff81d8be350f845f23f240 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Sun, 22 Apr 2018 13:06:17 -0700 Subject: [PATCH 115/320] gets rid of duplicated code --- app/views/products/show.html.erb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 973ba13678..571152b0e4 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -13,13 +13,6 @@ Description: <%= @product.description %>
-
- fruit! - <%= @product.price %> - <%= @product.quantity %> - <%= @product.description %> -
-

Reviews

    From 14664efae843a03f09e7862c09221b250cf8b170 Mon Sep 17 00:00:00 2001 From: marikoja Date: Sun, 22 Apr 2018 13:11:57 -0700 Subject: [PATCH 116/320] merge conflicts --- app/views/layouts/application.html.erb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ca95d561ff..1db8cd6ee5 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -44,13 +44,11 @@
  • <%= link_to "Merchants", users_path %>
  • - -<<<<<<< HEAD
    -======= + <% if flash[:result_text] or flash[:messages] %>
    @@ -68,8 +66,6 @@ <% end %> ->>>>>>> f090fab2ade707d623ba396ca74d8d37fba8c32a -
    <% flash.each do |name, message| %>

    @@ -78,7 +74,6 @@ <% end %>

    - <%= yield %>
    From c3b1958ceb498335ae2638d10b247e43f7d4b955 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Sun, 22 Apr 2018 13:13:24 -0700 Subject: [PATCH 117/320] form for adding new product --- app/controllers/products_controller.rb | 5 +++-- app/views/layouts/application.html.erb | 6 ++---- app/views/products/_form.html.erb | 7 ++++--- app/views/products/new.html.erb | 3 +-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 4a1b37c698..0371761ee9 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -10,12 +10,13 @@ def index def new @product = Product.new - @product.user = User.find_by(id: params[:user_id]) + @product.user = User.find_by(uid: session[:uid]) end def create @product = Product.new(product_params) - @product.user = User.find_by(id: params[:user_id]) + @product.user = User.find_by(uid: session[:uid]) + @action = new_user_product_path(@product.user.id) if @product.save flash[:success] = "New product added" redirect_to root_path diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 139577ad01..284dbc77d7 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -19,11 +19,9 @@
    diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index a14e0d91b6..a6cf4edb63 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1,2 +1 @@ -

    Products#new

    -

    Find me in app/views/products/new.html.erb

    +<%= render partial: "productform" %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 571152b0e4..ed585953ea 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -6,7 +6,7 @@
    fruit!
    - Price: <%= @product.price %> + Price: $<%= @product.price.round(2) %>
    Quantity: <%= @product.quantity %>
    From 0f1e0bf034b4eec29d526c63608beb20c344efc2 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Sun, 22 Apr 2018 15:18:20 -0700 Subject: [PATCH 120/320] merchant show page --- app/views/layouts/application.html.erb | 2 ++ app/views/users/show.html.erb | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 4bf0cceb27..0be3aea434 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -21,6 +21,8 @@ <% if session[:user_id] %> <%= link_to "Logout", logout_path, method: :delete, class: "button right" %> + <%= link_to "My Profile", user_path(session[:user_id]), class: "button right" %> + <%= link_to "Add Product", new_user_product_path(session[:user_id]), class: "button right" %> <% else %> <%= link_to "user Login", github_login_path, class: "button" %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index ee79445b0d..16106f9e8c 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,4 +1,10 @@ -

    User Info

    -

    Name: <%= @user.name %>

    -

    Email: <%= @user.email %>

    -

    <%= link_to "Edit Profile", edit_user_path(@user.id) %>

    +

    Merchant Profile

    + +
    + Name: <%= @user.name %> + Email: <%= @user.email %> + <%= link_to "Edit Profile", edit_user_path(@user.id) %> +
    + +
    + From 20d920f9648cb90f778e5a962cf16bd2e80e43fe Mon Sep 17 00:00:00 2001 From: marikoja Date: Sun, 22 Apr 2018 15:43:53 -0700 Subject: [PATCH 121/320] updates seed files --- app/models/order.rb | 2 -- app/views/users/index.html.erb | 2 +- db/MerchantSeed.csv | 3 ++- db/OrdersSeed.csv | 14 ++++++------ db/ProductSeed.csv | 40 +++++++++++++++++----------------- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/app/models/order.rb b/app/models/order.rb index 01457b3d41..110effcc8e 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -2,8 +2,6 @@ class Order < ApplicationRecord has_many :order_items belongs_to :user - validates :order_items, length: { minimum: 1 } - validates :name, :card_number, :email, :street, :city, :state, :zip, :date_year, :date_month, :date_day, :cvv, presence: true validates :name, length: { minimum: 1 } diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 7def25391a..1c820ced63 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,4 +1,4 @@ -

    All Users

    +

    All Merchants

      <% @users.each do |user| %> <% if !user.uid.nil? %> diff --git a/db/MerchantSeed.csv b/db/MerchantSeed.csv index 351017b9cc..4ede3bdd4a 100644 --- a/db/MerchantSeed.csv +++ b/db/MerchantSeed.csv @@ -1,5 +1,6 @@ name,email,UID,provider +Guest,guest@gmail.com Joe Schmo,Joe@Schmo.com,234134,github Margo Tenenbaum,margot@tenenbaum.com,34363838,github Tabitha Baker,tabitha@baker.com,24354325,github -Lucy Sanders,lucy@sanders.com,2635467,github \ No newline at end of file +Lucy Sanders,lucy@sanders.com,2635467,github diff --git a/db/OrdersSeed.csv b/db/OrdersSeed.csv index 3d99424094..0b40881406 100644 --- a/db/OrdersSeed.csv +++ b/db/OrdersSeed.csv @@ -1,8 +1,8 @@ user_id,name,card_number,email,street,city,state,zip,date_year,date_month,date_day,cvv,status -1,"Ben",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"pending" -2,"Tim",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"paid" -3,"Tyler",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"complete" -1,"Ben",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"paid" -2,"Tim",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"complete" -3,"Tyler",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"pending" -3,"Tyler",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"complete" +2,"Ben",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"pending" +3,"Tim",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"paid" +4,"Tyler",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"complete" +2,"Ben",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"paid" +3,"Tim",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"complete" +4,"Tyler",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"pending" +4,"Tyler",8888333344447777,"person@email.com","1500 West Easy St.","Seattle","WA",89123,2025,4,20,314,"complete" diff --git a/db/ProductSeed.csv b/db/ProductSeed.csv index c7bdfba1c8..3d3788af2f 100644 --- a/db/ProductSeed.csv +++ b/db/ProductSeed.csv @@ -1,21 +1,21 @@ Product,price,description,user_id,quantity -Honey Crisp Apple,1.00,"Their creamy white flesh is exceptionally crisp and aromatic. A balanced content of sugar and acid gives Honeycrisp apples a pleasant sweet-tart flavor that varies in strength depending upon the maturity of the apple.",1,30 -Banana,0.25,"Bananas are rich in potassium, riboflavin, niacin, and dietary fibre. They also have high energy value and are really good for growing children and athletes. They are also excellent for low-salt, low-fat, and cholesterol-free diets. Hundreds of different varieties of banana flourish in the tropics, from sweet yellow pygmy to large fibrous plantains and green bananas, which can only be used for cooking.",1,50 -Rainier Cherries,2.99,Sweet and juicy,1,30 -Green Grapes,2.00,"A great energy source because of their natural fruit sugar content",1,300 -Grapefruit,1.00,"One of the largest citrus fruit, grapefruits are a cross between the pomelo and the shaddock. High in vitamin C, grapefruits are best eaten raw, a traditional breakfast fruit. The best way to eat is to cut them in half and scoop out the flesh with a spoon.",1,10 -Kumquat,0.50,"The name means ""golden orange"" in Chinese. Kumquats are often preserved in sweet syrup and used for marmalade and garnishes, but fresh ones are delicious in fruit salads or for eating just as they are.",1,80 -Lemon,0.25,"Rarely eaten on its own, lemons are an indispensable ingredient in the kitchen. Lemon juice can be used instead of vinegar in sauces, for seasoning in vinaigrette and as instant dressing for fish and shellfish. The best way to store lemon is in the vegetable crisper in the fridge you can put lemons in fruit bowl for a shorter, check them often - if one starts to spoil, the rest will quickly follow.",1,15 -Pineapple,3.00,"Derived from the Spanish word 'pina' meaning pine cone. Pineapples have a juicy, sweet-but sometimes slightly tart-fragrant flavour. They are best eaten fresh, serve pineapple flesh in slices, wedges or chunks. It is also available in cans, dried and glace. A good source of vitamin C.",1,14 -Plums,1.25,"Plums contain more antioxidant than any other fruit. Plums are delicate so make sure that the one you buy are unblemished, and they should be plump and firm. The small sugar plum is dried to make prunes. Delicious stewed, plums are also ideal for making chutneys.",1,16 -Start Apple,1.15,"The star apple fruits are green to purple with a smooth skin. When sliced horizontally the flesh is translucent white with the seeds forming a star shape. It is best eaten ripe, scooped straight from the skin. It is ripe when soft and should be eaten immediately, but it is still alright to refrigerate for a few days.",1,45 -Strawberry,2.78,"A unique fruit, the seeds grow around the outside of the fruit rather than inside it. Comes in many different sizes, colours and shapes, ranging from cone-like, to oval, or heart-shaped. Best to eat on their own or with natural yoghurt. Use strawberries in desserts, fruit salads, preserves, or in milkshakes.",2,26 -Watermelon,5.00,"The high water content of watermelons means that they are low in calories. They contain some vitamins B and C. Watermelon is excellent juiced, chopped up into a fruit salad, or just eaten in chunky slices.",2,43 -Tamarillo,1.65,"these are related to tomatoes and sometimes called ""tree tomatoes."" They are the size of an egg tomato, with dark red skin. The fruit has a strong, sweet flavour that makes it suitable for both sweet or savoury dishes. It can also be used in jams, chutneys, and sorbets.",2,12 -Rambutan,3.40,"The rambutan fruit grows in clusters, with a deep crimson outer skin. The flesh is translucent, and the pale seed is edible when young. Related to lychees and are sometimes known as ""hairy lychees"".(about 5cm / 2inches in diameter) and look quite different but have a similar texture. They can be added to salads, made into jams or jellies, but they are best eaten on their own.",2,3 -Peach,2.25,"Or pawpaw, a large tropical fruit whose ripe flesh can be juicy, creamy, orange-red, or yellow. In the centre is a mass of large peppery black seeds, which are edible and sometimes crushed and used as a spice. Ripe papaya is eaten as a breakfast fruit or as a dessert. It can also be pureed for ice cream, sorbets and iced drinks.",2,9 -Fig,0.50,"Figs are oval or pear-shaped and can be eaten fresh or dried. They are well known for their laxative and digestive properties. Their high, natural sugar content makes them the sweetest of all fruits. The flavour varies, depending on where they were grown and how ripe they are.",3,24 -Lime,0.25,"Limes are only green because they are picked unripe but if left to ripen they turn yellow. Limes can be used like lemons but as juice, it is more acidic, so usually less is needed. To make the juice flow more, you can microwave the limes for 2-3 seconds before squeezing. Mostly used in drinks (lime cordials) and cooking.",3,65 -Passionfruit,3.00,"The most popular variety is the purple passionfruit about the size of a chicken egg. It has a highly fragrant, sweet, but slightly tart, tasting fruit that can be spooned out and eaten fresh or added to fruit salad, pavlova, and it makes a very popular drink, ice cream and sorbets and a flavouring for all kinds of desserts.",3,43 -Nectarine,1.25,"The nectarine flesh is rich, sweet and juicy and is well suited for eating fresh and for using in ice cream, pies and fruit salads. Colour ranges from silvery white or yellowy orange to pinkish red. The white-fleshed varieties are considered the best and usually the most expensive. Nectarines are often described as a cross between a peach and a plum, but nectarines are actually a variety of smooth-skinned peach.",3,2 -Mangosteen,1.15,"Contrary to its name, the mangosteen doesn't resemble or taste like the mango. It resemble an apple, having a short stem and four thick leaf-like bracts which form a rosette encasing the brownish-purple fruit.",3,7 +Honey Crisp Apple,1.00,"Their creamy white flesh is exceptionally crisp and aromatic. A balanced content of sugar and acid gives Honeycrisp apples a pleasant sweet-tart flavor that varies in strength depending upon the maturity of the apple.",2,30 +Banana,0.25,"Bananas are rich in potassium, riboflavin, niacin, and dietary fibre. They also have high energy value and are really good for growing children and athletes. They are also excellent for low-salt, low-fat, and cholesterol-free diets. Hundreds of different varieties of banana flourish in the tropics, from sweet yellow pygmy to large fibrous plantains and green bananas, which can only be used for cooking.",2,50 +Rainier Cherries,2.99,Sweet and juicy,2,30 +Green Grapes,2.00,"A great energy source because of their natural fruit sugar content",2,300 +Grapefruit,1.00,"One of the largest citrus fruit, grapefruits are a cross between the pomelo and the shaddock. High in vitamin C, grapefruits are best eaten raw, a traditional breakfast fruit. The best way to eat is to cut them in half and scoop out the flesh with a spoon.",2,10 +Kumquat,0.50,"The name means ""golden orange"" in Chinese. Kumquats are often preserved in sweet syrup and used for marmalade and garnishes, but fresh ones are delicious in fruit salads or for eating just as they are.",2,80 +Lemon,0.25,"Rarely eaten on its own, lemons are an indispensable ingredient in the kitchen. Lemon juice can be used instead of vinegar in sauces, for seasoning in vinaigrette and as instant dressing for fish and shellfish. The best way to store lemon is in the vegetable crisper in the fridge you can put lemons in fruit bowl for a shorter, check them often - if one starts to spoil, the rest will quickly follow.",2,15 +Pineapple,3.00,"Derived from the Spanish word 'pina' meaning pine cone. Pineapples have a juicy, sweet-but sometimes slightly tart-fragrant flavour. They are best eaten fresh, serve pineapple flesh in slices, wedges or chunks. It is also available in cans, dried and glace. A good source of vitamin C.",2,14 +Plums,1.25,"Plums contain more antioxidant than any other fruit. Plums are delicate so make sure that the one you buy are unblemished, and they should be plump and firm. The small sugar plum is dried to make prunes. Delicious stewed, plums are also ideal for making chutneys.",2,16 +Start Apple,1.15,"The star apple fruits are green to purple with a smooth skin. When sliced horizontally the flesh is translucent white with the seeds forming a star shape. It is best eaten ripe, scooped straight from the skin. It is ripe when soft and should be eaten immediately, but it is still alright to refrigerate for a few days.",2,45 +Strawberry,2.78,"A unique fruit, the seeds grow around the outside of the fruit rather than inside it. Comes in many different sizes, colours and shapes, ranging from cone-like, to oval, or heart-shaped. Best to eat on their own or with natural yoghurt. Use strawberries in desserts, fruit salads, preserves, or in milkshakes.",3,26 +Watermelon,5.00,"The high water content of watermelons means that they are low in calories. They contain some vitamins B and C. Watermelon is excellent juiced, chopped up into a fruit salad, or just eaten in chunky slices.",3,43 +Tamarillo,1.65,"these are related to tomatoes and sometimes called ""tree tomatoes."" They are the size of an egg tomato, with dark red skin. The fruit has a strong, sweet flavour that makes it suitable for both sweet or savoury dishes. It can also be used in jams, chutneys, and sorbets.",3,12 +Rambutan,3.40,"The rambutan fruit grows in clusters, with a deep crimson outer skin. The flesh is translucent, and the pale seed is edible when young. Related to lychees and are sometimes known as ""hairy lychees"".(about 5cm / 2inches in diameter) and look quite different but have a similar texture. They can be added to salads, made into jams or jellies, but they are best eaten on their own.",3,3 +Peach,2.25,"Or pawpaw, a large tropical fruit whose ripe flesh can be juicy, creamy, orange-red, or yellow. In the centre is a mass of large peppery black seeds, which are edible and sometimes crushed and used as a spice. Ripe papaya is eaten as a breakfast fruit or as a dessert. It can also be pureed for ice cream, sorbets and iced drinks.",3,9 +Fig,0.50,"Figs are oval or pear-shaped and can be eaten fresh or dried. They are well known for their laxative and digestive properties. Their high, natural sugar content makes them the sweetest of all fruits. The flavour varies, depending on where they were grown and how ripe they are.",4,24 +Lime,0.25,"Limes are only green because they are picked unripe but if left to ripen they turn yellow. Limes can be used like lemons but as juice, it is more acidic, so usually less is needed. To make the juice flow more, you can microwave the limes for 2-3 seconds before squeezing. Mostly used in drinks (lime cordials) and cooking.",4,65 +Passionfruit,3.00,"The most popular variety is the purple passionfruit about the size of a chicken egg. It has a highly fragrant, sweet, but slightly tart, tasting fruit that can be spooned out and eaten fresh or added to fruit salad, pavlova, and it makes a very popular drink, ice cream and sorbets and a flavouring for all kinds of desserts.",4,43 +Nectarine,1.25,"The nectarine flesh is rich, sweet and juicy and is well suited for eating fresh and for using in ice cream, pies and fruit salads. Colour ranges from silvery white or yellowy orange to pinkish red. The white-fleshed varieties are considered the best and usually the most expensive. Nectarines are often described as a cross between a peach and a plum, but nectarines are actually a variety of smooth-skinned peach.",4,2 +Mangosteen,1.15,"Contrary to its name, the mangosteen doesn't resemble or taste like the mango. It resemble an apple, having a short stem and four thick leaf-like bracts which form a rosette encasing the brownish-purple fruit.",4,7 From e9ccf7800cc37b1e5a81ad3c179ba7bda941e7ab Mon Sep 17 00:00:00 2001 From: Abiaina Date: Sun, 22 Apr 2018 21:31:40 -0700 Subject: [PATCH 122/320] created order controller methods, order _item model methods --- app/controllers/order_items_controller.rb | 19 ++++++++++++--- app/controllers/orders_controller.rb | 28 +++++++++++++++++++++++ app/models/order_item.rb | 11 +++++---- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index 3b6b4c8142..82df14a587 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -8,6 +8,18 @@ def new end def create + OrderItem.make_many (order_item_params[:order], order_item_params[:user_id].order.id) + @order.user_id = @user.id + if @order.save + flash[:status] = :success + flash[:result_text] = "Successful order" + # redirect_to where???? + else + flash[:status] = :failure + flash[:result_text] = "Could not make order" + flash[:messages] = @order.errors.messages + render :new, status: :bad_request + end end def edit @@ -23,7 +35,8 @@ def show end private - - #params - + def order_item_params + # How to make the session hash be passed on? + params.require().permit(:order, :user_id) + end end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 324127f956..f068ea95e4 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,9 +1,37 @@ class OrdersController < ApplicationController def index + orders = Order.all + end + def new + order = Order.new end def create + @order = Order.new(order_params) + + # is this right? + if User.find(order_params[:user_id].to_i).nil? + @user = User.find(1) + else + @user = User.find(order_params[:user_id].to_i) + end + + @order.user_id = @user.id + if @order.save + flash[:status] = :success + flash[:result_text] = "Successful order" + # redirect_to where???? + else + flash[:status] = :failure + flash[:result_text] = "Could not make order" + flash[:messages] = @order.errors.messages + render :new, status: :bad_request + end + end + private + def order_params + params.require(:order).permit(:user_id, :status, :email, :street, :city, :state, :zip, :card_number, :date_year, :date_month, :date_day, :cvv, :name) end end diff --git a/app/models/order_item.rb b/app/models/order_item.rb index 888ef85753..1dad2261cf 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -9,10 +9,13 @@ class OrderItem < ApplicationRecord numericality: true } + # validates_uniqueness_of :order_item, :scope => [:order_id, :product_id] - # I am not sure if this is correct - # haven't written the model tests yet - # I am h oping to to validate for unique combos of order_id and item_id to prevent repeat orders + def self.make_many (hash, order_id) + hash.each do |key, value| + # help me :0 + OrderItem.create(order_id, key, value) + end + end - # validates_uniqueness_of :order_item, :scope => [:order_id, :product_id] end From 5c32ecf63c4f91a0fcad9be1c986226eef5167b4 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Mon, 23 Apr 2018 09:54:25 -0700 Subject: [PATCH 123/320] adds edit profile form --- app/controllers/users_controller.rb | 18 ++++++++++++++++++ app/views/users/_formedituser.html.erb | 12 ++++++++++++ app/views/users/edit.html.erb | 3 +-- 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 app/views/users/_formedituser.html.erb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 435bb0534a..8220077360 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -35,9 +35,21 @@ def create end def edit + @user = User.find_by(id: params[:id]) end def update + if @user + if @user.update(user_params) + flash[:success] = "#{@user.Name} updated" + redirect_to user_path(@user.id) + else + flash.now[:alert] = "Failed to update" + render :edit + end + else + redirect_to user_path(@user.id) + end end def destroy @@ -45,4 +57,10 @@ def destroy session[:order] = nil redirect_to root_path end + + private + + def user_params + return params.require(:user).permit(:name, :email) + end end diff --git a/app/views/users/_formedituser.html.erb b/app/views/users/_formedituser.html.erb new file mode 100644 index 0000000000..0915d78b73 --- /dev/null +++ b/app/views/users/_formedituser.html.erb @@ -0,0 +1,12 @@ +

      Edit Profile

      + +<%= form_for @user do |f| %> + + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label :email %> + <%= f.text_field :email %> + + <%= f.submit %> +<% end %> diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 1881fbdba0..8a012a39bb 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -1,2 +1 @@ -

      Users#edit

      -

      Find me in app/views/users/edit.html.erb

      +<%= render partial: "formedituser" %> From 5bc7b590e505a12d9a175973baed5e80329f5ec6 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Mon, 23 Apr 2018 09:55:19 -0700 Subject: [PATCH 124/320] problem with creating new Order, removed and commented out order validations --- app/controllers/orders_controller.rb | 19 +++++++++---------- app/models/order.rb | 27 ++++++++++++++------------- app/models/order_item.rb | 1 - app/views/orders/index.html.erb | 10 +++++++++- config/routes.rb | 4 +++- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index f068ea95e4..418c3e7158 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -4,21 +4,20 @@ def index end def new - order = Order.new - end - - def create - @order = Order.new(order_params) - - # is this right? - if User.find(order_params[:user_id].to_i).nil? - @user = User.find(1) + # fix this logic should refer to the user_id for finding if a user exists + if User.find(session[user_id].find(1) else - @user = User.find(order_params[:user_id].to_i) + @user = User.find(session[:user_id].to_i) end + @order = Order.new @order.user_id = @user.id + end + + def create + @order = Order.new(order_params) if @order.save + session[:order_id] = @order.id flash[:status] = :success flash[:result_text] = "Successful order" # redirect_to where???? diff --git a/app/models/order.rb b/app/models/order.rb index 01457b3d41..2caf80b5a4 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -2,19 +2,20 @@ class Order < ApplicationRecord has_many :order_items belongs_to :user - validates :order_items, length: { minimum: 1 } - - validates :name, :card_number, :email, :street, :city, :state, :zip, :date_year, :date_month, :date_day, :cvv, presence: true - - validates :name, length: { minimum: 1 } - - validates :card_number, :zip, :date_year, :date_day, :date_month, :cvv, numericality: { only_integer: true } - - validates :card_number, length: { is: 16 } - validates :cvv, length: { is: 3 } - validates :zip, length: { is: 5 } - - validates_email_format_of :email + validates :name, presence: true + + # validates :name, :card_number, :email, :street, :city, :state, :zip, :date_year, :date_month, :date_day, :cvv, presence: true + # + # validates :name, length: { minimum: 1 } + # + # validates :card_number, :zip, :date_year, :date_day, :date_month, :cvv, numericality: { only_integer: true } + # + # validates :card_number, length: { is: 16 } + # validates :cvv, length: { is: 3 } + # validates :zip, length: { is: 5 } + # + # validates_email_format_of :email + # end diff --git a/app/models/order_item.rb b/app/models/order_item.rb index 1dad2261cf..d69dd3ae63 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -13,7 +13,6 @@ class OrderItem < ApplicationRecord def self.make_many (hash, order_id) hash.each do |key, value| - # help me :0 OrderItem.create(order_id, key, value) end end diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index 91d235a84e..22827ffb5b 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -1,4 +1,12 @@

      Orders#index

      -

      Find me in app/views/orders/index.html.erb

      +

      +

        + <% @orders.each do |order| %> +
      • + <%= order %> +
      • + <% end %> +
      +

      diff --git a/config/routes.rb b/config/routes.rb index 7b7c870217..f644818a7a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,6 @@ Rails.application.routes.draw do + # we should make another root homepage with fewer items to show root 'products#index' # get '/order', to: 'orders#index', as: 'order' @@ -9,7 +10,8 @@ get '/auth/github', as: 'github_login' delete '/logout', to: "users#destroy", as: "logout" - + # Orders + get '/orders' , to: 'orders#index', as: 'orders' # resources :sessions get '/order' , to: 'sessions#index', as: 'order' post '/order' , to: 'sessions#create', as: 'add_to_order' From e4d9e376e86c56710d3fcb2c5818070f007349f7 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Mon, 23 Apr 2018 10:18:44 -0700 Subject: [PATCH 125/320] uncommented out Order validations added orders view page and not in order controller for order form code --- app/controllers/orders_controller.rb | 5 +++-- app/models/order.rb | 26 ++++++++++++-------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 418c3e7158..d008455211 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,11 +1,12 @@ class OrdersController < ApplicationController def index - orders = Order.all + @orders = Order.all end def new + # Fix this logic with Mari's & Pheobe's code # fix this logic should refer to the user_id for finding if a user exists - if User.find(session[user_id].find(1) + if User.find(session[:user_id].find(1)) else @user = User.find(session[:user_id].to_i) end diff --git a/app/models/order.rb b/app/models/order.rb index 2caf80b5a4..28000317df 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -3,19 +3,17 @@ class Order < ApplicationRecord belongs_to :user - validates :name, presence: true - - # validates :name, :card_number, :email, :street, :city, :state, :zip, :date_year, :date_month, :date_day, :cvv, presence: true - # - # validates :name, length: { minimum: 1 } - # - # validates :card_number, :zip, :date_year, :date_day, :date_month, :cvv, numericality: { only_integer: true } - # - # validates :card_number, length: { is: 16 } - # validates :cvv, length: { is: 3 } - # validates :zip, length: { is: 5 } - # - # validates_email_format_of :email - # + validates :name, :card_number, :email, :street, :city, :state, :zip, :date_year, :date_month, :date_day, :cvv, presence: true + + validates :name, length: { minimum: 1 } + + validates :card_number, :zip, :date_year, :date_day, :date_month, :cvv, numericality: { only_integer: true } + + validates :card_number, length: { is: 16 } + validates :cvv, length: { is: 3 } + validates :zip, length: { is: 5 } + + validates_email_format_of :email + end From 44d2b092b0f0c438d4ac9d0a02632171364898b8 Mon Sep 17 00:00:00 2001 From: marikoja Date: Mon, 23 Apr 2018 10:23:26 -0700 Subject: [PATCH 126/320] checkout form --- app/assets/javascripts/application.js | 2 +- app/controllers/orders_controller.rb | 10 + app/views/layouts/application.html.erb | 3 +- app/views/orders/_form.html.erb | 34 +++ app/views/orders/create.html.erb | 0 app/views/orders/index.html.erb | 3 +- app/views/orders/new.html.erb | 4 + app/views/orders/normalize.css | 341 +++++++++++++++++++++++++ app/views/sessions/index.html.erb | 2 +- config/routes.rb | 4 +- 10 files changed, 396 insertions(+), 7 deletions(-) create mode 100644 app/views/orders/_form.html.erb create mode 100644 app/views/orders/create.html.erb create mode 100644 app/views/orders/new.html.erb create mode 100644 app/views/orders/normalize.css diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index f04673be81..cf4bdced41 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -14,7 +14,7 @@ // //= require rails-ujs //= require foundation -//= require turbolinks + //= require_tree . $(function(){ $(document).foundation(); }); diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 324127f956..496e923a60 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -3,6 +3,16 @@ def index end + def new + @user = User.find_by(id: session[:user_id]) + + if @user.nil? + @user = User.find(1) + end + + @new_order = Order.new(user_id: @user.id) + end + def create end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 0be3aea434..a54a9b1456 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -29,8 +29,6 @@ <% end %> <%= link_to "Order", order_path, class: "button" %> - - +
      diff --git a/app/views/orders/_form.html.erb b/app/views/orders/_form.html.erb new file mode 100644 index 0000000000..704b8c5dda --- /dev/null +++ b/app/views/orders/_form.html.erb @@ -0,0 +1,34 @@ +<%= form_for @new_order, url: '/orders/new' do |f| %> + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label :email %> + <%= f.text_field :email %> + + <%= f.label :card_number %> + <%= f.text_field :card_number %> + +<%# maybe refactor with method to use a single date field and separate with logic %> + <%= f.label :date_year %> + <%= f.text_field :date_year %> + + <%= f.label :date_month %> + <%= f.text_field :date_month %> + + <%= f.label :date_day %> + <%= f.text_field :date_day %> + + <%= f.label :cvv %> + <%= f.text_field :cvv %> + + <%= f.label :street %> + <%= f.text_field :street %> + + <%= f.label :city %> + <%= f.text_field :city %> + + <%= f.label :zip %> + <%= f.text_field :zip %> + + <%= f.submit %> +<% end %> diff --git a/app/views/orders/create.html.erb b/app/views/orders/create.html.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index 91d235a84e..0ee1ff4eec 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -1,4 +1,3 @@ -

      Orders#index

      -

      Find me in app/views/orders/index.html.erb

      +

      Shopping Cart

      diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb new file mode 100644 index 0000000000..70e6f8df24 --- /dev/null +++ b/app/views/orders/new.html.erb @@ -0,0 +1,4 @@ +<%= render partial: "form" %> + +

      this should show up

      +<%= %> diff --git a/app/views/orders/normalize.css b/app/views/orders/normalize.css new file mode 100644 index 0000000000..47b010e477 --- /dev/null +++ b/app/views/orders/normalize.css @@ -0,0 +1,341 @@ +/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 06c5c2bb50..6c9192bd08 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -32,7 +32,7 @@

      Total: $<%= calculate_total.round(2) %>

      - <%= link_to "Checkout", create_order_path, method: :post ,class: "button" %> + <%= link_to "Checkout", new_order_path, class: "button" %> <%= link_to "Clear Order", delete_order_path, method: :delete, data: { confirm: "Are you sure?" }, class: "button" %> <%= link_to "Continue Shopping", products_path, class: "button" %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 7b7c870217..befec60c99 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -25,7 +25,9 @@ resources :categories - # resources :orders + # resources :orders, only: [:new, :create] + get '/orders/new', to: 'orders#new', as: 'new_order' + resources :users do resources :products, except: [:delete] From 5adde3715b9b22e6737e9f34ed1d64714e270b0f Mon Sep 17 00:00:00 2001 From: Abiaina Date: Mon, 23 Apr 2018 10:40:29 -0700 Subject: [PATCH 127/320] order show page, created routes/updated model methods for order/user relationship --- app/controllers/orders_controller.rb | 24 ++++++++++++++++-------- app/views/orders/show.html.erb | 1 + config/routes.rb | 1 + 3 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 app/views/orders/show.html.erb diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 418c3e7158..9e087f5716 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,26 +1,34 @@ class OrdersController < ApplicationController def index - orders = Order.all + @orders = Order.all end def new - # fix this logic should refer to the user_id for finding if a user exists - if User.find(session[user_id].find(1) + @order = Order.new + end + + def show + @order = Order.find_by(id: params[:id]) + end + + def create + @user = User.find_by(id: session[:user_id]) + + if @user else - @user = User.find(session[:user_id].to_i) + @user = User.find(1) end - @order = Order.new @order.user_id = @user.id - end - def create @order = Order.new(order_params) if @order.save + session[:order_id] = @order.id + flash[:status] = :success flash[:result_text] = "Successful order" - # redirect_to where???? + redirect_to order_details_path(@order.id) else flash[:status] = :failure flash[:result_text] = "Could not make order" diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb new file mode 100644 index 0000000000..bd00daa7fa --- /dev/null +++ b/app/views/orders/show.html.erb @@ -0,0 +1 @@ +

      Order: <%= @order.id %>

      diff --git a/config/routes.rb b/config/routes.rb index 1685983706..8777fa3945 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,6 +12,7 @@ # Orders get '/orders' , to: 'orders#index', as: 'orders' + get '/order/:id' , to: 'orders#show', as: 'order_details' # resources :sessions get '/order' , to: 'sessions#index', as: 'order' post '/order' , to: 'sessions#create', as: 'add_to_order' From 9a2849bdca2dc8d73eb21ebf863d80f70246e532 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 10:41:21 -0700 Subject: [PATCH 128/320] adds homepage --- app/controllers/products_controller.rb | 5 +++++ app/views/products/index.html.erb | 4 ++-- app/views/products/root.html.erb | 17 +++++++++++++++++ config/routes.rb | 3 ++- 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 app/views/products/root.html.erb diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 5a7872d3be..7b27d05245 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -1,4 +1,9 @@ class ProductsController < ApplicationController + + def root + @products = Product.all + end + def index @user = User.find_by(id: params[:user_id]) if @user.nil? # if the user does not exist diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index c2fe046977..5583e28051 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -1,7 +1,7 @@ <% if @user.nil? %> -

      FruEtsy Goodies

      - <% products = @products.sample(12) %> +

      All FruEtsy Goodies

      + <% products = @products %> <% else %>

      <%= @user.name %> Goodies

      <% products = @products %> diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb new file mode 100644 index 0000000000..f4cefe7c62 --- /dev/null +++ b/app/views/products/root.html.erb @@ -0,0 +1,17 @@ +
      +

      Product Highlights

      +
        + <% @products.sample(3).each do |product|%> +
      • + fruit! + + <%= link_to product.name, product_path(product[:id]) %> + + $<%= product.price.round(2) %> + + <%= product.description %> +
      • + + <% end %> +
      +
      diff --git a/config/routes.rb b/config/routes.rb index 7abb176aa5..130dae7a90 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,8 @@ Rails.application.routes.draw do # we should make another root homepage with fewer items to show - root 'products#index' + # root 'products#index' + root 'products#root' # get '/order', to: 'orders#index', as: 'order' # post '/order', to: 'orders#create', as: 'add_to_order' From 0104eb78237dfaeb8aac241a4d90fac665dffd80 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 10:42:58 -0700 Subject: [PATCH 129/320] fixes nav bar button layout --- app/views/layouts/application.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a54a9b1456..d74501004e 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -25,7 +25,7 @@ <%= link_to "Add Product", new_user_product_path(session[:user_id]), class: "button right" %> <% else %> - <%= link_to "user Login", github_login_path, class: "button" %> + <%= link_to "user Login", github_login_path, class: "button right" %> <% end %> <%= link_to "Order", order_path, class: "button" %> From 31b49d8c3432d5a11f513a8e32737aa7e0b984eb Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 10:57:03 -0700 Subject: [PATCH 130/320] refactors --- config/routes.rb | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 130dae7a90..caf1b44aba 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,19 +1,16 @@ Rails.application.routes.draw do - # we should make another root homepage with fewer items to show - # root 'products#index' root 'products#root' - # get '/order', to: 'orders#index', as: 'order' - # post '/order', to: 'orders#create', as: 'add_to_order' - get "/auth/:provider/callback", to: "users#create", as: "auth_callback" get '/auth/github', as: 'github_login' delete '/logout', to: "users#destroy", as: "logout" # Orders - get '/orders' , to: 'orders#index', as: 'orders' - # resources :sessions + get '/orders' , to: 'orders#index', as: 'orders' + get '/orders/new', to: 'orders#new', as: 'new_order' + + get '/order' , to: 'sessions#index', as: 'order' post '/order' , to: 'sessions#create', as: 'add_to_order' patch '/order' , to: 'sessions#update', as: 'update_order' @@ -29,11 +26,6 @@ resources :order_items - - # resources :orders, only: [:new, :create] - get '/orders/new', to: 'orders#new', as: 'new_order' - - resources :users do resources :products, except: [:delete] resources :orders, only: [:index, :show] From ecc99b2db88b75bd799049698a07507c5e8eab52 Mon Sep 17 00:00:00 2001 From: marikoja Date: Mon, 23 Apr 2018 12:40:11 -0700 Subject: [PATCH 131/320] checkout page --- app/assets/stylesheets/application.css | 16 +++++++++- app/views/orders/_form.html.erb | 6 ++-- app/views/orders/new.html.erb | 43 ++++++++++++++++++++++++-- app/views/sessions/index.html.erb | 2 +- 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3dd0050d44..3d188cd469 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -20,7 +20,7 @@ header { background: lightgreen; - + text-align: center; padding-top: 5%; } @@ -42,3 +42,17 @@ nav .button.right { ul li { list-style-type: none; } + +.checkout_page { + margin: 50px; + display: grid; + grid-template-columns: 1fr 1fr; + grid-column-gap: 1rem; + +} + +.checkout_form { + display: grid; + flex-wrap: wrap; + flex-direction: column; +} diff --git a/app/views/orders/_form.html.erb b/app/views/orders/_form.html.erb index 704b8c5dda..39f8c98b78 100644 --- a/app/views/orders/_form.html.erb +++ b/app/views/orders/_form.html.erb @@ -8,6 +8,9 @@ <%= f.label :card_number %> <%= f.text_field :card_number %> + <%= f.label :cvv %> + <%= f.text_field :cvv %> + <%# maybe refactor with method to use a single date field and separate with logic %> <%= f.label :date_year %> <%= f.text_field :date_year %> @@ -18,9 +21,6 @@ <%= f.label :date_day %> <%= f.text_field :date_day %> - <%= f.label :cvv %> - <%= f.text_field :cvv %> - <%= f.label :street %> <%= f.text_field :street %> diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb index 70e6f8df24..24826c4a1b 100644 --- a/app/views/orders/new.html.erb +++ b/app/views/orders/new.html.erb @@ -1,4 +1,41 @@ -<%= render partial: "form" %> +
      -

      this should show up

      -<%= %> +
      + <%= render partial: "form" %> +
      +
      + +
      + + + + + + + + + + + + + <% session[:order].each do |key, val| %> + <% @product = Product.find_by(id: key.to_i) %> + <% params[:id] = key %> + + + + + <%= form_tag('/order', method: :patch) do %> + + <%= hidden_field_tag 'id', "#{key}" %> + <% end %> + + <% end %> + +
      ProductDescriptionPriceQuantity
      <%= @product.name %><%= @product.description %>$<%= @product.price %><%= number_field_tag 'quantity', "#{val}" %>
      +

      Total: $<%= calculate_total.round(2) %>

      +
      + + + +
      diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 6c9192bd08..0cd1f8bf5c 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,4 +1,4 @@ -

      Current Order

      +

      Shopping Cart

      <% if session[:order].nil? || session[:order] == {} %>

      No Items in the Order

      <%= link_to "Add to Order", products_path, class: "button" %>

      From d730d32f26d47143e63f54a72f6bc05b7c693085 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 12:42:34 -0700 Subject: [PATCH 132/320] adds logic to product show for review option --- app/views/layouts/application.html.erb | 1 - app/views/products/show.html.erb | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d74501004e..3880d7e325 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,7 +12,6 @@ -

      Welcome to FruEtsy

      for all your syrup-less fruit salad needs

      diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index ed585953ea..bc83f0d3ce 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,7 +1,12 @@

      <%= @product.name %>

      - <%= link_to "Review #{@product.name}", new_product_review_path(@product.id) %> + <% if @product.user_id == session[:user_id] %> +

      You cannot review your own product

      + <% else %> + <%= link_to "Review #{@product.name}", new_product_review_path(@product.id) %> + <% end %> +
      fruit! From bc4d3bbd93221fb6dc3494f31d207327d3179c92 Mon Sep 17 00:00:00 2001 From: marikoja Date: Mon, 23 Apr 2018 12:56:23 -0700 Subject: [PATCH 133/320] creates dropdown for merchants --- app/views/layouts/application.html.erb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d74501004e..2a74c1312a 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -47,7 +47,15 @@ <% end %>
    -
  • <%= link_to "Merchants", users_path %>
  • +
  • <%= link_to "Merchants", users_path %> + +
  • From 717821da3a5c0b16a61f4d7110ff5492fce5a9ad Mon Sep 17 00:00:00 2001 From: Abiaina Date: Mon, 23 Apr 2018 13:29:49 -0700 Subject: [PATCH 134/320] add logic to order model/controller --- app/controllers/order_items_controller.rb | 28 ++++++++++------------- app/controllers/orders_controller.rb | 6 ++++- app/models/order.rb | 21 +++++++++++++++++ app/models/order_item.rb | 6 ----- app/views/orders/show.html.erb | 13 +++++++++++ 5 files changed, 51 insertions(+), 23 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index 82df14a587..677a583d87 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -3,23 +3,19 @@ def index @order_items = OrderItem.all end - def new - @order_item = OrderItem.new - end - def create - OrderItem.make_many (order_item_params[:order], order_item_params[:user_id].order.id) - @order.user_id = @user.id - if @order.save - flash[:status] = :success - flash[:result_text] = "Successful order" - # redirect_to where???? - else - flash[:status] = :failure - flash[:result_text] = "Could not make order" - flash[:messages] = @order.errors.messages - render :new, status: :bad_request - end + @order_item = OrderItem.new + # @order.user_id = @user.id + # if @order.save + # flash[:status] = :success + # flash[:result_text] = "Successful order" + # # redirect_to where???? + # else + # flash[:status] = :failure + # flash[:result_text] = "Could not make order" + # flash[:messages] = @order.errors.messages + # render :new, status: :bad_request + # end end def edit diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 9e087f5716..399ff1531e 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -12,6 +12,8 @@ def show end def create + @order = Order.new(order_params) + @user = User.find_by(id: session[:user_id]) if @user @@ -21,13 +23,15 @@ def create @order.user_id = @user.id - @order = Order.new(order_params) if @order.save session[:order_id] = @order.id flash[:status] = :success flash[:result_text] = "Successful order" + + @order_items = Order.make_order_items(@order.id, session[:order]) + redirect_to order_details_path(@order.id) else flash[:status] = :failure diff --git a/app/models/order.rb b/app/models/order.rb index 2caf80b5a4..818dc725b8 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -18,4 +18,25 @@ class Order < ApplicationRecord # validates_email_format_of :email # + + # loop through hash of orders to add to order + def self.make_order_items(id, hash) + order_items = [] + + hash.each do |key, value| + + order_item = OrderItem.new + + order_item.product_id = key.to_i + order_item.order_id = session[:order_id].to_i + order_item.status = "paid" + order_item.quantity = value.to_i + + order_item.save + + order_items << order_item + end + return order_items + end + end diff --git a/app/models/order_item.rb b/app/models/order_item.rb index d69dd3ae63..2232b5147f 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -11,10 +11,4 @@ class OrderItem < ApplicationRecord # validates_uniqueness_of :order_item, :scope => [:order_id, :product_id] - def self.make_many (hash, order_id) - hash.each do |key, value| - OrderItem.create(order_id, key, value) - end - end - end diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index bd00daa7fa..153ef7cf27 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -1 +1,14 @@

    Order: <%= @order.id %>

    +

    order_items

    + +
      + <% @order_items.each do |order_item| %> +
    • <%= Product.find_by(id: order_item.product_id) %> +
    • +
    • Quantity <%= order_item.quantity %> +
    • +
    • + <%= Product.find_by(id: order_item.product_id).user %> +
    • + <% end %> +
    From ebffd926270b480abf1f20671a89d0445e4a582d Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 13:37:31 -0700 Subject: [PATCH 135/320] review restriction logic --- app/controllers/products_controller.rb | 9 +++++++-- app/controllers/sessions_controller.rb | 14 +++++++------- config/routes.rb | 9 ++++----- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 7b27d05245..484e5ed454 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -15,12 +15,17 @@ def index def new @product = Product.new - @product.user = User.find_by(uid: session[:uid]) + @user = User.find_by(id: session[:user_id]) + # @product.user = User.find_by(uid: session[:uid]) + @product.user = @user end def create @product = Product.new(product_params) - @product.user = User.find_by(uid: session[:uid]) + @user = User.find_by(id: session[:user_id]) + @product.user = @user + + #@product.user = User.find_by(uid: session[:uid]) @action = new_user_product_path(@product.user.id) if @product.save flash[:success] = "New product added" diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 68032ba4c1..c97e6b4ba2 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -11,7 +11,6 @@ def new def create # add logic for adding an item that is already in the order - quantity = params[:quantity] product_id = params[:product_id] @product = Product.find_by(id: product_id) @@ -22,13 +21,14 @@ def create @product.update(quantity: new_quantity) # add to sessions # check if session[:order] is empty - if session[:order].nil? - session[:order] = { @product.id => quantity.to_i } - else - session[:order].merge!(@product.id => quantity.to_i) - # session[:order][@product.id] = quantity.to_i - end + if session[:order].nil? + session[:order] = { @product.id => quantity.to_i } + else + session[:order].merge!(@product.id => quantity.to_i) + # session[:order][@product.id] = quantity.to_i + end # redirect + flash[:success] = "Product added to order" redirect_to order_path else # flash message that the quantity is too high diff --git a/config/routes.rb b/config/routes.rb index caf1b44aba..2d0433c919 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,11 +6,6 @@ get '/auth/github', as: 'github_login' delete '/logout', to: "users#destroy", as: "logout" - # Orders - get '/orders' , to: 'orders#index', as: 'orders' - get '/orders/new', to: 'orders#new', as: 'new_order' - - get '/order' , to: 'sessions#index', as: 'order' post '/order' , to: 'sessions#create', as: 'add_to_order' patch '/order' , to: 'sessions#update', as: 'update_order' @@ -18,6 +13,10 @@ post '/orderitem' , to: 'order_items#create', as: 'create_order' + # Orders + get '/orders' , to: 'orders#index', as: 'orders' + get '/orders/new', to: 'orders#new', as: 'new_order' + resources :products do resources :reviews end From 176da60216b9a47c9ba8f24c59ba19cf1c623b05 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Mon, 23 Apr 2018 13:37:46 -0700 Subject: [PATCH 136/320] adds product edit --- app/assets/javascripts/application.js | 2 +- app/controllers/products_controller.rb | 2 +- app/views/products/index.html.erb | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index f04673be81..cf4bdced41 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -14,7 +14,7 @@ // //= require rails-ujs //= require foundation -//= require turbolinks + //= require_tree . $(function(){ $(document).foundation(); }); diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 5a7872d3be..e616224de4 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -33,7 +33,7 @@ def update end def show - @product = Product.find_by(id: params[:id]) + @product = Product.find_by(id: params[:id]) # redirect_to order_path end diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index c2fe046977..670ec089bf 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -20,6 +20,7 @@ <%= product.description %> + <% end %> From 5f6dadc27bc1200a607e577e4edbba4399fa929e Mon Sep 17 00:00:00 2001 From: marikoja Date: Mon, 23 Apr 2018 13:55:27 -0700 Subject: [PATCH 137/320] update variable name --- app/controllers/orders_controller.rb | 2 +- app/views/orders/_form.html.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 58308b5921..e61a7751f7 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -10,7 +10,7 @@ def new @user = User.find(1) end - @new_order = Order.new(user_id: @user.id) + @order = Order.new(user_id: @user.id) end def create diff --git a/app/views/orders/_form.html.erb b/app/views/orders/_form.html.erb index 39f8c98b78..4c20a700b3 100644 --- a/app/views/orders/_form.html.erb +++ b/app/views/orders/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_for @new_order, url: '/orders/new' do |f| %> +<%= form_for @order, url: '/orders/new' do |f| %> <%= f.label :name %> <%= f.text_field :name %> From 8a87cfd7cddf2738c43edf992c9297da3f18a306 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 13:57:58 -0700 Subject: [PATCH 138/320] route issue change --- config/routes.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 7e5a86357a..7f6f5a0a8a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,10 +6,6 @@ get '/auth/github', as: 'github_login' delete '/logout', to: "users#destroy", as: "logout" - # Orders - get '/orders' , to: 'orders#index', as: 'orders' - get '/orders/new', to: 'orders#new', as: 'new_order' - # resources :sessions get '/order' , to: 'sessions#index', as: 'order' post '/order' , to: 'sessions#create', as: 'add_to_order' From df4e20c78bb605d1afdd1191cd1ee39c5dca0892 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Mon, 23 Apr 2018 14:24:10 -0700 Subject: [PATCH 139/320] some user edit changes --- app/controllers/sessions_controller.rb | 12 ++++++------ app/controllers/users_controller.rb | 15 ++++++--------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 68032ba4c1..86f3ac355c 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -22,12 +22,12 @@ def create @product.update(quantity: new_quantity) # add to sessions # check if session[:order] is empty - if session[:order].nil? - session[:order] = { @product.id => quantity.to_i } - else - session[:order].merge!(@product.id => quantity.to_i) - # session[:order][@product.id] = quantity.to_i - end + if session[:order].nil? + session[:order] = { @product.id => quantity.to_i } + else + session[:order].merge!(@product.id => quantity.to_i) + # session[:order][@product.id] = quantity.to_i + end # redirect redirect_to order_path else diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 8220077360..07962c5e1a 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -35,20 +35,17 @@ def create end def edit - @user = User.find_by(id: params[:id]) + @user = User.find_by(uid: session[:uid]) end def update if @user - if @user.update(user_params) - flash[:success] = "#{@user.Name} updated" - redirect_to user_path(@user.id) - else - flash.now[:alert] = "Failed to update" - render :edit - end - else + @user.update(user_params) + flash[:success] = "#{@user.Name} updated" redirect_to user_path(@user.id) + else + flash.now[:alert] = "Failed to update" + render :edit end end From b8d0d522f2692b2e00e5e0bed2c46c849a1c7114 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Mon, 23 Apr 2018 14:28:10 -0700 Subject: [PATCH 140/320] removed categories products table --- db/migrate/20180423212509_drop_products_categories.rb | 5 +++++ db/schema.rb | 9 +-------- 2 files changed, 6 insertions(+), 8 deletions(-) create mode 100644 db/migrate/20180423212509_drop_products_categories.rb diff --git a/db/migrate/20180423212509_drop_products_categories.rb b/db/migrate/20180423212509_drop_products_categories.rb new file mode 100644 index 0000000000..80b76e2670 --- /dev/null +++ b/db/migrate/20180423212509_drop_products_categories.rb @@ -0,0 +1,5 @@ +class DropProductsCategories < ActiveRecord::Migration[5.1] + def change + drop_table :products_categories + end +end diff --git a/db/schema.rb b/db/schema.rb index 410d25ad65..b66024cb16 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: 20180422051721) do +ActiveRecord::Schema.define(version: 20180423212509) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -66,13 +66,6 @@ t.integer "quantity" end - create_table "products_categories", force: :cascade do |t| - t.bigint "product_id" - t.bigint "category_id" - t.index ["category_id"], name: "index_products_categories_on_category_id" - t.index ["product_id"], name: "index_products_categories_on_product_id" - end - create_table "reviews", force: :cascade do |t| t.integer "product_id" t.integer "rating" From c29636b6db314041e2f41c8265317ac3cbfa30ef Mon Sep 17 00:00:00 2001 From: marikoja Date: Mon, 23 Apr 2018 14:33:14 -0700 Subject: [PATCH 141/320] header image --- app/assets/stylesheets/application.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3d188cd469..4b2dfad822 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -19,7 +19,9 @@ */ header { - background: lightgreen; + /* background: lightgreen; */ + background-image: url("https://spindriftfresh.com/wp-content/uploads/2017/12/fruit-header-1.jpg"); + background-size: cover; text-align: center; padding-top: 5%; From 7729fae8387decce5de8eaa099bcc09f91898f6c Mon Sep 17 00:00:00 2001 From: marikoja Date: Mon, 23 Apr 2018 14:39:57 -0700 Subject: [PATCH 142/320] fixes merchant dropdown links --- app/views/layouts/application.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index cd85708b0c..1ea9537fa1 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -50,7 +50,7 @@ From fe3acc59fd79410a24dd34ca0795d28a73063a51 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Mon, 23 Apr 2018 14:40:46 -0700 Subject: [PATCH 143/320] fixes user profile edit --- app/controllers/users_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 07962c5e1a..d43318e42d 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -39,9 +39,10 @@ def edit end def update + @user = User.find_by(uid: session[:uid]) if @user @user.update(user_params) - flash[:success] = "#{@user.Name} updated" + flash[:success] = "#{@user.name} updated" redirect_to user_path(@user.id) else flash.now[:alert] = "Failed to update" From 1f8aa8926aa03fc5923388af9aba2e10131cf34e Mon Sep 17 00:00:00 2001 From: marikoja Date: Mon, 23 Apr 2018 15:31:22 -0700 Subject: [PATCH 144/320] header styling first attempts --- app/assets/stylesheets/application.css | 20 ++++++++++++++++++++ app/views/layouts/application.html.erb | 7 ++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 4b2dfad822..edb50369f8 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -27,8 +27,16 @@ header { padding-top: 5%; } +header h1 { + font-family: 'Monoton', cursive; + color: purple; +} + header .tagline { padding-left: 29%; + font-family: 'Alegreya Sans SC', sans-serif; + + color: white; } nav { @@ -41,6 +49,18 @@ nav .button.right { margin: 1em; } +nav .button { + border-radius: 2rem; + background: rgba(0, 0, 0, 0.2); + /* color: rgb(136, 33, 128); */ +} + + +.button, .dropdown_top { + font-family: 'Alegreya Sans SC', sans-serif; + color: white; +} + ul li { list-style-type: none; } diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 1ea9537fa1..51b1a83de4 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,6 +9,7 @@ <%= stylesheet_link_tag "application" %> <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> + @@ -31,7 +32,7 @@
    diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 0cd1f8bf5c..2bbc3ad7f3 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,4 +1,5 @@

    Shopping Cart

    + <% if session[:order].nil? || session[:order] == {} %>

    No Items in the Order

    <%= link_to "Add to Order", products_path, class: "button" %>

    From 29fd66f1ba77c416b0f12487f77e4856f27c6754 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Mon, 23 Apr 2018 16:58:00 -0700 Subject: [PATCH 152/320] adds some front page stlying --- app/assets/stylesheets/application.css | 6 ++++++ app/views/products/root.html.erb | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 694c78e116..15d2035a9b 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -81,3 +81,9 @@ ul li { flex-wrap: wrap; flex-direction: column; } + +.frontpage { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 1fr 1fr 1fr; +} diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index f4cefe7c62..36b70c25dd 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -1,7 +1,7 @@

    Product Highlights

    -
      - <% @products.sample(3).each do |product|%> +
        + <% @products.sample(9).each do |product|%>
      • fruit! @@ -9,7 +9,7 @@ $<%= product.price.round(2) %> - <%= product.description %> +

        <%= product.description %>

      • <% end %> From 6d2bfa5c5d1b97245861549693065df327f8e4c7 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 17:28:23 -0700 Subject: [PATCH 153/320] refactors product show page and reviews --- app/assets/stylesheets/application.css | 4 +- app/controllers/reviews_controller.rb | 4 +- app/views/products/show.html.erb | 73 +++++++++++++++----------- 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 15d2035a9b..8f5cf53ffc 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -68,7 +68,7 @@ ul li { list-style-type: none; } -.checkout_page { +.checkout_page, .product_show { margin: 50px; display: grid; grid-template-columns: 1fr 1fr; @@ -76,7 +76,7 @@ ul li { } -.checkout_form { +.checkout_form, .product_show_item { display: grid; flex-wrap: wrap; flex-direction: column; diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index e18455c152..b3fd0bce15 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -14,11 +14,11 @@ def create @review.product_id = @product.id if @review.save - flash[:status] = :success + # flash[:status] = :success flash[:result_text] = "Successfully reviewed #{@product.name}" redirect_to product_path(@product.id) else - flash[:status] = :failure + # flash[:status] = :failure flash[:result_text] = "Could not review #{@product.name}" flash[:messages] = @review.errors.messages render :new, status: :bad_request diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index cf86972781..bba370570a 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -1,38 +1,47 @@

        <%= @product.name %>

        +
        -
        - <% if @product.user_id == session[:user_id] %> -

        You cannot review your own product

        - <% else %> - <%= link_to "Review #{@product.name}", new_product_review_path(@product.id) %> - <% end %> -
        +
        + fruit! +
        + Price: $<%= @product.price.round(2) %> +
        + Quantity: <%= @product.quantity %> +
        + Description: <%= @product.description %> +
        -
        - fruit! -
        - Price: $<%= @product.price.round(2) %> -
        - Quantity: <%= @product.quantity %> -
        - Description: <%= @product.description %> -
        +
        + + <% if @product.user_id == session[:user_id] %> +

        You cannot review your own product

        + <% else %> +

        <%= link_to "Review #{@product.name}", new_product_review_path(@product.id) %>

        + <% end %> + + + + + + + + + + <% @product.reviews.each do |review| %> + + + + + <% end %> + +
        RatingReview
        <%= review.rating %><%= review.text_review %>
        -
        -

        Reviews

        -
          - <% @product.reviews.each do |review| %> -
        • Review: <%= review.text_review %> -
        • -
        • Rating: <%= review.rating %> -
        • +
          + <%= form_tag('/order', method: 'post') do %> + <%= label_tag 'quantity' %> + <%= number_field_tag 'quantity' %> + <%= hidden_field_tag 'product_id', @product.id %> + <%= submit_tag "Add to Order", class: "button" %> <% end %> -
        -
        - <%= form_tag('/order', method: 'post') do %> - <%= label_tag 'quantity' %> - <%= number_field_tag 'quantity' %> - <%= hidden_field_tag 'product_id', @product.id %> - <%= submit_tag "Add to Order", class: "button" %> - <% end %> +
        From 76c8e793c2fc49ea30c9a2a02ea77c10cafbabb6 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Mon, 23 Apr 2018 17:29:15 -0700 Subject: [PATCH 154/320] deleting migrations --- app/views/products/root.html.erb | 1 + .../20180419224116_dropproducts_categories.rb | 5 ----- db/migrate/20180420011146_drop_installs.rb | 5 ----- db/migrate/20180420012112_droptable.rb | 6 ------ ...0180420012158_create_products_categories_join.rb | 13 ------------- .../20180423212509_drop_products_categories.rb | 5 ----- 6 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 db/migrate/20180419224116_dropproducts_categories.rb delete mode 100644 db/migrate/20180420011146_drop_installs.rb delete mode 100644 db/migrate/20180420012112_droptable.rb delete mode 100644 db/migrate/20180420012158_create_products_categories_join.rb delete mode 100644 db/migrate/20180423212509_drop_products_categories.rb diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 36b70c25dd..5152a0b3f1 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -15,3 +15,4 @@ <% end %>
    + diff --git a/db/migrate/20180419224116_dropproducts_categories.rb b/db/migrate/20180419224116_dropproducts_categories.rb deleted file mode 100644 index b363e1edc0..0000000000 --- a/db/migrate/20180419224116_dropproducts_categories.rb +++ /dev/null @@ -1,5 +0,0 @@ -class DropproductsCategories < ActiveRecord::Migration[5.1] - def change - drop_table :products_categories - end -end diff --git a/db/migrate/20180420011146_drop_installs.rb b/db/migrate/20180420011146_drop_installs.rb deleted file mode 100644 index b0b445e1eb..0000000000 --- a/db/migrate/20180420011146_drop_installs.rb +++ /dev/null @@ -1,5 +0,0 @@ -class DropInstalls < ActiveRecord::Migration[5.1] - def change - drop_table :products_categories - end -end diff --git a/db/migrate/20180420012112_droptable.rb b/db/migrate/20180420012112_droptable.rb deleted file mode 100644 index 1058fe4cb6..0000000000 --- a/db/migrate/20180420012112_droptable.rb +++ /dev/null @@ -1,6 +0,0 @@ -class Droptable < ActiveRecord::Migration[5.1] - def change - drop_table :products_categories_joins - - end -end diff --git a/db/migrate/20180420012158_create_products_categories_join.rb b/db/migrate/20180420012158_create_products_categories_join.rb deleted file mode 100644 index 99bec8ab95..0000000000 --- a/db/migrate/20180420012158_create_products_categories_join.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] - def change - create_table :products_categories do |t| - - t.belongs_to :product, index: true - t.belongs_to :category, index: true - - end - end -end - - - hidden_field_tag :url, params[:url].to_s diff --git a/db/migrate/20180423212509_drop_products_categories.rb b/db/migrate/20180423212509_drop_products_categories.rb deleted file mode 100644 index 80b76e2670..0000000000 --- a/db/migrate/20180423212509_drop_products_categories.rb +++ /dev/null @@ -1,5 +0,0 @@ -class DropProductsCategories < ActiveRecord::Migration[5.1] - def change - drop_table :products_categories - end -end From 05a9b43dd41a01c6ac5cacf8253adbda35ed6379 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 17:32:52 -0700 Subject: [PATCH 155/320] additional refactor --- app/views/products/show.html.erb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index bba370570a..507342950b 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -9,6 +9,13 @@ Quantity: <%= @product.quantity %>
    Description: <%= @product.description %> + + <%= form_tag('/order', method: 'post') do %> + <%= label_tag 'quantity' %> + <%= number_field_tag 'quantity' %> + <%= hidden_field_tag 'product_id', @product.id %> + <%= submit_tag "Add to Order", class: "button" %> + <% end %>
    @@ -34,14 +41,6 @@ <% end %> - - -
    - <%= form_tag('/order', method: 'post') do %> - <%= label_tag 'quantity' %> - <%= number_field_tag 'quantity' %> - <%= hidden_field_tag 'product_id', @product.id %> - <%= submit_tag "Add to Order", class: "button" %> - <% end %> +
    From b8852e887ed17aea9188c4e8cb94a8078e3a7699 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 17:41:38 -0700 Subject: [PATCH 156/320] adds gap to homepage --- app/assets/stylesheets/application.css | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 8f5cf53ffc..90a81ef88d 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -86,4 +86,5 @@ ul li { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr; + grid-gap: 1rem; } From 4e2a0e5c9e01ae12f707b944b2f9a6daa9a8a90d Mon Sep 17 00:00:00 2001 From: Phoebe Date: Mon, 23 Apr 2018 19:30:07 -0700 Subject: [PATCH 157/320] refactors flash messages --- app/controllers/reviews_controller.rb | 6 +-- app/controllers/sessions_controller.rb | 22 +++++--- app/views/layouts/application.html.erb | 71 +++++++++++--------------- 3 files changed, 47 insertions(+), 52 deletions(-) diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index b3fd0bce15..c2adde4789 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -14,17 +14,17 @@ def create @review.product_id = @product.id if @review.save - # flash[:status] = :success + flash[:status] = :success flash[:result_text] = "Successfully reviewed #{@product.name}" redirect_to product_path(@product.id) else - # flash[:status] = :failure + flash[:status] = :failure flash[:result_text] = "Could not review #{@product.name}" flash[:messages] = @review.errors.messages render :new, status: :bad_request end end - + def index end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index d4411c8c36..8842b801c2 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -26,12 +26,13 @@ def create session[:order].merge!(@product.id => quantity.to_i) end # flash and redirect - flash[:success] = "Product added to order" + flash[:status] = :success + flash[:result_text] = "Product added to order" redirect_to order_path - else # flash message that the quantity is too high - flash.now[:alert] = "The quantity entered is too high" + flash[:status] = :alert + flash[:result_text] = "The quantity entered is too high" redirect_to product_path(@product.id) end @@ -50,20 +51,24 @@ def update update_quantity = product.quantity + old_quantity product.update(quantity: update_quantity) session[:order].delete(product_id.to_s) - flash[:success] = "Item removed from Order" + flash[:status] = :success + flash[:result_text] = "Item removed from Order" redirect_to order_path elsif new_quantity < 0 - flash.now[:alert] = "Invalid number" + flash[:status] = :alert + flash.now[:result_text] = "Invalid number" render :index elsif (product.quantity - new_quantity) < 0 - flash.now[:alert] = "Not enough in stock" + flash[:status] = :alert + flash.now[:result_text] = "Not enough in stock" render :index else diff = old_quantity - new_quantity update_quantity = product.quantity + diff product.update(quantity: update_quantity) session[:order][product_id.to_s] = new_quantity - flash[:success] = "Item quantity updated" + flash[:status] = :success + flash[:result_text] = "Item quantity updated" redirect_to order_path end end @@ -76,7 +81,8 @@ def destroy end # clear session session[:order] = {} - flash[:success] = "Order cleared successfully" + flash[:status] = :success + flash[:result_text] = "Order cleared successfully" redirect_to order_path end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 51b1a83de4..d3b828d424 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,30 +9,29 @@ <%= stylesheet_link_tag "application" %> <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> - -
    -

    Welcome to FruEtsy

    -

    for all your syrup-less fruit salad needs

    -
    -
    - - <% if flash[:result_text] or flash[:messages] %> -
    -

    <%= flash[:status] == :failure ? "A problem occurred: " : "" %><%= flash[:result_text] %> - <% if flash[:messages] %> -

      - <% flash[:messages].each do |name, problems| %> - <% problems.each do |problem| %> -
    • <%= name %>: <%= problem %>
    • - <% end %> - <% end %> -
    + + + + +
    + + <% if flash[:result_text] or flash[:messages] %> +
    +

    <%= flash[:status] == :failure ? "A problem occurred: " : "" %><%= flash[:result_text] %> + <% if flash[:messages] %> +

      + <% flash[:messages].each do |name, problems| %> + <% problems.each do |problem| %> +
    • <%= name %>: <%= problem %>
    • + <% end %> <% end %> -
    + <% end %> +
    + <% end %> - <%= yield %> -
    + <%= yield %> + -
    -

    © Bunch of Banadies

    -
    - - +
    +

    © Bunch of Banadies

    +
    + + From 159bab442cac151f190d41b8f16fe1f240274866 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 26 Apr 2018 15:52:03 -0700 Subject: [PATCH 269/320] button border weight reduced --- app/assets/stylesheets/application.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index cd88683f3f..0d9cb540c9 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -77,7 +77,7 @@ h1 { .button { border-radius: 2rem; background: none; - border: solid 3px purple; + border: solid 1px purple; color: rgb(136, 33, 128); font-family: 'Didact Gothic', sans-serif; } From 5dfa45cf70680fd427818c7c47172fa2e4d51fc9 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 26 Apr 2018 15:52:39 -0700 Subject: [PATCH 270/320] order item model tests --- app/models/order_item.rb | 7 --- test/fixtures/order_items.yml | 2 +- test/models/order_item_test.rb | 103 +++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 8 deletions(-) diff --git a/app/models/order_item.rb b/app/models/order_item.rb index 80c9c91bd9..dc316ecd9b 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -9,15 +9,8 @@ class OrderItem < ApplicationRecord numericality: true } - # validates_uniqueness_of :order_item, :scope => [:order_id, :product_id] - - # creates many order_item instances - # requires order_id and hash of product_id:quantity - # called in OrdersController - # to get an array you have to do a .where on the order item instance def self.make_order_items(id, hash) - order_items = [] hash.each do |key, value| diff --git a/test/fixtures/order_items.yml b/test/fixtures/order_items.yml index e3923c2b29..d6a63daa9b 100644 --- a/test/fixtures/order_items.yml +++ b/test/fixtures/order_items.yml @@ -3,7 +3,7 @@ # I am unsure of what to call the status fruit_salad: order: cart1 - product: cherry + product: cherries quantity: 3 status: paid diff --git a/test/models/order_item_test.rb b/test/models/order_item_test.rb index bed50fe8c1..301c75f4af 100644 --- a/test/models/order_item_test.rb +++ b/test/models/order_item_test.rb @@ -9,5 +9,108 @@ value(salad).must_be :valid? end + it "belongs to product" do + salad = order_items(:fruit_salad) + value(salad.product).must_be :valid? + salad.product.must_equal products(:cherries) + + end + + it "must have a product" do + salad = order_items(:fruit_salad) + products(:cherries).destroy + + salad.valid?.must_equal false + end + + it "belongs to order" do + salad = order_items(:fruit_salad) + value(salad.order).must_be :valid? + salad.order.must_equal orders(:cart1) + + end + + it "must have an order" do + salad = order_items(:fruit_salad) + orders(:cart1).destroy + + salad.valid?.must_equal false + end + + it "must have a product id" do + salad = order_items(:fruit_salad) + value(salad).must_be :valid? + + salad.product_id = nil + salad.valid?.must_equal false + end + + it "must have an order id" do + salad = order_items(:fruit_salad) + value(salad).must_be :valid? + + salad.order_id = nil + salad.valid?.must_equal false + end + + it "must have a quantity" do + salad = order_items(:fruit_salad) + value(salad).must_be :valid? + + salad.quantity = nil + salad.valid?.must_equal false + end + + it "must have a numerical quantity" do + salad = order_items(:fruit_salad) + value(salad).must_be :valid? + + salad.quantity = "quantity!" + salad.valid?.must_equal false + end + + # describe 'make order items' do + # + # it "" do + # hash = { products(:cherries).id => 3 } + # id = orders(:cart1).id + # + # order_item = OrderItem.make_order_items(id, hash) + # + # order_item.must_be_instance_of Hash + # end + + # end + + describe 'user_order_items' do + + it 'returns an array of order items' do + + items = OrderItem.user_order_items(users(:beyonce)) + + items.must_be_instance_of Array + + items.each do |i| + i.must_be_instance_of OrderItem + end + end + + it 'returns an array of order items belonging to one user' do + + items = OrderItem.user_order_items(users(:beyonce)) + items.each do |i| + i.user.must_be users(:beyonce) + end + end + + it 'returns an empty array if there are no order items for a user' do + + items = OrderItem.user_order_items(users(:hermonie)) + items.must_equal [] + + end + + end + end From 29d755ef77dcfe81776baa9b454c13c14c5b578e Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 26 Apr 2018 16:13:05 -0700 Subject: [PATCH 271/320] fixes rbga error --- app/assets/stylesheets/application.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 0d9cb540c9..485ee7e63f 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -83,7 +83,7 @@ h1 { } .button:hover{ - background-color: rgb(126, 15, 126, .5); + background-color: rgba(126, 15, 126, .5); /* background: rgba(0, 0, 0, 0); */ } From 059c34d649018ee65d4d8f52836b8f81930623f8 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 26 Apr 2018 16:19:50 -0700 Subject: [PATCH 272/320] cart and order now basket --- app/assets/stylesheets/application.css | 8 ++++---- app/controllers/sessions_controller.rb | 10 +++++----- app/views/layouts/application.html.erb | 3 +-- app/views/orders/index.html.erb | 2 +- app/views/products/show.html.erb | 2 +- app/views/sessions/index.html.erb | 8 ++++---- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 0d9cb540c9..f12a24a8dd 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -63,10 +63,10 @@ nav { justify-content: space-around; } -/* .right { */ - /* float: right; */ - /* margin: 1em; */ -/* } */ +/* .right { + float: right; + margin: 1em; + } */ h1 { diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 6b8187d448..0a71623ab6 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -17,7 +17,7 @@ def create if quantity.to_i <= 0 flash[:status] = :alert - flash[:result_text] = "Please add at least one product to the order" + flash[:result_text] = "Please add at least one product to the basket" redirect_to product_path(@product.id) return end @@ -29,7 +29,7 @@ def create if order_product_ids.include? product_id flash[:status] = :alert - flash[:result_text] = "That product is already in your Order" + flash[:result_text] = "That product is already in your Basket" redirect_to order_path else add_products_to_session(@product, params[:quantity]) @@ -48,7 +48,7 @@ def update product.update(quantity: update_quantity) session[:order].delete(product_id.to_s) flash[:status] = :success - flash[:result_text] = "Item removed from Order" + flash[:result_text] = "Item removed from Basket" redirect_to order_path elsif new_quantity < 0 flash[:status] = :alert @@ -77,7 +77,7 @@ def destroy session[:order] = {} flash[:status] = :success - flash[:result_text] = "Order cleared successfully" + flash[:result_text] = "Basket emptied successfully" redirect_to order_path end @@ -93,7 +93,7 @@ def add_products_to_session (product, quantity) session[:order].merge!(product.id => quantity.to_i) end flash[:status] = :success - flash[:result_text] = "Product added to order" + flash[:result_text] = "Product added to basket" redirect_to order_path else flash[:status] = :alert diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index b5a582f729..eb337c38c8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -23,7 +23,7 @@ - <% if session[:user_id] != nil && session[:user_id] != 1 %>
  • <%= link_to "My Profile", user_path(session[:user_id]), class: "button right" %>
  • diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb index 37633380be..c6d36f731e 100644 --- a/app/views/orders/index.html.erb +++ b/app/views/orders/index.html.erb @@ -1,6 +1,6 @@ -

    Shopping Cart

    +

    Fruit Basket

      <% @orders.each do |order| %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 474775a79d..ccb20f0c9d 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -22,7 +22,7 @@ <%= label_tag 'quantity' %> <%= number_field_tag 'quantity' %> <%= hidden_field_tag 'product_id', @product.id %> - <%= submit_tag "Add to Order", class: "button" %> + <%= submit_tag "Add to Basket", class: "button" %> <% end %> diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 344d83cce3..7444c7aebf 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,8 +1,8 @@ -

      Shopping Cart

      +

      Fruit Basket

      <% if session[:order].nil? || session[:order] == {} %> -

      No Items in the Order

      -

      <%= link_to "Add to Order", products_path, class: "button" %>

      +

      No Items in Basket

      +

      <%= link_to "Add to Basket", products_path, class: "button" %>

      <% else %> @@ -34,6 +34,6 @@

      Total: $<%= calculate_total %>

      <%= link_to "Checkout", new_order_path, class: "button" %> - <%= link_to "Clear Order", delete_order_path, method: :delete, data: { confirm: "Are you sure?" }, class: "button" %> + <%= link_to "Clear Basket", delete_order_path, method: :delete, data: { confirm: "Are you sure?" }, class: "button" %> <%= link_to "Continue Shopping", products_path, class: "button" %> <% end %> From a84673eeacb1d9b36b4c28d77d8bff0449336b25 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 26 Apr 2018 16:20:45 -0700 Subject: [PATCH 273/320] updates product show page --- app/views/products/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 474775a79d..cee98ab3a2 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -56,7 +56,7 @@ <% else %> -

      There are no reviews. Please add one!

      +

      There are no reviews.

      <% end %> From c87f206c44a70373daa6cc2d654be086379937db Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 26 Apr 2018 16:30:11 -0700 Subject: [PATCH 274/320] adds product c tests --- app/assets/stylesheets/orders.scss | 4 ++++ app/assets/stylesheets/users.scss | 2 +- test/controllers/products_controller_test.rb | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss index 3b0428a94e..8dd7536d3d 100644 --- a/app/assets/stylesheets/orders.scss +++ b/app/assets/stylesheets/orders.scss @@ -1,3 +1,7 @@ // Place all the styles related to the orders controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ + +#checkout-column { + padding-right: 10%; +} diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss index 10fc99c5e5..45d51261ed 100644 --- a/app/assets/stylesheets/users.scss +++ b/app/assets/stylesheets/users.scss @@ -14,7 +14,7 @@ } .label { - background-color: white; + background: rgba(245,243,244,0.1); color: purple; font-weight: bold; font-size: 1.1rem; diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 0a3de3eabd..189b84cac4 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -56,7 +56,7 @@ end describe 'create' do - it "creates a work with valid data for a real category" do + it "creates a product with valid data for a real category" do user = users(:beyonce) login(user) From 5eb106a97e61f4a47395de481ffa538e5cc363e4 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 26 Apr 2018 17:13:33 -0700 Subject: [PATCH 275/320] fixes some tests --- test/models/order_test.rb | 72 +++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/test/models/order_test.rb b/test/models/order_test.rb index 0d6156327a..2951b6d4c2 100644 --- a/test/models/order_test.rb +++ b/test/models/order_test.rb @@ -17,6 +17,12 @@ order.valid?.must_equal false end + it "must have a name with a length < 50" do + order.name = "jdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjd" + + order.valid?.must_equal false + end + it "must have a card number" do order.card_number = nil order.valid?.must_equal false @@ -36,25 +42,8 @@ order.valid?.must_equal false end - it "must have an integer date day" do - order.date_day = 5.8 - order.valid?.must_equal false - order.date_day = "ahfkj" - order.valid?.must_equal false - - end - - it "must have an integer date month" do - order.date_month = 5.8 - order.valid?.must_equal false - order.date_month = "ahfkj" - order.valid?.must_equal false - end - - it "must have an integer date year" do - order.date_year = 5.8 - order.valid?.must_equal false - order.date_year = "ahfkj" + it "must have a date month" do + order.date_month = nil order.valid?.must_equal false end @@ -102,13 +91,7 @@ order.valid?.must_equal false end - it "must have at least one order item" do - order.order_items = [] - order.valid?.must_equal false - end - it "can have many order items" do - order.order_items.count.must_equal 2 end @@ -116,4 +99,43 @@ order.user = nil order.valid?.must_equal false end + + describe 'order_status' do + + it 'returns a status' do + statuses = ['complete', 'paid', 'pending'] + + order = orders(:cart2) + status = Order.order_status(order) + + statuses.include?(status).must_equal true + end + + it 'returns pending status if all order items are paid' do + + order = orders(:cart2) + status = Order.order_status(order) + + status.must_equal 'pending' + end + + it 'returns pending status if some order items are paid and some are complete' do + + order = orders(:cart2) + + order_items(:watermelon_salad).status = 'complete' + status = Order.order_status(order) + + status.must_equal 'pending' + end + + it 'returns complete status if all order items are complete' do + + order = orders(:cart2) + order.order_items.each do |i| + i.status = 'complete' + end + Order.order_status(order).must_equal 'complete' + end + end end From 4a739ebf653211ce3d921769f7470f9b484a3a77 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 26 Apr 2018 17:20:50 -0700 Subject: [PATCH 276/320] failing attempt at random merchant pic from array of constants --- app/models/user.rb | 2 ++ app/views/users/show.html.erb | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/app/models/user.rb b/app/models/user.rb index 01325ec923..b2022d051b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,4 +10,6 @@ def self.build_from_github(auth_hash) return User.new(uid: auth_hash[:uid], provider: auth_hash[:provider], email: auth_hash[:info][:email], name: auth_hash[:info][:nickname]) end +MERCHANT_PICS = ['https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-4.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-26.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-27.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-28.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-29.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-30.jpg' ] + end diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 7fb2fc7c7e..837c36f9e2 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -14,4 +14,8 @@ <%= link_to "My Products", user_products_path(@user.id), class: "button" %> + +
      + <%= imgage_tag(MERCHANT_PICS.sample(1), alt="Merchant profile picture")%> +
      From b26fd82eeb7a8a6a25d6d7df3399f24b97377ace Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 26 Apr 2018 17:20:56 -0700 Subject: [PATCH 277/320] merchants can only view their products order details page containing their products --- app/controllers/orders_controller.rb | 21 +++++++ app/views/order_items/index.html.erb | 6 +- app/views/orders/merchant_order_show.html.erb | 62 +++++++++++++++++++ config/routes.rb | 3 + 4 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 app/views/orders/merchant_order_show.html.erb diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 80b4e2ef02..8d779d184d 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -74,6 +74,27 @@ def create session[:order] = {} end + def merchant_order_show + @order = Order.find_by(id: params[:id]) + @user = User.find_by(uid: session['uid']) + + if @user + @order_items = OrderItem.where(order_id: @order.id) + + else + product_ids = @user.products.map{ |i| i.id } + @order_items = [] + array = OrderItem.where(order_id: @order.id) + + array.each do |item| + if product_ids.include?(item.product.id) + @order_items << item + end + end + + end + end + private def order_params params.require(:order).permit(:user_id, :status, :email, :street, :city, :state, :zip, :card_number, :date_year, :date_month, :date_day, :cvv, :name) diff --git a/app/views/order_items/index.html.erb b/app/views/order_items/index.html.erb index 4e95f14b58..ff9623f9cd 100644 --- a/app/views/order_items/index.html.erb +++ b/app/views/order_items/index.html.erb @@ -37,7 +37,7 @@ <%= item.product.name %> <%= item.quantity %> - <%= link_to "Order \# #{item.order.id}", order_details_path(item.order.id) %> + <%= link_to "Order \# #{item.order.id}", sold_order_path(item.order.id) %> $<%= sprintf('%.2f', (item.product.price) * item.quantity) %> <%= link_to "Change Status", edit_order_item_path(item.id), class: 'button'%> @@ -65,7 +65,7 @@ <%= item.product.name %> <%= item.quantity %> - <%= link_to "Order \# #{item.order.id}", order_details_path(item.order.id) %> + <%= link_to "Order \# #{item.order.id}", sold_order_path(item.order.id) %> <%= sprintf('%.2f', (item.product.price) * item.quantity) %> <%= link_to "Change Status", edit_order_item_path(item.id), class: 'button' %> @@ -90,7 +90,7 @@ <%= item.product.name %> <%= item.quantity %> - <%= link_to "Order \# #{item.order.id}", order_details_path(item.order.id) %> + <%= link_to "Order \# #{item.order.id}", sold_order_path(item.order.id) %> <% end %> <% end %> diff --git a/app/views/orders/merchant_order_show.html.erb b/app/views/orders/merchant_order_show.html.erb new file mode 100644 index 0000000000..ac5848a0a7 --- /dev/null +++ b/app/views/orders/merchant_order_show.html.erb @@ -0,0 +1,62 @@ +

      Thank you for shopping on Fruetsy!

      +

      Order Confirmation #: <%= @order.id %>

      + + + + + + + + + + + + + + <% total = 0 %> + <% @order_items.each do |order_item| %> + <% @status = "paid" %> + + <% product = Product.find_by(id: order_item.product_id) %> + <% subtotal = (order_item.quantity.to_i * product.price) %> + <% subtotal = sprintf('%.2f', (order_item.quantity.to_i * product.price)).to_f %> + + <% if order_item.status == nil || order_item.status == "pending" %> + <% @status = order_item.status %> + <% end %> + + + + <% if product.user_id == session[:user_id] %> + + + + + + <% end %> + + + <% end %> +
      Order Confirmation page
      ProductPriceQuantitySubtotalOrder Item Status
      <%= link_to product.name, product_path(product.id) %>$<%= sprintf('%.2f', order_item.product.price) %><%= order_item.quantity %>$<%= sprintf('%.2f', subtotal) %><%= order_item.status %>
      + +
        + +
      • Name: <%= @order.name %>
      • +
      • Email: <%= @order.email %>
      • +
      • + Address: <%= @order.street %>, + <%= @order.city %>, + <%= @order.state %> + <%= @order.zip %> +
      • +
      • Card: ************<%= @order.card_number.to_s.last(4).to_i %>
      • +
      • Exp: <%= "#{@order.date_month}" %>
      • +
      • CVV: <%= @order.cvv %>
      • +
        +
      • Purchased On: <%= render_date(@order.created_at) %>
      • + <% order_status = Order.order_status(@order) %> + <% if order_status == "complete" %> + <% @order.status = "complete" %> + <% end %> +
      • Order Status: <%= order_status %>
      • +
      diff --git a/config/routes.rb b/config/routes.rb index 59ccb85658..5d1035cd5f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,6 +6,9 @@ get '/auth/github', as: 'github_login' delete '/logout', to: "users#destroy", as: "logout" + # this is a new route to limit view of order details for merchant + get '/sold_order/:id' , to: 'orders#merchant_order_show', as: 'sold_order' + get '/order' , to: 'sessions#index', as: 'order' post '/order' , to: 'sessions#create', as: 'add_to_order' patch '/order' , to: 'sessions#update', as: 'update_order' From 967f3b3a76f5ae1d0e87e83838fb5c2e876fdc0e Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Thu, 26 Apr 2018 17:54:40 -0700 Subject: [PATCH 278/320] bit of tests --- app/views/order_items/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/order_items/index.html.erb b/app/views/order_items/index.html.erb index 4e95f14b58..2fa836391c 100644 --- a/app/views/order_items/index.html.erb +++ b/app/views/order_items/index.html.erb @@ -14,7 +14,7 @@

      Order Revenue

      Paid: $<%= sprintf('%.2f', @paid_items.map { |i| i.product.price * i.quantity }.sum) %>

      Complete: $<%= sprintf('%.2f', @completed_items.map { |i| i.product.price * i.quantity }.sum) %>

      -

      Total: $<%= sprintf('%.2f', @paid_items.map { |i| i.product.price * i.quantity }.sum + @completed_items.map { |i| i.product.price * i.quantity }.sum + @cancelled_items.map { |i| i.product.price * i.quantity }.sum) %>

      +

      Total: $<%= sprintf('%.2f', @paid_items.map { |i| i.product.price * i.quantity }.sum + @completed_items.map { |i| i.product.price * i.quantity }.sum) %>

      From 08a99369eaca0a9c00a66072a4f76dcc4ff1bb53 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Thu, 26 Apr 2018 19:20:41 -0700 Subject: [PATCH 279/320] seeds categories for products --- app/assets/stylesheets/application.css | 7 ++++ app/views/categories/show.html.erb | 24 ++++++------ db/ProductSeed2.csv | 22 +++++++++++ db/seeds.rb | 51 ++++++++++++++++---------- 4 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 db/ProductSeed2.csv diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 6555c340e1..95b5692e70 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -111,6 +111,13 @@ ul li { height: fit-content; } +.category_show { + display: flex; + flex-wrap: wrap; + flex-direction: row; + /* height: fit-content; */ +} + .frontpage { display: grid; grid-template-columns: 1fr 1fr 1fr; diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 1a1ca32f13..179495122d 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -1,13 +1,13 @@

      <%= @category.name %>

      -
        - <% @category.products.each do |product| %> -
      • - fruit! - <%= link_to product.name, product_path(product.id) %> - - $<%= sprintf('%.2f', product.price) %> - - <%= product.description %> -
      • - <% end %> -
      +
      +
        + <% @category.products.each do |product| %> +
      • + fruit! + <%= link_to product.name, product_path(product.id) %> + $<%= sprintf('%.2f', product.price) %> + <%= product.description %> +
      • + <% end %> +
      +
      diff --git a/db/ProductSeed2.csv b/db/ProductSeed2.csv new file mode 100644 index 0000000000..a65fe7def9 --- /dev/null +++ b/db/ProductSeed2.csv @@ -0,0 +1,22 @@ +Product,price,description,user_id,quantity ,category,image +Apple,1.00,Honey Crisp,2,30,Pome,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Banana,0.25,Perfectly ripe,2,50,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Rainier Cherries,2.99,Sweet and juicy,2,30,Bunches,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Green Grapes,2.00," +A great energy source because of their natural fruit sugar content",2,300,Bunches,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Grapefruit,1.00,"One of the largest citrus fruit, grapefruits are a cross between the pomelo and the shaddock. High in vitamin C, grapefruits are best eaten raw, a traditional breakfast fruit. The best way to eat is to cut them in half and scoop out the flesh with a spoon.",2,10,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Kumquat,0.50,"The name means ""golden orange"" in Chinese. Kumquats are often preserved in sweet syrup and used for marmalade and garnishes, but fresh ones are delicious in fruit salads or for eating just as they are.",2,80,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Lemon,0.25,"Rarely eaten on its own, lemons are an indispensable ingredient in the kitchen. Lemon juice can be used instead of vinegar in sauces, for seasoning in vinaigrette and as instant dressing for fish and shellfish. The best way to store lemon is in the vegetable crisper in the fridge you can put lemons in fruit bowl for a shorter, check them often - if one starts to spoil, the rest will quickly follow.",2,15,Citrus,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Pineapple,3.00,"Derived from the Spanish word 'pina' meaning pine cone. Pineapples have a juicy, sweet-but sometimes slightly tart-fragrant flavour. They are best eaten fresh, serve pineapple flesh in slices, wedges or chunks. It is also available in cans, dried and glace. A good source of vitamin C.",2,14,Pome,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Plums,1.25,"Plums contain more antioxidant than any other fruit. Plums are delicate so make sure that the one you buy are unblemished, and they should be plump and firm. The small sugar plum is dried to make prunes. Delicious stewed, plums are also ideal for making chutneys.",2,16,Pits,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Star Apple,1.15,"The star apple fruits are green to purple with a smooth skin. When sliced horizontally the flesh is translucent white with the seeds forming a star shape. It is best eaten ripe, scooped straight from the skin. It is ripe when soft and should be eaten immediately, but it is still alright to refrigerate for a few days.",2,45,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Strawberry,2.78,"A unique fruit, the seeds grow around the outside of the fruit rather than inside it. Comes in many different sizes, colours and shapes, ranging from cone-like, to oval, or heart-shaped. Best to eat on their own or with natural yoghurt. Use strawberries in desserts, fruit salads, preserves, or in milkshakes.",3,26,Edible Skin,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Watermelon ,5.00,"The high water content of watermelons means that they are low in calories. They contain some vitamins B and C. Watermelon is excellent juiced, chopped up into a fruit salad, or just eaten in chunky slices.",3,43,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Tamarillo,1.65,"these are related to tomatoes and sometimes called ""tree tomatoes."" They are the size of an egg tomato, with dark red skin. The fruit has a strong, sweet flavour that makes it suitable for both sweet or savoury dishes. It can also be used in jams, chutneys, and sorbets.",3,12,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Rambutan,3.40,"The rambutan fruit grows in clusters, with a deep crimson outer skin. The flesh is translucent, and the pale seed is edible when young. Related to lychees and are sometimes known as ""hairy lychees"".(about 5cm / 2inches in diameter) and look quite different but have a similar texture. They can be added to salads, made into jams or jellies, but they are best eaten on their own.",3,3,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Peach,2.25,"Or pawpaw, a large tropical fruit whose ripe flesh can be juicy, creamy, orange-red, or yellow. In the centre is a mass of large peppery black seeds, which are edible and sometimes crushed and used as a spice. Ripe papaya is eaten as a breakfast fruit or as a dessert. It can also be pureed for ice cream, sorbets and iced drinks.",3,9,Pits,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Fig,0.50,"Figs are oval or pear-shaped and can be eaten fresh or dried. They are well known for their laxative and digestive properties. Their high, natural sugar content makes them the sweetest of all fruits. The flavour varies, depending on where they were grown and how ripe they are.",4,24,Edible Skin,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Lime,0.25,"Limes are only green because they are picked unripe but if left to ripen they turn yellow. Limes can be used like lemons but as juice, it is more acidic, so usually less is needed. To make the juice flow more, you can microwave the limes for 2-3 seconds before squeezing. Mostly used in drinks (lime cordials) and cooking.",4,65,Citrus,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Passionfruit,3.00,"The most popular variety is the purple passionfruit about the size of a chicken egg. It has a highly fragrant, sweet, but slightly tart, tasting fruit that can be spooned out and eaten fresh or added to fruit salad, pavlova, and it makes a very popular drink, ice cream and sorbets and a flavouring for all kinds of desserts.",4,43,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Nectarine,1.25,"The nectarine flesh is rich, sweet and juicy and is well suited for eating fresh and for using in ice cream, pies and fruit salads. Colour ranges from silvery white or yellowy orange to pinkish red. The white-fleshed varieties are considered the best and usually the most expensive. Nectarines are often described as a cross between a peach and a plum, but nectarines are actually a variety of smooth-skinned peach.",4,2,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Mangosteen,1.15,"Contrary to its name, the mangosteen doesn't resemble or taste like the mango. It resemble an apple, having a short stem and four thick leaf-like bracts which form a rosette encasing the brownish-purple fruit.",4,7,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg \ No newline at end of file diff --git a/db/seeds.rb b/db/seeds.rb index 80f457ad18..71111e35a2 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -28,7 +28,7 @@ end end -PRODUCT_FILE = Rails.root.join('db', 'ProductSeed.csv') +PRODUCT_FILE = Rails.root.join('db', 'ProductSeed2.csv') puts "Loading product data from #{PRODUCT_FILE}" product_failures = [] @@ -39,9 +39,22 @@ product.description = row['description'] product.image = row['image'] product.user_id = row['user_id'] - # product.quantity = row['quantity'] product.quantity = rand(1..50) + # add category to product + if row['category'] != "-" + category = Category.find_by(name: row['category']) + if category + product.categories << category + else + category = Category.new + category.name = row['category'] + category.save + puts "Category created: #{category.inspect}" + product.categories << category + end + end + successful = product.save if !successful product_failures << product @@ -51,6 +64,23 @@ end end +# CATEGORY_FILE = Rails.root.join('db', 'Categoryseed.csv') +# puts "Loading category data from #{CATEGORY_FILE}" +# +# category_failures = [] +# CSV.foreach(CATEGORY_FILE, :headers => true) do |row| +# category = Category.new +# category.name = row['Category'] +# +# successful = category.save +# if !successful +# category_failures << category +# puts "Failed to save category: #{category.inspect}" +# else +# puts "Created category: #{category.inspect}" +# end +# end + REVIEW_FILE = Rails.root.join('db', 'ReviewsSeed.csv') puts "Loading review data from #{REVIEW_FILE}" @@ -71,23 +101,6 @@ end end -CATEGORY_FILE = Rails.root.join('db', 'Categoryseed.csv') -puts "Loading category data from #{CATEGORY_FILE}" - -category_failures = [] -CSV.foreach(CATEGORY_FILE, :headers => true) do |row| - category = Category.new - category.name = row['Category'] - - successful = category.save - if !successful - category_failures << category - puts "Failed to save category: #{category.inspect}" - else - puts "Created category: #{category.inspect}" - end -end - ORDER_FILE = Rails.root.join('db', 'OrdersSeed.csv') puts "Loading order data from #{ORDER_FILE}" From 07d9ba80a6c3b3d4b45ec1cebf92dc08c08b3206 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 26 Apr 2018 20:51:42 -0700 Subject: [PATCH 280/320] validation updates --- app/controllers/orders_controller.rb | 1 + app/models/product.rb | 14 +++----------- app/models/user.rb | 2 ++ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 8d779d184d..42c30f44ed 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,4 +1,5 @@ class OrdersController < ApplicationController +before_action :account_views, only: [:edit] def index @orders = Order.all diff --git a/app/models/product.rb b/app/models/product.rb index 73eb208658..a08a0be61a 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -4,11 +4,12 @@ class Product < ApplicationRecord has_many :reviews has_many :order_items - accepts_nested_attributes_for :categories, reject_if: proc { |attributes| attributes['category_name'].blank?} + accepts_nested_attributes_for :categories, reject_if: proc { |attributes| attributes['category_name'].blank?} validates :name, { presence: true, - length: { minimum: 1 } + length: { minimum: 1 }, + uniquness: true } validates :price, { @@ -16,13 +17,4 @@ class Product < ApplicationRecord numericality: { greater_than: 0 } } - # def categories_attributes=(category_attributes) - # if !category_attributes.nil? - # category_attributes.values.each do |category_attribute| - # category = Category.find_or_create_by(category_attribute) - # self.categories << category - # end - # end - # end - end diff --git a/app/models/user.rb b/app/models/user.rb index 01325ec923..37326f4284 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,4 +10,6 @@ def self.build_from_github(auth_hash) return User.new(uid: auth_hash[:uid], provider: auth_hash[:provider], email: auth_hash[:info][:email], name: auth_hash[:info][:nickname]) end +MERCHANT_PICS = ['https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-4.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-26.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-27.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-28.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-29.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-30.jpg'] + end From b55ba34e3500bd95ab06bc26dddbe5bbdddb29e2 Mon Sep 17 00:00:00 2001 From: marikoja Date: Thu, 26 Apr 2018 21:19:02 -0700 Subject: [PATCH 281/320] merchant images now working --- app/assets/stylesheets/application.css | 11 +++++++++++ app/models/product.rb | 11 +---------- app/models/user.rb | 2 +- app/views/users/show.html.erb | 10 ++++++---- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 6555c340e1..70f18acbd5 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -147,3 +147,14 @@ footer p { a { color: purple; } + +.merchant p { + display: flex; + flex-direction: column; +} +.merchant { + display: flex; + /* flex-direction: column; */ + justify-content: center; + align-items: flex-end; +} diff --git a/app/models/product.rb b/app/models/product.rb index 73eb208658..75daaab92b 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -4,7 +4,7 @@ class Product < ApplicationRecord has_many :reviews has_many :order_items - accepts_nested_attributes_for :categories, reject_if: proc { |attributes| attributes['category_name'].blank?} + accepts_nested_attributes_for :categories, reject_if: proc { |attributes| attributes['category_name'].blank?} validates :name, { presence: true, @@ -16,13 +16,4 @@ class Product < ApplicationRecord numericality: { greater_than: 0 } } - # def categories_attributes=(category_attributes) - # if !category_attributes.nil? - # category_attributes.values.each do |category_attribute| - # category = Category.find_or_create_by(category_attribute) - # self.categories << category - # end - # end - # end - end diff --git a/app/models/user.rb b/app/models/user.rb index b2022d051b..16bbfc16a7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,6 +10,6 @@ def self.build_from_github(auth_hash) return User.new(uid: auth_hash[:uid], provider: auth_hash[:provider], email: auth_hash[:info][:email], name: auth_hash[:info][:nickname]) end -MERCHANT_PICS = ['https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-4.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-26.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-27.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-28.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-29.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-30.jpg' ] + MERCHANT_PICS = ['https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-4.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-26.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-27.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-28.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-29.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-30.jpg'] end diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 837c36f9e2..3940b4bd9f 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -2,11 +2,13 @@

      Merchant Profile

      -
      +

      Name: <%= @user.name %>

      +
      +

      Email: <%= @user.email %>

      -
      +
      <%= link_to "Edit Profile", edit_user_path(@user.id), class: "button" %> @@ -15,7 +17,7 @@ <%= link_to "My Products", user_products_path(@user.id), class: "button" %>
      -
      - <%= imgage_tag(MERCHANT_PICS.sample(1), alt="Merchant profile picture")%> +
      + <%= image_tag(User::MERCHANT_PICS.sample, :alt => "Merchant profile picture", :size => "260x180")%>
      From 69542f4fd4792dc86b8339e473d20240b11b4025 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Thu, 26 Apr 2018 23:18:25 -0700 Subject: [PATCH 282/320] add outline for order controller tests, merchant_order_show page test failed and passing, blocked non merchants from accessing product edit and order pages --- app/controllers/order_items_controller.rb | 8 +++++ app/controllers/orders_controller.rb | 36 +++++++++++++--------- app/models/product.rb | 13 +++++--- test/controllers/orders_controller_test.rb | 28 +++++++++++++---- 4 files changed, 59 insertions(+), 26 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index ff14760b43..57df6ed713 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -19,10 +19,18 @@ def index def edit @order_item = OrderItem.find_by(id: params[:id]) + @order = Order.find_by(id: params[:id]) + @user = User.find_by(uid: session['uid']) + if @order_item.nil? flash[:status] = :alert flash[:result_text] = "That order_item does not exist" redirect_to root_path + + elsif @user.id == nil || @user.id == 1 + flash[:status] = :failure + flash[:result_text] = "You are not a merchant for this product" + redirect_to :root end end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 42c30f44ed..67146ab90d 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -1,5 +1,5 @@ class OrdersController < ApplicationController -before_action :account_views, only: [:edit] + before_action :account_views, only: [:edit] def index @orders = Order.all @@ -79,25 +79,31 @@ def merchant_order_show @order = Order.find_by(id: params[:id]) @user = User.find_by(uid: session['uid']) - if @user + if @user.id != nil && @user.id != 1 @order_items = OrderItem.where(order_id: @order.id) else - product_ids = @user.products.map{ |i| i.id } - @order_items = [] - array = OrderItem.where(order_id: @order.id) - - array.each do |item| - if product_ids.include?(item.product.id) - @order_items << item - end - end + # i want to remove this code because it should raise an error if the user is not the same as the visitor + + # product_ids = @user.products.map{ |i| i.id } + # @order_items = [] + # array = OrderItem.where(order_id: @order.id) + # + # array.each do |item| + # if product_ids.include?(item.product.id) + # @order_items << item + # end + # end + flash[:status] = :failure + flash[:result_text] = "You are not a merchant for this order" + redirect_to :root end end - private - def order_params - params.require(:order).permit(:user_id, :status, :email, :street, :city, :state, :zip, :card_number, :date_year, :date_month, :date_day, :cvv, :name) - end + +private +def order_params + params.require(:order).permit(:user_id, :status, :email, :street, :city, :state, :zip, :card_number, :date_year, :date_month, :date_day, :cvv, :name) +end end diff --git a/app/models/product.rb b/app/models/product.rb index a08a0be61a..cf03dc1a14 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -4,13 +4,16 @@ class Product < ApplicationRecord has_many :reviews has_many :order_items + accepts_nested_attributes_for :categories, reject_if: proc { |attributes| attributes['category_name'].blank?} - validates :name, { - presence: true, - length: { minimum: 1 }, - uniquness: true - } +# I removed this validation because it messed with my duplicate orders. +# I think this validation has to be checked for in products create method + # validates :name, { + # presence: true, + # length: { minimum: 1 }, + # uniquness: true + # } validates :price, { presence: true, diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index cffbbccca3..f69640d954 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -162,11 +162,27 @@ end - # describe "show" do - # it "should get show" do - # get order_details_path(@test_order.id) - # value(response).must_be :success? - # end - # end + describe "show" do + it "should get show" do + get order_details_path(@test_order.id) + value(response).must_be :success? + end + end + + describe "merchant_order_show" do + it "should get order show page for merchants order_items and their order details" do + get sold_order_path(@test_order.id) + value(response).must_be :success? + end + + it "valid data returns an array of order_items of products made by merchant" do + + end + + + it "invalid data returns an empty array" do + + end + end end From 07fa8d0611c3a76cd78853a41349b31ea731fe8c Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 00:06:05 -0700 Subject: [PATCH 283/320] updates image tags --- app/assets/stylesheets/application.css | 6 +----- app/models/product.rb | 2 +- app/views/categories/show.html.erb | 2 +- app/views/products/index.html.erb | 2 +- app/views/products/root.html.erb | 3 ++- app/views/products/show.html.erb | 5 +++-- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 95b5692e70..40f534d7c2 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -131,11 +131,7 @@ main { } footer { - /* background-image: url("https://spindriftfresh.com/wp-content/uploads/2017/12/fruit-header-1.jpg"); */ - /* background-size: cover; */ - /* transform: rotate(180deg); */ - /* text-align: center; */ - /* position: fixed; */ + left: 0; bottom: 0; width: 100%; diff --git a/app/models/product.rb b/app/models/product.rb index a08a0be61a..281a2ca9be 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -9,7 +9,7 @@ class Product < ApplicationRecord validates :name, { presence: true, length: { minimum: 1 }, - uniquness: true + uniqueness: true } validates :price, { diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 179495122d..32823472c5 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -3,7 +3,7 @@
        <% @category.products.each do |product| %>
      • - fruit! + <%= image_tag(product.image, :alt => "fruit!") %> <%= link_to product.name, product_path(product.id) %> $<%= sprintf('%.2f', product.price) %> <%= product.description %> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 1450fc0765..8c2e073eb1 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -14,7 +14,7 @@
          <% products.each do |product|%>
        • - fruit! + <%= image_tag(product.image, :alt => "fruit!", :class => "thumbnail") %> <%= link_to product.name.capitalize, product_path(product[:id]) %> diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 59fde24d1d..98df423be1 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -3,7 +3,8 @@
            <% @products.sample(9).each do |product|%>
          • - fruit! + <%= image_tag(product.image, :alt => "fruit!", :class => "thumbnail") %> + <%= link_to product.name, product_path(product[:id]) %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 6859a90b90..4c0bdc15ad 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,7 +2,7 @@
            - fruit! + <%= image_tag(@product.image, :alt => "fruit!", :class => "thumbnail") %>
            Price: $<%= sprintf('%.2f', @product.price) %>
            @@ -47,7 +47,8 @@ <% review.rating.times do %> - fruit rating + + <%= image_tag("https://4.bp.blogspot.com/-xMWFXKu-oRE/WThKE4gVoWI/AAAAAAAACg4/1V6fMZoa6jk0WbFholbMH3PlYg8wSAxGQCLcB/s1600/banana-fruit-icons_www.fruitsname.com_256x256-3.png", :alt => "fruit rating", width:'55') %> <% end %> <%= review.text_review %> From e786535164509bde6b11ff605c599303867bbd59 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 00:32:30 -0700 Subject: [PATCH 284/320] test for merchant sold items page working ish...fix loops for end/unepected end --- test/controllers/orders_controller_test.rb | 250 ++++++++++++--------- 1 file changed, 139 insertions(+), 111 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index f69640d954..a8166914ab 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -5,6 +5,7 @@ @test_user = users(:beyonce) @test_order = orders(:cart1) @test_product = products(:cherries) + # @test_order_item = order_items(:fruit_salad) end describe "index" do @@ -37,11 +38,11 @@ login(user) post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} + :quantity => 2} - order_count = Order.count + order_count = Order.count - post orders_path, params: { order: + post orders_path, params: { order: { user: user , status: "paid" , name: user.name , @@ -56,133 +57,160 @@ date_day: 3 , cvv: 123 } - } - must_respond_with :redirect - - must_redirect_to order_details_path(Order.last.id) - - Order.count.must_equal (order_count + 1) - end - - it "valid data should create a new order when no user is logged in" do - user = User.first - user.id = 1 - user.save - - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} - - order_count = Order.count - - post orders_path, params: { order: - { user: user , - status: "paid" , - name: user.name , - card_number: 1234123412341234 , - email: user.email , - street: "malden" , - city: "seattle" , - state: "wa" , - zip: 12345 , - date_year: 19 , - date_month: 5 , - date_day: 3 , - cvv: 123 + } + must_respond_with :redirect + + must_redirect_to order_details_path(Order.last.id) + + Order.count.must_equal (order_count + 1) + end + + it "valid data should create a new order when no user is logged in" do + user = User.first + user.id = 1 + user.save + + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + + order_count = Order.count + + post orders_path, params: { order: + { user: user , + status: "paid" , + name: user.name , + card_number: 1234123412341234 , + email: user.email , + street: "malden" , + city: "seattle" , + state: "wa" , + zip: 12345 , + date_year: 19 , + date_month: 5 , + date_day: 3 , + cvv: 123 + } } - } - must_respond_with :redirect - - must_redirect_to order_details_path(Order.last.id) - - Order.count.must_equal (order_count + 1) + must_respond_with :redirect + + must_redirect_to order_details_path(Order.last.id) + + Order.count.must_equal (order_count + 1) + end + + it "invalid data should redirect to order new page if user logged in" do + user = users(:beyonce) + login(user) + + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + + order_count = Order.count + + post orders_path, params: { order: + { user: user , + status: "paid" , + name: user.name , + card_number: nil , + email: user.email , + street: "malden" , + city: "seattle" , + state: "wa" , + zip: 12345 , + date_year: 19 , + date_month: 5 , + date_day: 3 , + cvv: 123 + } + } + must_respond_with :bad_request + + Order.count.must_equal order_count + + end + + it "invalid data should redirect to order new page if no user logged in" do + + user = User.first + user.id = 1 + user.save + + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + + order_count = Order.count + + post orders_path, params: { order: + { user: user , + status: "paid" , + name: user.name , + card_number: nil , + email: user.email , + street: "malden" , + city: "seattle" , + state: "wa" , + zip: 12345 , + date_year: 19 , + date_month: 5 , + date_day: 3 , + cvv: 123 + } + } + must_respond_with :bad_request + + Order.count.must_equal order_count + end + + end + end + end end - it "invalid data should redirect to order new page if user logged in" do - user = users(:beyonce) - login(user) - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} + describe "show" do + it "should get show" do + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} - order_count = Order.count + get order_details_path(@test_order.id) + value(response).must_be :success? - post orders_path, params: { order: - { user: user , - status: "paid" , - name: user.name , - card_number: nil , - email: user.email , - street: "malden" , - city: "seattle" , - state: "wa" , - zip: 12345 , - date_year: 19 , - date_month: 5 , - date_day: 3 , - cvv: 123 - } - } - must_respond_with :bad_request + end + end - Order.count.must_equal order_count + describe "merchant_order_show" do - end + it "should get order show page for merchants order_items and their order details" do + test_user_hash = + { + :name => @test_user.name, + :email => @test_user.email, + :uid => @test_user.uid, + :provider => @test_user.provider + } + user = User.new(test_user_hash) + user.save - it "invalid data should redirect to order new page if no user logged in" do + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) - user = User.first - user.id = 1 - user.save + get auth_callback_path(:github) - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} + get sold_order_path(@test_order.id), params: { :id => @test_user.id} - order_count = Order.count + value(response).must_be :success? + end - post orders_path, params: { order: - { user: user , - status: "paid" , - name: user.name , - card_number: nil , - email: user.email , - street: "malden" , - city: "seattle" , - state: "wa" , - zip: 12345 , - date_year: 19 , - date_month: 5 , - date_day: 3 , - cvv: 123 - } - } - must_respond_with :bad_request - - Order.count.must_equal order_count - end - - end + it "valid data returns an array of order_items of products made by merchant" do - describe "show" do - it "should get show" do - get order_details_path(@test_order.id) - value(response).must_be :success? - end - end - - describe "merchant_order_show" do - it "should get order show page for merchants order_items and their order details" do - get sold_order_path(@test_order.id) - value(response).must_be :success? - end + end - it "valid data returns an array of order_items of products made by merchant" do - end + it "invalid data returns an empty array" do + end - it "invalid data returns an empty array" do + end end end - end From f5def3bf4ec739af1a9485ad893008e903b37746 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 09:03:11 -0700 Subject: [PATCH 285/320] test merchant order passes for valid input --- test/controllers/orders_controller_test.rb | 287 +++++++++------------ 1 file changed, 127 insertions(+), 160 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index a8166914ab..cc72c73bbb 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -40,177 +40,144 @@ post add_to_order_path, params: { :product_id => products(:cherries).id, :quantity => 2} - order_count = Order.count - - post orders_path, params: { order: - { user: user , - status: "paid" , - name: user.name , - card_number: 1234123412341234 , - email: user.email , - street: "malden" , - city: "seattle" , - state: "wa" , - zip: 12345 , - date_year: 19 , - date_month: 5 , - date_day: 3 , - cvv: 123 + order_count = Order.count + + post orders_path, params: { order: + { user: user , + status: "paid" , + name: user.name , + card_number: 1234123412341234 , + email: user.email , + street: "malden" , + city: "seattle" , + state: "wa" , + zip: 12345 , + date_year: 19 , + date_month: 5 , + date_day: 3 , + cvv: 123 } } - must_respond_with :redirect - - must_redirect_to order_details_path(Order.last.id) - - Order.count.must_equal (order_count + 1) - end - - it "valid data should create a new order when no user is logged in" do - user = User.first - user.id = 1 - user.save - - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} - - order_count = Order.count - - post orders_path, params: { order: - { user: user , - status: "paid" , - name: user.name , - card_number: 1234123412341234 , - email: user.email , - street: "malden" , - city: "seattle" , - state: "wa" , - zip: 12345 , - date_year: 19 , - date_month: 5 , - date_day: 3 , - cvv: 123 - } - } - must_respond_with :redirect - - must_redirect_to order_details_path(Order.last.id) - - Order.count.must_equal (order_count + 1) - end - - it "invalid data should redirect to order new page if user logged in" do - user = users(:beyonce) - login(user) - - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} - - order_count = Order.count - - post orders_path, params: { order: - { user: user , - status: "paid" , - name: user.name , - card_number: nil , - email: user.email , - street: "malden" , - city: "seattle" , - state: "wa" , - zip: 12345 , - date_year: 19 , - date_month: 5 , - date_day: 3 , - cvv: 123 - } - } - must_respond_with :bad_request - - Order.count.must_equal order_count - - end - - it "invalid data should redirect to order new page if no user logged in" do - - user = User.first - user.id = 1 - user.save - - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} - - order_count = Order.count - - post orders_path, params: { order: - { user: user , - status: "paid" , - name: user.name , - card_number: nil , - email: user.email , - street: "malden" , - city: "seattle" , - state: "wa" , - zip: 12345 , - date_year: 19 , - date_month: 5 , - date_day: 3 , - cvv: 123 - } - } - must_respond_with :bad_request - - Order.count.must_equal order_count - end - - end - end - end - end - - - describe "show" do - it "should get show" do - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} - - get order_details_path(@test_order.id) - value(response).must_be :success? - - end - end - - describe "merchant_order_show" do - - it "should get order show page for merchants order_items and their order details" do - test_user_hash = - { - :name => @test_user.name, - :email => @test_user.email, - :uid => @test_user.uid, - :provider => @test_user.provider - } - user = User.new(test_user_hash) - user.save + must_respond_with :redirect - OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + must_redirect_to order_details_path(Order.last.id) - get auth_callback_path(:github) - - get sold_order_path(@test_order.id), params: { :id => @test_user.id} - - value(response).must_be :success? - end + Order.count.must_equal (order_count + 1) + end - it "valid data returns an array of order_items of products made by merchant" do + it "valid data should create a new order when no user is logged in" do + user = User.first + user.id = 1 + user.save + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + order_count = Order.count + post orders_path, params: { order: + { user: user , + status: "paid" , + name: user.name , + card_number: 1234123412341234 , + email: user.email , + street: "malden" , + city: "seattle" , + state: "wa" , + zip: 12345 , + date_year: 19 , + date_month: 5 , + date_day: 3 , + cvv: 123 + } + } + must_respond_with :redirect + must_redirect_to order_details_path(Order.last.id) + Order.count.must_equal (order_count + 1) + end - end + it "invalid data should redirect to order new page if user logged in" do + user = users(:beyonce) + login(user) + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + order_count = Order.count + post orders_path, params: { order: + { user: user , + status: "paid" , + name: user.name , + card_number: nil , + email: user.email , + street: "malden" , + city: "seattle" , + state: "wa" , + zip: 12345 , + date_year: 19 , + date_month: 5 , + date_day: 3 , + cvv: 123 + } + } + must_respond_with :bad_request + Order.count.must_equal order_count + end + it "invalid data should redirect to order new page if no user logged in" do + user = User.first + user.id = 1 + user.save + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + order_count = Order.count + post orders_path, params: { order: + { user: user , + status: "paid" , + name: user.name , + card_number: nil , + email: user.email , + street: "malden" , + city: "seattle" , + state: "wa" , + zip: 12345 , + date_year: 19 , + date_month: 5 , + date_day: 3 , + cvv: 123 + } + } + must_respond_with :bad_request + Order.count.must_equal order_count + end + end - it "invalid data returns an empty array" do + describe "show" do + it "should get show" do + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + get order_details_path(@test_order.id) + value(response).must_be :success? + end + end - end + describe "merchant_order_show" do + it "should get order show page for merchants order_items and their order details" do + test_user_hash = + { + :name => @test_user.name, + :email => @test_user.email, + :uid => @test_user.uid, + :provider => @test_user.provider + } + user = User.new(test_user_hash) + user.save + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + get auth_callback_path(:github) + get sold_order_path(@test_order.id), params: { :id => @test_user.id} + value(response).must_be :success? + end - end + it "valid data returns an array of order_items of products made by merchant" do + end + it "invalid data returns an empty array" do end + end end From 89ae3b31545a7322b0a4f2716ed3b4c6e7c05c44 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 09:29:35 -0700 Subject: [PATCH 286/320] fixes category save --- app/controllers/products_controller.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 33c00e8cf0..6fa91b9786 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -29,6 +29,13 @@ def new def create @product = Product.new(product_params) + + new_category = product_params[:categories_attributes]["0"]["name"] + if new_category != "" + category = Category.create(name: new_category) + @product.categories << category + end + binding.pry @user = User.find_by(id: session[:user_id]) @product.user = @user @action = user_products_path(@product.user.id) From 6e608f9547fd4f095a24038ee53afc91e5e39bf1 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 09:29:55 -0700 Subject: [PATCH 287/320] gets rid of binding --- app/controllers/products_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 6fa91b9786..6d33f20732 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -35,7 +35,7 @@ def create category = Category.create(name: new_category) @product.categories << category end - binding.pry + @user = User.find_by(id: session[:user_id]) @product.user = @user @action = user_products_path(@product.user.id) From 68357090338c332108e4989868b985d4495fb71f Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 09:30:43 -0700 Subject: [PATCH 288/320] removed commented out code in controller --- app/controllers/orders_controller.rb | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 67146ab90d..20da370120 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -83,18 +83,6 @@ def merchant_order_show @order_items = OrderItem.where(order_id: @order.id) else - # i want to remove this code because it should raise an error if the user is not the same as the visitor - - # product_ids = @user.products.map{ |i| i.id } - # @order_items = [] - # array = OrderItem.where(order_id: @order.id) - # - # array.each do |item| - # if product_ids.include?(item.product.id) - # @order_items << item - # end - # end - flash[:status] = :failure flash[:result_text] = "You are not a merchant for this order" redirect_to :root From 744eb17d8e6193dabb7330c9dcd748377828ac16 Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 09:31:25 -0700 Subject: [PATCH 289/320] changes image tag in root file --- app/models/user.rb | 2 +- app/views/products/root.html.erb | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 66c94bfc58..659318fa06 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,7 +10,7 @@ def self.build_from_github(auth_hash) return User.new(uid: auth_hash[:uid], provider: auth_hash[:provider], email: auth_hash[:info][:email], name: auth_hash[:info][:nickname]) end - MERCHANT_PICS = ['https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-4.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-26.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-27.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-28.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-29.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-30.jpg'] + MERCHANT_PICS = ['https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-4.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-26.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-27.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-28.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-29.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-30.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-34.jpg', 'https://www.icreativeideas.com/wp-content/uploads/2014/08/Creative-Animals-Made-of-Fruits-And-Vegetables-32.jpg'] end diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 98df423be1..59fde24d1d 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -3,8 +3,7 @@
              <% @products.sample(9).each do |product|%>
            • - <%= image_tag(product.image, :alt => "fruit!", :class => "thumbnail") %> - + fruit! <%= link_to product.name, product_path(product[:id]) %> From 3e028fd8a6df59b4d8f275668cd69e64516c4864 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 09:34:55 -0700 Subject: [PATCH 290/320] fixes product show for categories --- app/views/products/show.html.erb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 4c0bdc15ad..1756c7573d 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -12,9 +12,11 @@
              Categories: + <% @product.categories.each do |category| %> - <%= category.name %> + <%= category.name %>, <% end %> +
              From 60c84827058d2c05f882669318d65ef3d98379e4 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 09:41:11 -0700 Subject: [PATCH 291/320] controller test for order show page for confirmation of purchase test failed then passes for nominal cases --- app/controllers/order_items_controller.rb | 14 +++----------- test/controllers/orders_controller_test.rb | 13 +++++++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb index 57df6ed713..9d8ab1de35 100644 --- a/app/controllers/order_items_controller.rb +++ b/app/controllers/order_items_controller.rb @@ -2,7 +2,8 @@ class OrderItemsController < ApplicationController def index @user = User.find_by(uid: session[:uid]) if @user == nil || @user.id == 1 - #flash message + flash[:status] = :failure + flash[:result_text] = "Guest accounts dont have access to individual order items" redirect_to root_path else @order_items = OrderItem.user_order_items(@user.id) @@ -12,11 +13,6 @@ def index end end - # is this needed? meaning is this an actual page - # def create - # @order_item = OrderItem.new - # end - def edit @order_item = OrderItem.find_by(id: params[:id]) @order = Order.find_by(id: params[:id]) @@ -37,11 +33,7 @@ def edit def update @order_item = OrderItem.find_by(id: params[:id]) @user = User.find_by(id: session[:user_id]) - # if session[:user_id] == 1 - # flash[:status] = :failure - # flash[:result_text] = "You must be a merchant to update products" - # redirect_to root_path - # end + if @order_item if @order_item.update(order_item_params) flash[:status] = :success diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index cc72c73bbb..d00edb1f2f 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -149,6 +149,19 @@ describe "show" do it "should get show" do + + test_user_hash = + { + :name => @test_user.name, + :email => @test_user.email, + :uid => @test_user.uid, + :provider => @test_user.provider + } + user = User.new(test_user_hash) + user.save + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + get auth_callback_path(:github) + post add_to_order_path, params: { :product_id => products(:cherries).id, :quantity => 2} get order_details_path(@test_order.id) From 19b9bf3bef3c2747d81b021f9e08bf7bae9ec441 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Fri, 27 Apr 2018 09:41:39 -0700 Subject: [PATCH 292/320] adds merchant show stlying --- app/assets/stylesheets/users.scss | 27 +++++++++++++++++++++++++++ app/views/users/show.html.erb | 29 ++++++++++++++++------------- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss index 45d51261ed..9d60115add 100644 --- a/app/assets/stylesheets/users.scss +++ b/app/assets/stylesheets/users.scss @@ -2,9 +2,36 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ +.merchant-profile h2 { + text-align: center; + color: gray; +} + +.merchant-show { + display: grid; + grid-template-columns: 1fr 2fr; +} + +.merchant-pic { + margin-bottom: 1em; + margin-right: 1em; +} + +.merchant-info { + display: flex; + flex-direction: column; + justify-content: center; +} + +.merchat-info p .color { + margin-left: 2em; + color: gray; +} + .merchant-profile h2 { margin-bottom: .8em; } + .merchant-profile section p { font-size: 1.4rem; } diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 3940b4bd9f..619f53acf8 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,23 +1,26 @@

              Merchant Profile

              +
              -
              -

              Name: <%= @user.name %>

              -
              -
              -

              Email: <%= @user.email %>

              -
              -
              - <%= link_to "Edit Profile", edit_user_path(@user.id), class: "button" %> +
              + <%= image_tag(User::MERCHANT_PICS.sample, :alt => "Merchant profile picture", :size => "260x180")%> +
              +
              +

              Name: <%= @user.name %>

              - <%= link_to "My Orders", user_order_items_path(@user.id), class: "button" %> +

              Email: <%= @user.email %>

              +
              + <%= link_to "Edit Profile", edit_user_path(@user.id), class: "button" %> - <%= link_to "My Products", user_products_path(@user.id), class: "button" %> -
              -
              - <%= image_tag(User::MERCHANT_PICS.sample, :alt => "Merchant profile picture", :size => "260x180")%> + <%= link_to "My Orders", user_order_items_path(@user.id), class: "button" %> + + <%= link_to "My Products", user_products_path(@user.id), class: "button" %> +
              + +
              +
              From ba4b16aa5f473352f23bb9f9d263ce25fb253eb8 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 09:51:23 -0700 Subject: [PATCH 293/320] fixes two tests for product controller --- app/controllers/products_controller.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 6d33f20732..03efef99c6 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -29,13 +29,14 @@ def new def create @product = Product.new(product_params) - - new_category = product_params[:categories_attributes]["0"]["name"] - if new_category != "" - category = Category.create(name: new_category) - @product.categories << category + if product_params[:categories_attributes] != nil + new_category = product_params[:categories_attributes]["0"]["name"] + if new_category != "" + category = Category.create(name: new_category) + @product.categories << category + end end - + @user = User.find_by(id: session[:user_id]) @product.user = @user @action = user_products_path(@product.user.id) From f30b016c137151b09569f96f6164791698ee8eda Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 09:58:48 -0700 Subject: [PATCH 294/320] created controller test for order controller show method when order has no order_items --- app/controllers/orders_controller.rb | 5 ++++- test/controllers/orders_controller_test.rb | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 20da370120..224c931425 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -30,7 +30,10 @@ def show if @user @order_items = OrderItem.where(order_id: @order.id) - + if @order_items == [] + flash[:status] = :failure + flash[:result_text] = "No order items in your order" + end else product_ids = @user.products.map{ |i| i.id } @order_items = [] diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index d00edb1f2f..139385433f 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -167,6 +167,26 @@ get order_details_path(@test_order.id) value(response).must_be :success? end + + it "should show order page with no order_items if no order_items in order to show and flash no order_items" do + test_user_hash = + { + :name => @test_user.name, + :email => @test_user.email, + :uid => @test_user.uid, + :provider => @test_user.provider + } + user = User.new(test_user_hash) + user.save + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + get auth_callback_path(:github) + + get order_details_path(@test_order.id) + value(response).must_be :success? + + + end + end describe "merchant_order_show" do From 6e30f3c7594f813f48c497fc3d719ce5c0b90a7c Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 10:00:10 -0700 Subject: [PATCH 295/320] changed image tags to html img --- app/views/categories/show.html.erb | 2 +- app/views/products/index.html.erb | 2 +- app/views/products/root.html.erb | 3 +-- app/views/products/show.html.erb | 5 +++-- app/views/users/show.html.erb | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 32823472c5..f2d30730f4 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -3,7 +3,7 @@
                <% @category.products.each do |product| %>
              • - <%= image_tag(product.image, :alt => "fruit!") %> + fruit! <%= link_to product.name, product_path(product.id) %> $<%= sprintf('%.2f', product.price) %> <%= product.description %> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8c2e073eb1..748dca444d 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -14,7 +14,7 @@
                  <% products.each do |product|%>
                • - <%= image_tag(product.image, :alt => "fruit!", :class => "thumbnail") %> + fruit! <%= link_to product.name.capitalize, product_path(product[:id]) %> diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 98df423be1..4be5d2e48d 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -3,8 +3,7 @@
                    <% @products.sample(9).each do |product|%>
                  • - <%= image_tag(product.image, :alt => "fruit!", :class => "thumbnail") %> - + fruit! <%= link_to product.name, product_path(product[:id]) %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 4c0bdc15ad..3114ffa3de 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,7 +2,8 @@
                    - <%= image_tag(@product.image, :alt => "fruit!", :class => "thumbnail") %> + fruit! +
                    Price: $<%= sprintf('%.2f', @product.price) %>
                    @@ -48,7 +49,7 @@ <% review.rating.times do %> - <%= image_tag("https://4.bp.blogspot.com/-xMWFXKu-oRE/WThKE4gVoWI/AAAAAAAACg4/1V6fMZoa6jk0WbFholbMH3PlYg8wSAxGQCLcB/s1600/banana-fruit-icons_www.fruitsname.com_256x256-3.png", :alt => "fruit rating", width:'55') %> + fruit rating <% end %> <%= review.text_review %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 3940b4bd9f..2d542bd5aa 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -18,6 +18,6 @@
                    - <%= image_tag(User::MERCHANT_PICS.sample, :alt => "Merchant profile picture", :size => "260x180")%> + Merchant profile picture
                    From b7bcdd25a9a6c48acdb0b10b081f41522bb6a1bb Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 10:16:21 -0700 Subject: [PATCH 296/320] changes imaage tags from ruby to html --- app/views/categories/show.html.erb | 2 +- app/views/products/index.html.erb | 2 +- app/views/products/show.html.erb | 8 +++----- app/views/users/show.html.erb | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 32823472c5..f2d30730f4 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -3,7 +3,7 @@
                      <% @category.products.each do |product| %>
                    • - <%= image_tag(product.image, :alt => "fruit!") %> + fruit! <%= link_to product.name, product_path(product.id) %> $<%= sprintf('%.2f', product.price) %> <%= product.description %> diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8c2e073eb1..da53ba437c 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -14,7 +14,7 @@
                        <% products.each do |product|%>
                      • - <%= image_tag(product.image, :alt => "fruit!", :class => "thumbnail") %> + fruit! <%= link_to product.name.capitalize, product_path(product[:id]) %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 1756c7573d..30cf57268f 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,7 +2,7 @@
                        - <%= image_tag(@product.image, :alt => "fruit!", :class => "thumbnail") %> + fruit!
                        Price: $<%= sprintf('%.2f', @product.price) %>
                        @@ -12,11 +12,9 @@
                        Categories: - <% @product.categories.each do |category| %> - <%= category.name %>, + <%= category.name %> <% end %> -
                        @@ -49,8 +47,8 @@ <% review.rating.times do %> + fruit rating - <%= image_tag("https://4.bp.blogspot.com/-xMWFXKu-oRE/WThKE4gVoWI/AAAAAAAACg4/1V6fMZoa6jk0WbFholbMH3PlYg8wSAxGQCLcB/s1600/banana-fruit-icons_www.fruitsname.com_256x256-3.png", :alt => "fruit rating", width:'55') %> <% end %> <%= review.text_review %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 3940b4bd9f..2d542bd5aa 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -18,6 +18,6 @@
                        - <%= image_tag(User::MERCHANT_PICS.sample, :alt => "Merchant profile picture", :size => "260x180")%> + Merchant profile picture
                        From 3d060d9e64c1902effd369bdbf1cdd04df851bce Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Fri, 27 Apr 2018 10:26:58 -0700 Subject: [PATCH 297/320] changed color styling --- app/assets/stylesheets/application.css | 13 +++++++++++++ app/assets/stylesheets/products.scss | 15 ++++++++++++--- app/assets/stylesheets/users.scss | 5 ++++- app/views/categories/show.html.erb | 6 +++--- app/views/products/index.html.erb | 4 ++-- app/views/products/root.html.erb | 6 +++--- app/views/products/show.html.erb | 12 +++++++----- app/views/users/show.html.erb | 4 ++-- 8 files changed, 46 insertions(+), 19 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 1180638da8..d2dabc773f 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -151,6 +151,14 @@ a { color: purple; } +span a { + margin-right: 1.1em; +} + +.frontpage li .color { + color: #6d747f; +} + .merchant p { display: flex; flex-direction: column; @@ -161,3 +169,8 @@ a { justify-content: center; align-items: flex-end; } + +h1 { + text-align: center; + color: gray; +} diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index e64ee901d4..a72f003079 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -1,9 +1,6 @@ // Place all the styles related to the Products controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ - .frontpage li { - - } .product-name { font-size: 1.5em; @@ -20,3 +17,15 @@ .merchant-buttons { margin-top: 1em; } + +.product_show { + line-height: 2.4em; +} + +.product-show > * { + margin-left: 1.3em; +} + +.product-show .color { + color: #6d747f; +} diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss index 9d60115add..ea771911fa 100644 --- a/app/assets/stylesheets/users.scss +++ b/app/assets/stylesheets/users.scss @@ -23,8 +23,11 @@ justify-content: center; } -.merchat-info p .color { +.merchat-info p { margin-left: 2em; +} + +.merchant-show .merchant-info .color { color: gray; } diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 32823472c5..bf85d9e5a4 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -4,9 +4,9 @@ <% @category.products.each do |product| %>
                      • <%= image_tag(product.image, :alt => "fruit!") %> - <%= link_to product.name, product_path(product.id) %> - $<%= sprintf('%.2f', product.price) %> - <%= product.description %> + <%= link_to product.name, product_path(product.id) %> + $<%= sprintf('%.2f', product.price) %> +

                        <%= product.description %>

                      • <% end %>
                      diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8c2e073eb1..cdb1accc2d 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -18,9 +18,9 @@ <%= link_to product.name.capitalize, product_path(product[:id]) %> - $<%= sprintf('%.2f', product.price) %> + $<%= sprintf('%.2f', product.price) %> -
                      <%= product.description %>
                      +
                      <%= product.description %>
                      <% if @user && @user.id == session[:user_id]%> diff --git a/app/views/products/root.html.erb b/app/views/products/root.html.erb index 59fde24d1d..6675fcf93c 100644 --- a/app/views/products/root.html.erb +++ b/app/views/products/root.html.erb @@ -5,11 +5,11 @@
                    • fruit! - <%= link_to product.name, product_path(product[:id]) %> + <%= link_to product.name.capitalize, product_path(product[:id]) %> - $<%= sprintf('%.2f', product.price) %> + $<%= sprintf('%.2f', product.price) %> -

                      <%= product.description %>

                      +

                      <%= product.description %>

                    • <% end %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 1756c7573d..72df90a73d 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -4,17 +4,18 @@
                      <%= image_tag(@product.image, :alt => "fruit!", :class => "thumbnail") %>
                      - Price: $<%= sprintf('%.2f', @product.price) %> +
                      + Price: $<%= sprintf('%.2f', @product.price) %>
                      - Quantity Available: <%= @product.quantity %> + Quantity Available: <%= @product.quantity %>
                      - Description: <%= @product.description %> + Description: <%= @product.description %>
                      - + Categories: <% @product.categories.each do |category| %> - <%= category.name %>, + <%= category.name %>, <% end %> @@ -27,6 +28,7 @@ <%= submit_tag "Add to Basket", class: "button" %> <% end %>
                      +
                      <% if @product.user_id == session[:user_id] %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 619f53acf8..04db045c96 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -7,10 +7,10 @@ <%= image_tag(User::MERCHANT_PICS.sample, :alt => "Merchant profile picture", :size => "260x180")%>
                      -

                      Name: <%= @user.name %>

                      +

                      Name: <%= @user.name %>

                      -

                      Email: <%= @user.email %>

                      +

                      Email: <%= @user.email %>

                      <%= link_to "Edit Profile", edit_user_path(@user.id), class: "button" %> From 2d5e4b921e36eb96f6dfb3193f7b1eb8e458821e Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 10:28:16 -0700 Subject: [PATCH 298/320] changes delete button to retire --- app/views/products/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 8c2e073eb1..023547b5d7 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -25,7 +25,7 @@ <% if @user && @user.id == session[:user_id]%>
                      <%= link_to "Edit Product", edit_product_path(product.id), class: "button" %> - <%= link_to 'Delete Product', product_path(product.id), method: :delete, class: "button" %>
                      + <%= link_to 'Retire Product', product_path(product.id), method: :delete, class: "button" %>
                      <% end %> From f22d236921a18560d381006b60c453cd67b91efe Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Fri, 27 Apr 2018 10:38:06 -0700 Subject: [PATCH 299/320] prod index merge conflict --- app/views/products/index.html.erb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index fc280cb0cf..74d55996e9 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -14,12 +14,7 @@
                        <% products.each do |product|%>
                      • -<<<<<<< HEAD fruit! -======= - fruit! ->>>>>>> dda08ed37097c79a4e1f24f4c6e17658cc171778 - <%= link_to product.name.capitalize, product_path(product[:id]) %> $<%= sprintf('%.2f', product.price) %> From 7d4b2bfcfe84f40f6df240a787e72d6264c8cfc3 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Fri, 27 Apr 2018 10:41:36 -0700 Subject: [PATCH 300/320] heroku merge conflicts profile --- app/views/users/show.html.erb | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 747b28db2e..4ffe7aaa0f 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -11,7 +11,7 @@

                        Email: <%= @user.email %>

                        -<<<<<<< HEAD +
                      @@ -25,16 +25,3 @@ -======= -
                      - <%= link_to "Edit Profile", edit_user_path(@user.id), class: "button" %> - - <%= link_to "My Orders", user_order_items_path(@user.id), class: "button" %> - - <%= link_to "My Products", user_products_path(@user.id), class: "button" %> -
                      - - - - ->>>>>>> dda08ed37097c79a4e1f24f4c6e17658cc171778 From 1704cb35a9b025b2a5ef1201420faa5a3b7bf68d Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Fri, 27 Apr 2018 10:45:24 -0700 Subject: [PATCH 301/320] moves profile buttons --- app/views/users/show.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 4ffe7aaa0f..0423ade45d 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -12,7 +12,7 @@

                      Email: <%= @user.email %>

                      -
                      +
                      <%= link_to "Edit Profile", edit_user_path(@user.id), class: "button" %> @@ -21,6 +21,7 @@ <%= link_to "My Products", user_products_path(@user.id), class: "button" %>
                      +
                    From b6ffe81361f0e8bac763269926231fb07251dba9 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Fri, 27 Apr 2018 11:02:21 -0700 Subject: [PATCH 302/320] adds new product form styling --- app/assets/stylesheets/products.scss | 10 ++++++++++ app/assets/stylesheets/reviews.scss | 4 ++++ app/views/products/_productform.html.erb | 3 ++- app/views/products/new.html.erb | 2 ++ app/views/products/show.html.erb | 5 +---- app/views/reviews/_form.html.erb | 6 ++++-- 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss index a72f003079..58aac21399 100644 --- a/app/assets/stylesheets/products.scss +++ b/app/assets/stylesheets/products.scss @@ -29,3 +29,13 @@ .product-show .color { color: #6d747f; } + +.my-class { + text-align: center; + color: gray; +} + +.product-form { + margin-left: 13%; + margin-right: 13% +} diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss index 11bbb12cd5..a72c0b687c 100644 --- a/app/assets/stylesheets/reviews.scss +++ b/app/assets/stylesheets/reviews.scss @@ -1,3 +1,7 @@ // Place all the styles related to the Reviews controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ + +.review-form a .color { + color: #6d747f; +} diff --git a/app/views/products/_productform.html.erb b/app/views/products/_productform.html.erb index c24a1870a0..8005e529bb 100644 --- a/app/views/products/_productform.html.erb +++ b/app/views/products/_productform.html.erb @@ -29,12 +29,13 @@ <%= f.label :categories, :class => "label" %> <%= collection_check_boxes(:product, :category_ids, Category.all, :id, :name) %> - +
                    <%= f.label :new_category, :class => "label" %> <%= f.fields_for :categories, @product.categories.build do |categories_fields| %> <%= categories_fields.text_field :name %> <% end %>
                    + <%= f.submit :class => "button" %> <% end %> diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb index 3b4a476a51..fca4f31b89 100644 --- a/app/views/products/new.html.erb +++ b/app/views/products/new.html.erb @@ -1 +1,3 @@ +
                    <%= render partial: "productform", locals: { page_title: "Create a New Product" } %> +
                    diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index c7c048fbca..8c3d2a6f68 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -2,12 +2,9 @@
                    -<<<<<<< HEAD + fruit! -======= - fruit! ->>>>>>> dda08ed37097c79a4e1f24f4c6e17658cc171778
                    Price: $<%= sprintf('%.2f', @product.price) %> diff --git a/app/views/reviews/_form.html.erb b/app/views/reviews/_form.html.erb index 743158ee62..4109bc517a 100644 --- a/app/views/reviews/_form.html.erb +++ b/app/views/reviews/_form.html.erb @@ -1,9 +1,11 @@ +
                    <%= form_for @review, url: {action: "create"} do |f| %> - <%= f.label :rating, :class => "label" %> + <%= f.label :rating, :class => "label color" %> <%= f.select :rating, 1..5, :prompt => "Select One" %> - <%= f.label :text_review, :class => "label" %> + <%= f.label :text_review, :class => "label color" %> <%= f.text_field :text_review %> <%= f.submit :class => "button" %> <% end %> +
                    From c7d0aef923ba5c38ba7e3b77ca8fdb55beb204db Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 11:04:45 -0700 Subject: [PATCH 303/320] changes from cvv to exp date --- app/views/orders/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index 3d13d51070..b22863216e 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -50,7 +50,7 @@ <%= @order.zip %>
                  • Card: ************<%= @order.card_number.to_s.last(4).to_i %>
                  • -
                  • Exp: <%= @order.cvv %>
                  • +
                  • Exp: <%= @order.date_month %>

                  • Order Total: $<%= sprintf('%.2f', total) %>
                  • Purchased On: <%= render_date(@order.created_at) %>
                  • From bc5b62aa1996b74fb9bf4a1d6ee5f334b774de45 Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 11:15:21 -0700 Subject: [PATCH 304/320] updates seed images --- db/ProductSeed2.csv | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/db/ProductSeed2.csv b/db/ProductSeed2.csv index a65fe7def9..02f473fce7 100644 --- a/db/ProductSeed2.csv +++ b/db/ProductSeed2.csv @@ -1,22 +1,22 @@ Product,price,description,user_id,quantity ,category,image -Apple,1.00,Honey Crisp,2,30,Pome,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Banana,0.25,Perfectly ripe,2,50,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Rainier Cherries,2.99,Sweet and juicy,2,30,Bunches,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg +Vimto,1.00,It contains the juice of grapes, raspberries and blackcurrants (in a 3% concentration), flavoured with herbs and spices. ,2,30,Pome,https://www.muslim-shop.com/bilder/produkte/gross/Vimto-Getraenkesirup-710-ml.jpg +Banana,0.25,Bananas are a tropical fruit that grows on a plant that reaches a height of 10 to 25 feet. The bananas are supported on a large heavy stem and grow with the individual stems facing downward. Bananas are always picked green and ripen on the way to market. When ripe, bananas lose their green color and begin to get small brown spots on their yellow skin.,2,50,-,https://images.unsplash.com/photo-1513098872174-2af8a3c9238a?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c95c19aaa44d82f1aceaa501e6d529c2&auto=format&fit=crop&w=1650&q=80 +Rainier Cherries,2.99,Rainier is a cultivar cherry, or a plant selected for desirable characteristics that can be maintained by propagation. It was developed in 1952 at Washington State University by Harold Fogle, and named after Mount Rainier. It is a cross between the Bing and Van cultivars. Rainiers are sweet cherries with a thin skin and thick creamy-yellow flesh. The cherries are very sensitive to temperature, wind, and rain. About 1/3 of a Rainier cherry orchard's crop is eaten by birds, which accounts for their higher prices. Select only firm and unblemished rainier cherries.,2,30,Bunches,http://blog.thefruitcompany.com/blog2014/wp-content/uploads/2016/06/tfc_chocolate_covered_cherries_-3.jpg Green Grapes,2.00," -A great energy source because of their natural fruit sugar content",2,300,Bunches,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Grapefruit,1.00,"One of the largest citrus fruit, grapefruits are a cross between the pomelo and the shaddock. High in vitamin C, grapefruits are best eaten raw, a traditional breakfast fruit. The best way to eat is to cut them in half and scoop out the flesh with a spoon.",2,10,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Kumquat,0.50,"The name means ""golden orange"" in Chinese. Kumquats are often preserved in sweet syrup and used for marmalade and garnishes, but fresh ones are delicious in fruit salads or for eating just as they are.",2,80,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Lemon,0.25,"Rarely eaten on its own, lemons are an indispensable ingredient in the kitchen. Lemon juice can be used instead of vinegar in sauces, for seasoning in vinaigrette and as instant dressing for fish and shellfish. The best way to store lemon is in the vegetable crisper in the fridge you can put lemons in fruit bowl for a shorter, check them often - if one starts to spoil, the rest will quickly follow.",2,15,Citrus,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Pineapple,3.00,"Derived from the Spanish word 'pina' meaning pine cone. Pineapples have a juicy, sweet-but sometimes slightly tart-fragrant flavour. They are best eaten fresh, serve pineapple flesh in slices, wedges or chunks. It is also available in cans, dried and glace. A good source of vitamin C.",2,14,Pome,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Plums,1.25,"Plums contain more antioxidant than any other fruit. Plums are delicate so make sure that the one you buy are unblemished, and they should be plump and firm. The small sugar plum is dried to make prunes. Delicious stewed, plums are also ideal for making chutneys.",2,16,Pits,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Star Apple,1.15,"The star apple fruits are green to purple with a smooth skin. When sliced horizontally the flesh is translucent white with the seeds forming a star shape. It is best eaten ripe, scooped straight from the skin. It is ripe when soft and should be eaten immediately, but it is still alright to refrigerate for a few days.",2,45,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Strawberry,2.78,"A unique fruit, the seeds grow around the outside of the fruit rather than inside it. Comes in many different sizes, colours and shapes, ranging from cone-like, to oval, or heart-shaped. Best to eat on their own or with natural yoghurt. Use strawberries in desserts, fruit salads, preserves, or in milkshakes.",3,26,Edible Skin,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Watermelon ,5.00,"The high water content of watermelons means that they are low in calories. They contain some vitamins B and C. Watermelon is excellent juiced, chopped up into a fruit salad, or just eaten in chunky slices.",3,43,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Tamarillo,1.65,"these are related to tomatoes and sometimes called ""tree tomatoes."" They are the size of an egg tomato, with dark red skin. The fruit has a strong, sweet flavour that makes it suitable for both sweet or savoury dishes. It can also be used in jams, chutneys, and sorbets.",3,12,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Rambutan,3.40,"The rambutan fruit grows in clusters, with a deep crimson outer skin. The flesh is translucent, and the pale seed is edible when young. Related to lychees and are sometimes known as ""hairy lychees"".(about 5cm / 2inches in diameter) and look quite different but have a similar texture. They can be added to salads, made into jams or jellies, but they are best eaten on their own.",3,3,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Peach,2.25,"Or pawpaw, a large tropical fruit whose ripe flesh can be juicy, creamy, orange-red, or yellow. In the centre is a mass of large peppery black seeds, which are edible and sometimes crushed and used as a spice. Ripe papaya is eaten as a breakfast fruit or as a dessert. It can also be pureed for ice cream, sorbets and iced drinks.",3,9,Pits,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Fig,0.50,"Figs are oval or pear-shaped and can be eaten fresh or dried. They are well known for their laxative and digestive properties. Their high, natural sugar content makes them the sweetest of all fruits. The flavour varies, depending on where they were grown and how ripe they are.",4,24,Edible Skin,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Lime,0.25,"Limes are only green because they are picked unripe but if left to ripen they turn yellow. Limes can be used like lemons but as juice, it is more acidic, so usually less is needed. To make the juice flow more, you can microwave the limes for 2-3 seconds before squeezing. Mostly used in drinks (lime cordials) and cooking.",4,65,Citrus,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Passionfruit,3.00,"The most popular variety is the purple passionfruit about the size of a chicken egg. It has a highly fragrant, sweet, but slightly tart, tasting fruit that can be spooned out and eaten fresh or added to fruit salad, pavlova, and it makes a very popular drink, ice cream and sorbets and a flavouring for all kinds of desserts.",4,43,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Nectarine,1.25,"The nectarine flesh is rich, sweet and juicy and is well suited for eating fresh and for using in ice cream, pies and fruit salads. Colour ranges from silvery white or yellowy orange to pinkish red. The white-fleshed varieties are considered the best and usually the most expensive. Nectarines are often described as a cross between a peach and a plum, but nectarines are actually a variety of smooth-skinned peach.",4,2,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg -Mangosteen,1.15,"Contrary to its name, the mangosteen doesn't resemble or taste like the mango. It resemble an apple, having a short stem and four thick leaf-like bracts which form a rosette encasing the brownish-purple fruit.",4,7,-,http://www.asuntospublicos.org/upload/2017/12/21/the-gallery-for-simple-fruit-bowl-painting-fruit-bowl-paintings-l-d1f74fb586adeb14.jpg \ No newline at end of file +A great energy source because of their natural fruit sugar content",2,300,Bunches,https://images.unsplash.com/photo-1515779122185-2390ccdf060b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4d9510f689e293cb68177431cacc57e4&auto=format&fit=crop&w=1650&q=80 +Grapefruit,1.00,"One of the largest citrus fruit, grapefruits are a cross between the pomelo and the shaddock. High in vitamin C, grapefruits are best eaten raw, a traditional breakfast fruit. The best way to eat is to cut them in half and scoop out the flesh with a spoon.",2,10,-,https://images.unsplash.com/photo-1512580344356-fd2f966fbeae?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=7045f4d90f98f03cf4f6e13cd97b3c3e&auto=format&fit=crop&w=800&q=60 +Kumquat,0.50,"The name means ""golden orange"" in Chinese. Kumquats are often preserved in sweet syrup and used for marmalade and garnishes, but fresh ones are delicious in fruit salads or for eating just as they are.",2,80,-,https://www.potagercity.fr/images/kumquat-58bd74c1857ff.png +Lemon,0.25,"Rarely eaten on its own, lemons are an indispensable ingredient in the kitchen. Lemon juice can be used instead of vinegar in sauces, for seasoning in vinaigrette and as instant dressing for fish and shellfish. The best way to store lemon is in the vegetable crisper in the fridge you can put lemons in fruit bowl for a shorter, check them often - if one starts to spoil, the rest will quickly follow.",2,15,Citrus,https://images.unsplash.com/photo-1432457990754-c8b5f21448de?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=b011e9b1e7a4fcbcfd9aedff10807ac4&auto=format&fit=crop&w=800&q=60 +Pineapple,3.00,"Derived from the Spanish word 'pina' meaning pine cone. Pineapples have a juicy, sweet-but sometimes slightly tart-fragrant flavour. They are best eaten fresh, serve pineapple flesh in slices, wedges or chunks. It is also available in cans, dried and glace. A good source of vitamin C.",2,14,Pome,https://images.unsplash.com/photo-1459541708374-6fe9eea39a29?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=475e22522ecbb80d3abfa1ca7a37eaf7&auto=format&fit=crop&w=800&q=60 +Plums,1.25,"Plums contain more antioxidant than any other fruit. Plums are delicate so make sure that the one you buy are unblemished, and they should be plump and firm. The small sugar plum is dried to make prunes. Delicious stewed, plums are also ideal for making chutneys.",2,16,Pits,https://images.unsplash.com/photo-1447175025301-707b39e9146f?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=e2c1cb369a8266bb5b8324c41662c57b&auto=format&fit=crop&w=800&q=60 +Star Apple,1.15,"The star apple fruits are green to purple with a smooth skin. When sliced horizontally the flesh is translucent white with the seeds forming a star shape. It is best eaten ripe, scooped straight from the skin. It is ripe when soft and should be eaten immediately, but it is still alright to refrigerate for a few days.",2,45,-,http://i19.photobucket.com/albums/b172/Bassgarden/Trinidad/starapple2.jpg +Strawberry,2.78,"A unique fruit, the seeds grow around the outside of the fruit rather than inside it. Comes in many different sizes, colours and shapes, ranging from cone-like, to oval, or heart-shaped. Best to eat on their own or with natural yoghurt. Use strawberries in desserts, fruit salads, preserves, or in milkshakes.",3,26,Edible Skin,https://images.unsplash.com/photo-1495548054858-0e78bb72869e?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c5e64ec548ca2eae10a301e3cc704153&auto=format&fit=crop&w=800&q=60 +Watermelon ,5.00,"The high water content of watermelons means that they are low in calories. They contain some vitamins B and C. Watermelon is excellent juiced, chopped up into a fruit salad, or just eaten in chunky slices.",3,43,-,https://images.unsplash.com/photo-1501648399952-70289b3a1b1d?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c0508b75adf548daa69fbec8cbd0335c&auto=format&fit=crop&w=686&q=80 +Tamarillo,1.65,"these are related to tomatoes and sometimes called ""tree tomatoes."" They are the size of an egg tomato, with dark red skin. The fruit has a strong, sweet flavour that makes it suitable for both sweet or savoury dishes. It can also be used in jams, chutneys, and sorbets.",3,12,-,http://hatgiongnga.net/wp-content/uploads/2017/03/hat-giong-ca-chua-than-go-tamarillo-480x412.jpg +Rambutan,3.40,"The rambutan fruit grows in clusters, with a deep crimson outer skin. The flesh is translucent, and the pale seed is edible when young. Related to lychees and are sometimes known as ""hairy lychees"".(about 5cm / 2inches in diameter) and look quite different but have a similar texture. They can be added to salads, made into jams or jellies, but they are best eaten on their own.",3,3,-,https://pixabay.com/en/lychee-litchi-tropical-fruit-sweet-3064709/ +Peach,2.25,"Or pawpaw, a large tropical fruit whose ripe flesh can be juicy, creamy, orange-red, or yellow. In the centre is a mass of large peppery black seeds, which are edible and sometimes crushed and used as a spice. Ripe papaya is eaten as a breakfast fruit or as a dessert. It can also be pureed for ice cream, sorbets and iced drinks.",3,9,Pits,https://images.unsplash.com/photo-1518518886629-0b9000299b8b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=eb1910975e5c3eae69b31ea78a1828bc&auto=format&fit=crop&w=800&q=60 +Fig,0.50,"Figs are oval or pear-shaped and can be eaten fresh or dried. They are well known for their laxative and digestive properties. Their high, natural sugar content makes them the sweetest of all fruits. The flavour varies, depending on where they were grown and how ripe they are.",4,24,Edible Skin,https://images.unsplash.com/photo-1506851141243-46bb87f2576c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=31de7e8f4f3709fda8ea9ef46d9cdfa2&auto=format&fit=crop&w=800&q=60 +Lime,0.25,"Limes are only green because they are picked unripe but if left to ripen they turn yellow. Limes can be used like lemons but as juice, it is more acidic, so usually less is needed. To make the juice flow more, you can microwave the limes for 2-3 seconds before squeezing. Mostly used in drinks (lime cordials) and cooking.",4,65,Citrus,https://images.unsplash.com/photo-1519144892250-cd5cd895026b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=6174fc5bfcfe0df7e56c2158a11a351c&auto=format&fit=crop&w=1650&q=80 +Passionfruit,3.00,"The most popular variety is the purple passionfruit about the size of a chicken egg. It has a highly fragrant, sweet, but slightly tart, tasting fruit that can be spooned out and eaten fresh or added to fruit salad, pavlova, and it makes a very popular drink, ice cream and sorbets and a flavouring for all kinds of desserts.",4,43,-,https://images.unsplash.com/photo-1502009285422-74e42ac2fd68?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3a2e9d5afe4225baf6216831378808bd&auto=format&fit=crop&w=800&q=60 +Nectarine,1.25,"The nectarine flesh is rich, sweet and juicy and is well suited for eating fresh and for using in ice cream, pies and fruit salads. Colour ranges from silvery white or yellowy orange to pinkish red. The white-fleshed varieties are considered the best and usually the most expensive. Nectarines are often described as a cross between a peach and a plum, but nectarines are actually a variety of smooth-skinned peach.",4,2,-,https://images.unsplash.com/photo-1504577089374-ed8ee92673bb?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=945226a39bab33580bdba05c4e172835&auto=format&fit=crop&w=800&q=60 +Mangosteen,1.15,"Contrary to its name, the mangosteen doesn't resemble or taste like the mango. It resemble an apple, having a short stem and four thick leaf-like bracts which form a rosette encasing the brownish-purple fruit.",4,7,-,https://cdn.pixabay.com/photo/2017/07/06/10/19/mangosteen-2477553__480.jpg From 4a8fdd79ef5c641ef23b5fcaeaf1e68b6b1a781f Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 11:20:02 -0700 Subject: [PATCH 305/320] updated flash messages for created orders in orders controller, order show page testing fails --- app/controllers/orders_controller.rb | 20 ++++---- test/controllers/orders_controller_test.rb | 54 ++++++++++++++-------- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 224c931425..3c75a6e743 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -24,16 +24,19 @@ def new end def show - @order = Order.find_by(id: params[:id]) @user = User.find_by(uid: session['uid']) + if @order.user_id != @user + + flash[:status] = :failure + flash[:result_text] = "This is not your order. Merchants please access your sold oders through your orders page" + flash[:messages] = @order.errors.messages + redirect_to :root + end + if @user @order_items = OrderItem.where(order_id: @order.id) - if @order_items == [] - flash[:status] = :failure - flash[:result_text] = "No order items in your order" - end else product_ids = @user.products.map{ |i| i.id } @order_items = [] @@ -43,7 +46,6 @@ def show @order_items << item end end - end end @@ -68,14 +70,14 @@ def create OrderItem.make_order_items(@order.id, session[:order]) redirect_to order_details_path(@order.id) + + session[:order] = {} else - flash[:status] = :failure + flash[:status] = :alert flash[:result_text] = "Could not make order" flash[:messages] = @order.errors.messages render :new, status: :bad_request end - - session[:order] = {} end def merchant_order_show diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 139385433f..3fc89b9f1a 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -159,34 +159,48 @@ } user = User.new(test_user_hash) user.save - OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) - get auth_callback_path(:github) - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} - get order_details_path(@test_order.id) - value(response).must_be :success? - end + product = products(:cherries) + product.user_id = user.id + product.save - it "should show order page with no order_items if no order_items in order to show and flash no order_items" do - test_user_hash = - { - :name => @test_user.name, - :email => @test_user.email, - :uid => @test_user.uid, - :provider => @test_user.provider - } - user = User.new(test_user_hash) - user.save OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) get auth_callback_path(:github) - get order_details_path(@test_order.id) + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + get order_details_path(@test_order.id), params: { :id => @test_order.id } value(response).must_be :success? - - end + # it "should show order page with no order_items if no order_items in order to show and flash no order_items and user is a merchant" do + # test_user_hash = + # { + # :name => @test_user.name, + # :email => @test_user.email, + # :uid => @test_user.uid, + # :provider => @test_user.provider + # } + # user = User.new(test_user_hash) + # user.save + # OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + # get auth_callback_path(:github) + # + # get order_details_path(@test_order.id) + # value(response).must_be :success? + # end + + # describe "uid nil and guest users should be able to see thier order confirmation page" do + # before do + # post add_to_order_path, params: { :product_id => products(:cherries).id, + # :quantity => 2} + # end + # + # it "should show order page with order_items if userid is nil" do + # get order_details_path(@test_order.id) + # value(response).must_be :success? + # end + # end end describe "merchant_order_show" do From 08ff60ddd6969832521ab8296ec13b8941dc0b00 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 11:28:55 -0700 Subject: [PATCH 306/320] fixed small bug in order confirmation show --- app/controllers/orders_controller.rb | 3 +-- test/controllers/orders_controller_test.rb | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 3c75a6e743..a2f63298e5 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -27,8 +27,7 @@ def show @order = Order.find_by(id: params[:id]) @user = User.find_by(uid: session['uid']) - if @order.user_id != @user - + if @order.user_id != @user.id flash[:status] = :failure flash[:result_text] = "This is not your order. Merchants please access your sold oders through your orders page" flash[:messages] = @order.errors.messages diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 3fc89b9f1a..e9703b7f21 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -167,10 +167,12 @@ OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) get auth_callback_path(:github) +# this should add the stuff in cart to sessions post add_to_order_path, params: { :product_id => products(:cherries).id, :quantity => 2} + get order_details_path(@test_order.id), params: { :id => @test_order.id } - value(response).must_be :success? + # value(response).must_be :success? end # it "should show order page with no order_items if no order_items in order to show and flash no order_items and user is a merchant" do From f8e18777d8973f324d33b5baed5b502bd7daab59 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 11:40:36 -0700 Subject: [PATCH 307/320] more show page testing for guest and logged in merchant --- test/controllers/orders_controller_test.rb | 62 +++++++++++++++------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index e9703b7f21..3877707c98 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -148,7 +148,7 @@ end describe "show" do - it "should get show" do + it "should get show order confirmation page for logged in users" do test_user_hash = { @@ -160,37 +160,59 @@ user = User.new(test_user_hash) user.save - product = products(:cherries) + + product = products(:watermelon) product.user_id = user.id product.save OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) get auth_callback_path(:github) -# this should add the stuff in cart to sessions post add_to_order_path, params: { :product_id => products(:cherries).id, :quantity => 2} get order_details_path(@test_order.id), params: { :id => @test_order.id } - # value(response).must_be :success? + value(response).must_be :success? end - # it "should show order page with no order_items if no order_items in order to show and flash no order_items and user is a merchant" do - # test_user_hash = - # { - # :name => @test_user.name, - # :email => @test_user.email, - # :uid => @test_user.uid, - # :provider => @test_user.provider - # } - # user = User.new(test_user_hash) - # user.save - # OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) - # get auth_callback_path(:github) - # - # get order_details_path(@test_order.id) - # value(response).must_be :success? - # end + it "should get show order confirmation page for guest user" do + + test_user_hash = + { + :name => @test_user.name, + :email => @test_user.email, + :uid => nil, + :provider => @test_user.provider + } + user = User.new(test_user_hash) + user.save + + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + get auth_callback_path(:github) + + post add_to_order_path, params: { :product_id => products(:cherries).id, + :quantity => 2} + + get order_details_path(@test_order.id), params: { :id => @test_order.id } + value(response).must_be :success? + end + + it "should show order page with no order_items if no order_items in order to show" do + test_user_hash = + { + :name => @test_user.name, + :email => @test_user.email, + :uid => @test_user.uid, + :provider => @test_user.provider + } + user = User.new(test_user_hash) + user.save + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + get auth_callback_path(:github) + + get order_details_path(@test_order.id) + value(response).must_be :success? + end # describe "uid nil and guest users should be able to see thier order confirmation page" do # before do From 76da8b74b51ad560d375dac490b524b55b8019a2 Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 11:47:49 -0700 Subject: [PATCH 308/320] seed file images --- app/views/categories/show.html.erb | 10 ++-------- app/views/products/index.html.erb | 2 +- app/views/products/show.html.erb | 3 ++- db/ProductSeed2.csv | 4 ++-- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb index 114ac318c4..9ed51c50a6 100644 --- a/app/views/categories/show.html.erb +++ b/app/views/categories/show.html.erb @@ -3,17 +3,11 @@
                      <% @category.products.each do |product| %>
                    • -<<<<<<< HEAD - <%= image_tag(product.image, :alt => "fruit!") %> + fruit! <%= link_to product.name, product_path(product.id) %> $<%= sprintf('%.2f', product.price) %>

                      <%= product.description %>

                      -======= - fruit! - <%= link_to product.name, product_path(product.id) %> - $<%= sprintf('%.2f', product.price) %> - <%= product.description %> ->>>>>>> dda08ed37097c79a4e1f24f4c6e17658cc171778 +
                    • <% end %>
                    diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb index 74d55996e9..8089199df3 100644 --- a/app/views/products/index.html.erb +++ b/app/views/products/index.html.erb @@ -14,7 +14,7 @@
                      <% products.each do |product|%>
                    • - fruit! + fruit! <%= link_to product.name.capitalize, product_path(product[:id]) %> $<%= sprintf('%.2f', product.price) %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb index 8c3d2a6f68..7553b8a1ea 100644 --- a/app/views/products/show.html.erb +++ b/app/views/products/show.html.erb @@ -3,7 +3,8 @@
                      - fruit! + + fruit!
                      diff --git a/db/ProductSeed2.csv b/db/ProductSeed2.csv index 02f473fce7..b48dd4c73f 100644 --- a/db/ProductSeed2.csv +++ b/db/ProductSeed2.csv @@ -13,10 +13,10 @@ Star Apple,1.15,"The star apple fruits are green to purple with a smooth skin. W Strawberry,2.78,"A unique fruit, the seeds grow around the outside of the fruit rather than inside it. Comes in many different sizes, colours and shapes, ranging from cone-like, to oval, or heart-shaped. Best to eat on their own or with natural yoghurt. Use strawberries in desserts, fruit salads, preserves, or in milkshakes.",3,26,Edible Skin,https://images.unsplash.com/photo-1495548054858-0e78bb72869e?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c5e64ec548ca2eae10a301e3cc704153&auto=format&fit=crop&w=800&q=60 Watermelon ,5.00,"The high water content of watermelons means that they are low in calories. They contain some vitamins B and C. Watermelon is excellent juiced, chopped up into a fruit salad, or just eaten in chunky slices.",3,43,-,https://images.unsplash.com/photo-1501648399952-70289b3a1b1d?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c0508b75adf548daa69fbec8cbd0335c&auto=format&fit=crop&w=686&q=80 Tamarillo,1.65,"these are related to tomatoes and sometimes called ""tree tomatoes."" They are the size of an egg tomato, with dark red skin. The fruit has a strong, sweet flavour that makes it suitable for both sweet or savoury dishes. It can also be used in jams, chutneys, and sorbets.",3,12,-,http://hatgiongnga.net/wp-content/uploads/2017/03/hat-giong-ca-chua-than-go-tamarillo-480x412.jpg -Rambutan,3.40,"The rambutan fruit grows in clusters, with a deep crimson outer skin. The flesh is translucent, and the pale seed is edible when young. Related to lychees and are sometimes known as ""hairy lychees"".(about 5cm / 2inches in diameter) and look quite different but have a similar texture. They can be added to salads, made into jams or jellies, but they are best eaten on their own.",3,3,-,https://pixabay.com/en/lychee-litchi-tropical-fruit-sweet-3064709/ +Rambutan,3.40,"The rambutan fruit grows in clusters, with a deep crimson outer skin. The flesh is translucent, and the pale seed is edible when young. Related to lychees and are sometimes known as ""hairy lychees"".(about 5cm / 2inches in diameter) and look quite different but have a similar texture. They can be added to salads, made into jams or jellies, but they are best eaten on their own.",3,3,-,https://res.cloudinary.com/twenty20/private_images/t_watermark-criss-cross-10/v1449827258000/photosp/a5555e4a-c0f8-4103-9a45-379580ff31d9/stock-photo-flower-food-sweet-food-berry-fruit-freshness-red-strawberry-bowl-a5555e4a-c0f8-4103-9a45-379580ff31d9.jpg Peach,2.25,"Or pawpaw, a large tropical fruit whose ripe flesh can be juicy, creamy, orange-red, or yellow. In the centre is a mass of large peppery black seeds, which are edible and sometimes crushed and used as a spice. Ripe papaya is eaten as a breakfast fruit or as a dessert. It can also be pureed for ice cream, sorbets and iced drinks.",3,9,Pits,https://images.unsplash.com/photo-1518518886629-0b9000299b8b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=eb1910975e5c3eae69b31ea78a1828bc&auto=format&fit=crop&w=800&q=60 Fig,0.50,"Figs are oval or pear-shaped and can be eaten fresh or dried. They are well known for their laxative and digestive properties. Their high, natural sugar content makes them the sweetest of all fruits. The flavour varies, depending on where they were grown and how ripe they are.",4,24,Edible Skin,https://images.unsplash.com/photo-1506851141243-46bb87f2576c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=31de7e8f4f3709fda8ea9ef46d9cdfa2&auto=format&fit=crop&w=800&q=60 Lime,0.25,"Limes are only green because they are picked unripe but if left to ripen they turn yellow. Limes can be used like lemons but as juice, it is more acidic, so usually less is needed. To make the juice flow more, you can microwave the limes for 2-3 seconds before squeezing. Mostly used in drinks (lime cordials) and cooking.",4,65,Citrus,https://images.unsplash.com/photo-1519144892250-cd5cd895026b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=6174fc5bfcfe0df7e56c2158a11a351c&auto=format&fit=crop&w=1650&q=80 Passionfruit,3.00,"The most popular variety is the purple passionfruit about the size of a chicken egg. It has a highly fragrant, sweet, but slightly tart, tasting fruit that can be spooned out and eaten fresh or added to fruit salad, pavlova, and it makes a very popular drink, ice cream and sorbets and a flavouring for all kinds of desserts.",4,43,-,https://images.unsplash.com/photo-1502009285422-74e42ac2fd68?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3a2e9d5afe4225baf6216831378808bd&auto=format&fit=crop&w=800&q=60 Nectarine,1.25,"The nectarine flesh is rich, sweet and juicy and is well suited for eating fresh and for using in ice cream, pies and fruit salads. Colour ranges from silvery white or yellowy orange to pinkish red. The white-fleshed varieties are considered the best and usually the most expensive. Nectarines are often described as a cross between a peach and a plum, but nectarines are actually a variety of smooth-skinned peach.",4,2,-,https://images.unsplash.com/photo-1504577089374-ed8ee92673bb?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=945226a39bab33580bdba05c4e172835&auto=format&fit=crop&w=800&q=60 -Mangosteen,1.15,"Contrary to its name, the mangosteen doesn't resemble or taste like the mango. It resemble an apple, having a short stem and four thick leaf-like bracts which form a rosette encasing the brownish-purple fruit.",4,7,-,https://cdn.pixabay.com/photo/2017/07/06/10/19/mangosteen-2477553__480.jpg +Mangosteen,1.15,"Contrary to its name, the mangosteen doesn't resemble or taste like the mango. It resemble an apple, having a short stem and four thick leaf-like bracts which form a rosette encasing the brownish-purple fruit.",4,7,-,https://res.cloudinary.com/twenty20/private_images/t_watermark-criss-cross-10/v1490628182000/photosp/aad591a8-10b4-499b-b4c5-c43b76e928b2/stock-photo-food-purple-delicious-fresh-overhead-fresh-fruits-mangosteen-flatlay-flat-lay-aad591a8-10b4-499b-b4c5-c43b76e928b2.jpg From 76d59f0bd9cfc6ac194e4e19761e8ada266ffb63 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 11:52:57 -0700 Subject: [PATCH 309/320] removed edge test case for show method in order controller....I could not figure out how to pull from session! :( --- test/controllers/orders_controller_test.rb | 41 ---------------------- 1 file changed, 41 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 3877707c98..6958235541 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -175,28 +175,6 @@ value(response).must_be :success? end - it "should get show order confirmation page for guest user" do - - test_user_hash = - { - :name => @test_user.name, - :email => @test_user.email, - :uid => nil, - :provider => @test_user.provider - } - user = User.new(test_user_hash) - user.save - - OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) - get auth_callback_path(:github) - - post add_to_order_path, params: { :product_id => products(:cherries).id, - :quantity => 2} - - get order_details_path(@test_order.id), params: { :id => @test_order.id } - value(response).must_be :success? - end - it "should show order page with no order_items if no order_items in order to show" do test_user_hash = { @@ -213,18 +191,6 @@ get order_details_path(@test_order.id) value(response).must_be :success? end - - # describe "uid nil and guest users should be able to see thier order confirmation page" do - # before do - # post add_to_order_path, params: { :product_id => products(:cherries).id, - # :quantity => 2} - # end - # - # it "should show order page with order_items if userid is nil" do - # get order_details_path(@test_order.id) - # value(response).must_be :success? - # end - # end end describe "merchant_order_show" do @@ -243,12 +209,5 @@ get sold_order_path(@test_order.id), params: { :id => @test_user.id} value(response).must_be :success? end - - it "valid data returns an array of order_items of products made by merchant" do - end - - it "invalid data returns an empty array" do - end - end end From fb5c0e6817c7031c462d07177162a65e40a03aba Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 11:58:38 -0700 Subject: [PATCH 310/320] seed file changes --- db/ProductSeed2.csv | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/db/ProductSeed2.csv b/db/ProductSeed2.csv index b48dd4c73f..cbbbd1e8cf 100644 --- a/db/ProductSeed2.csv +++ b/db/ProductSeed2.csv @@ -1,9 +1,8 @@ Product,price,description,user_id,quantity ,category,image -Vimto,1.00,It contains the juice of grapes, raspberries and blackcurrants (in a 3% concentration), flavoured with herbs and spices. ,2,30,Pome,https://www.muslim-shop.com/bilder/produkte/gross/Vimto-Getraenkesirup-710-ml.jpg -Banana,0.25,Bananas are a tropical fruit that grows on a plant that reaches a height of 10 to 25 feet. The bananas are supported on a large heavy stem and grow with the individual stems facing downward. Bananas are always picked green and ripen on the way to market. When ripe, bananas lose their green color and begin to get small brown spots on their yellow skin.,2,50,-,https://images.unsplash.com/photo-1513098872174-2af8a3c9238a?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c95c19aaa44d82f1aceaa501e6d529c2&auto=format&fit=crop&w=1650&q=80 -Rainier Cherries,2.99,Rainier is a cultivar cherry, or a plant selected for desirable characteristics that can be maintained by propagation. It was developed in 1952 at Washington State University by Harold Fogle, and named after Mount Rainier. It is a cross between the Bing and Van cultivars. Rainiers are sweet cherries with a thin skin and thick creamy-yellow flesh. The cherries are very sensitive to temperature, wind, and rain. About 1/3 of a Rainier cherry orchard's crop is eaten by birds, which accounts for their higher prices. Select only firm and unblemished rainier cherries.,2,30,Bunches,http://blog.thefruitcompany.com/blog2014/wp-content/uploads/2016/06/tfc_chocolate_covered_cherries_-3.jpg -Green Grapes,2.00," -A great energy source because of their natural fruit sugar content",2,300,Bunches,https://images.unsplash.com/photo-1515779122185-2390ccdf060b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4d9510f689e293cb68177431cacc57e4&auto=format&fit=crop&w=1650&q=80 +Vimto,1.00,"It contains the juice of grapes raspberries and blackcurrants (in a 3% concentration) flavoured with herbs and spices.",2,30,Pome,https://www.muslim-shop.com/bilder/produkte/gross/Vimto-Getraenkesirup-710-ml.jpg +Banana,0.25,"Bananas are a tropical fruit that grows on a plant that reaches a height of 10 to 25 feet. The bananas are supported on a large heavy stem and grow with the individual stems facing downward. Bananas are always picked green and ripen on the way to market. When ripe bananas lose their green color and begin to get small brown spots on their yellow skin.",2,50,-,https://images.unsplash.com/photo-1513098872174-2af8a3c9238a?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c95c19aaa44d82f1aceaa501e6d529c2&auto=format&fit=crop&w=1650&q=80 +Rainier Cherries,2.99,"Rainier is a cultivar cherry or a plant selected for desirable characteristics that can be maintained by propagation. It was developed in 1952 at Washington State University by Harold Fogle, and named after Mount Rainier. It is a cross between the Bing and Van cultivars. Rainiers are sweet cherries with a thin skin and thick creamy-yellow flesh. The cherries are very sensitive to temperature, wind, and rain. About 1/3 of a Rainier cherry orchard's crop is eaten by birds, which accounts for their higher prices. Select only firm and unblemished rainier cherries.",2,30,Bunches,http://blog.thefruitcompany.com/blog2014/wp-content/uploads/2016/06/tfc_chocolate_covered_cherries_-3.jpg +Green Grapes,2.00,"A great energy source because of their natural fruit sugar content",2,300,Bunches,https://images.unsplash.com/photo-1515779122185-2390ccdf060b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4d9510f689e293cb68177431cacc57e4&auto=format&fit=crop&w=1650&q=80 Grapefruit,1.00,"One of the largest citrus fruit, grapefruits are a cross between the pomelo and the shaddock. High in vitamin C, grapefruits are best eaten raw, a traditional breakfast fruit. The best way to eat is to cut them in half and scoop out the flesh with a spoon.",2,10,-,https://images.unsplash.com/photo-1512580344356-fd2f966fbeae?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=7045f4d90f98f03cf4f6e13cd97b3c3e&auto=format&fit=crop&w=800&q=60 Kumquat,0.50,"The name means ""golden orange"" in Chinese. Kumquats are often preserved in sweet syrup and used for marmalade and garnishes, but fresh ones are delicious in fruit salads or for eating just as they are.",2,80,-,https://www.potagercity.fr/images/kumquat-58bd74c1857ff.png Lemon,0.25,"Rarely eaten on its own, lemons are an indispensable ingredient in the kitchen. Lemon juice can be used instead of vinegar in sauces, for seasoning in vinaigrette and as instant dressing for fish and shellfish. The best way to store lemon is in the vegetable crisper in the fridge you can put lemons in fruit bowl for a shorter, check them often - if one starts to spoil, the rest will quickly follow.",2,15,Citrus,https://images.unsplash.com/photo-1432457990754-c8b5f21448de?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=b011e9b1e7a4fcbcfd9aedff10807ac4&auto=format&fit=crop&w=800&q=60 From 5b30ecbeabd8acc84aba2033560f40a8bba9b2fe Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 12:39:28 -0700 Subject: [PATCH 311/320] new order tests passing, new order test for guest user has error --- test/controllers/orders_controller_test.rb | 28 ++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 6958235541..7bd0459341 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -5,7 +5,6 @@ @test_user = users(:beyonce) @test_order = orders(:cart1) @test_product = products(:cherries) - # @test_order_item = order_items(:fruit_salad) end describe "index" do @@ -15,17 +14,22 @@ end end - # describe "new" do - # it "should get new" do - # get new_order_path - # value(response).must_be :success? - # end - # - # it "should assign user to guest when session user_id is nil" do - # session[:user_id] = nil - # get new_order_path - # end - # end + describe "new" do + it "should get new order for logged in user" do + user = users(:beyonce) + login(user) + get new_order_path + value(response).must_be :success? + end + + it "should get new order for not logged in guest" do + user = users(:beyonce) + login(user) + logout(user) + get new_order_path + value(response).must_be :success? + end + end describe "create" do it "should get create" do From 4d8d1105da00f41a730714d047050461ea93f751 Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 12:43:36 -0700 Subject: [PATCH 312/320] seed file changes --- db/ProductSeed2.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/ProductSeed2.csv b/db/ProductSeed2.csv index cbbbd1e8cf..cb942a2e85 100644 --- a/db/ProductSeed2.csv +++ b/db/ProductSeed2.csv @@ -1,5 +1,5 @@ Product,price,description,user_id,quantity ,category,image -Vimto,1.00,"It contains the juice of grapes raspberries and blackcurrants (in a 3% concentration) flavoured with herbs and spices.",2,30,Pome,https://www.muslim-shop.com/bilder/produkte/gross/Vimto-Getraenkesirup-710-ml.jpg +Vimto,1.00,"It contains the juice of grapes raspberries and blackcurrants (in a 3% concentration) flavoured with herbs and spices.",2,30,Pome,http://www.poukouwholesale.com/thumbnail.asp?file=assets/images/saudivimtosyrup.jpg&maxx=300&maxy=0 Banana,0.25,"Bananas are a tropical fruit that grows on a plant that reaches a height of 10 to 25 feet. The bananas are supported on a large heavy stem and grow with the individual stems facing downward. Bananas are always picked green and ripen on the way to market. When ripe bananas lose their green color and begin to get small brown spots on their yellow skin.",2,50,-,https://images.unsplash.com/photo-1513098872174-2af8a3c9238a?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c95c19aaa44d82f1aceaa501e6d529c2&auto=format&fit=crop&w=1650&q=80 Rainier Cherries,2.99,"Rainier is a cultivar cherry or a plant selected for desirable characteristics that can be maintained by propagation. It was developed in 1952 at Washington State University by Harold Fogle, and named after Mount Rainier. It is a cross between the Bing and Van cultivars. Rainiers are sweet cherries with a thin skin and thick creamy-yellow flesh. The cherries are very sensitive to temperature, wind, and rain. About 1/3 of a Rainier cherry orchard's crop is eaten by birds, which accounts for their higher prices. Select only firm and unblemished rainier cherries.",2,30,Bunches,http://blog.thefruitcompany.com/blog2014/wp-content/uploads/2016/06/tfc_chocolate_covered_cherries_-3.jpg Green Grapes,2.00,"A great energy source because of their natural fruit sugar content",2,300,Bunches,https://images.unsplash.com/photo-1515779122185-2390ccdf060b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4d9510f689e293cb68177431cacc57e4&auto=format&fit=crop&w=1650&q=80 From 4248ef44da5ba9bf5156f39c8a4619d5dc774dca Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 13:07:01 -0700 Subject: [PATCH 313/320] new order testing completed for guest and logged in users --- test/controllers/orders_controller_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb index 7bd0459341..5a7f81c80c 100644 --- a/test/controllers/orders_controller_test.rb +++ b/test/controllers/orders_controller_test.rb @@ -25,7 +25,7 @@ it "should get new order for not logged in guest" do user = users(:beyonce) login(user) - logout(user) + delete logout_path get new_order_path value(response).must_be :success? end From f03c36423fe1acc63e46a125cf260534826b10b2 Mon Sep 17 00:00:00 2001 From: Mary Lamkin Date: Fri, 27 Apr 2018 13:11:19 -0700 Subject: [PATCH 314/320] slight changes to merchant prof page --- app/assets/stylesheets/users.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss index ea771911fa..d521120980 100644 --- a/app/assets/stylesheets/users.scss +++ b/app/assets/stylesheets/users.scss @@ -5,6 +5,7 @@ .merchant-profile h2 { text-align: center; color: gray; + margin-bottom: 1.5em; } .merchant-show { @@ -13,7 +14,7 @@ } .merchant-pic { - margin-bottom: 1em; + margin-bottom: 3em; margin-right: 1em; } From 3b164063c5ba794c30f827a2dfe5d8754fba0d47 Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 13:16:17 -0700 Subject: [PATCH 315/320] review refactor --- db/ReviewsSeed.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/ReviewsSeed.csv b/db/ReviewsSeed.csv index da7f3f5e53..35c85368d0 100644 --- a/db/ReviewsSeed.csv +++ b/db/ReviewsSeed.csv @@ -1,6 +1,6 @@ product_id,rating,text_review -1,5,"The best apple ever, so crunchy and juicy!" -1,3,"Ehh... These apples are okay." +1,5,"Amazing!" +1,3,"Interesting. Not my favorite" 2,4,"Put these in banana bread, you should too!" 3,5,"SOOO yummy" 16,2, From 27a776b6b1a9dfb8fcba3a56abe71c2eb0a6caf0 Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 13:17:08 -0700 Subject: [PATCH 316/320] reviews seed file --- db/ReviewsSeed.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/ReviewsSeed.csv b/db/ReviewsSeed.csv index da7f3f5e53..6681a46d35 100644 --- a/db/ReviewsSeed.csv +++ b/db/ReviewsSeed.csv @@ -1,5 +1,5 @@ product_id,rating,text_review -1,5,"The best apple ever, so crunchy and juicy!" +1,5,"I've heard that people put this on their fruit but I prefer to mix it as a drink" 1,3,"Ehh... These apples are okay." 2,4,"Put these in banana bread, you should too!" 3,5,"SOOO yummy" From 406f2ce9c69756d8c5906ed50f7356f06af7f3fb Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 13:30:58 -0700 Subject: [PATCH 317/320] removes cvv info from order show page --- app/views/orders/merchant_order_show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/orders/merchant_order_show.html.erb b/app/views/orders/merchant_order_show.html.erb index ac5848a0a7..1389b24c36 100644 --- a/app/views/orders/merchant_order_show.html.erb +++ b/app/views/orders/merchant_order_show.html.erb @@ -51,7 +51,7 @@
                    • Card: ************<%= @order.card_number.to_s.last(4).to_i %>
                    • Exp: <%= "#{@order.date_month}" %>
                    • -
                    • CVV: <%= @order.cvv %>
                    • +
                    • Purchased On: <%= render_date(@order.created_at) %>
                    • <% order_status = Order.order_status(@order) %> From ee63826907a17adbba735bd01e74f834afdcea0f Mon Sep 17 00:00:00 2001 From: Phoebe Date: Fri, 27 Apr 2018 13:32:59 -0700 Subject: [PATCH 318/320] updates order status method --- app/models/order.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/order.rb b/app/models/order.rb index 436c9b7d11..dd96b1ff1e 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -21,7 +21,7 @@ def self.order_status(order) status = "complete" order_items.each do |item| - if item.status == "paid" + if item.status == "paid" || item.status = "cancelled" status = "pending" end end From 7d6d0ca888c059cd2c3b560a493a4883a3082acc Mon Sep 17 00:00:00 2001 From: Abiaina Date: Fri, 27 Apr 2018 13:37:40 -0700 Subject: [PATCH 319/320] fixed new order controller testing error for logged out/guest users. unable to fix yellow cherry edit product failed test --- app/controllers/sessions_controller.rb | 1 - app/controllers/users_controller.rb | 4 ---- app/models/review.rb | 19 ------------------- config/routes.rb | 2 -- .../order_items_controller_test.rb | 5 +++-- test/controllers/products_controller_test.rb | 8 ++++---- 6 files changed, 7 insertions(+), 32 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 0a71623ab6..6d82849425 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -7,7 +7,6 @@ def show end def new - end def create diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3d2a846c31..9f57575a96 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -10,10 +10,6 @@ def show @user = User.find_by(id: params[:id]) end - # def new - # @user = User.new - # end - def create auth_hash = request.env['omniauth.auth'] if auth_hash['uid'] diff --git a/app/models/review.rb b/app/models/review.rb index 453fff7a51..ae4c426fb2 100644 --- a/app/models/review.rb +++ b/app/models/review.rb @@ -8,23 +8,4 @@ class Review < ApplicationRecord inclusion: { in: 1..5} } - # validate that the product --> product.user_id --> doesn't match the login session id of user - # def no_self_reviews - # product = Product.find(session[:product_id]) - # user = User.find(product.user_id) - # - # if user.id == sessions[:user_id] - # - # end - - # should this be in product or in reviews model? - # def self.average_rating(reviews) - # total = 0 - # reviews.each do |rating| - # total += rating - # end - # - # return total/(reviews.count).round(1) - # end - end diff --git a/config/routes.rb b/config/routes.rb index 5d1035cd5f..e850b8765a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,8 +16,6 @@ get '/order/:id' , to: 'orders#show', as: 'order_details' - # post '/orderitem' , to: 'order_items#create', as: 'create_order' - resources :orders, only: [:index, :new, :create] resources :products do diff --git a/test/controllers/order_items_controller_test.rb b/test/controllers/order_items_controller_test.rb index d0f418190c..90051defee 100644 --- a/test/controllers/order_items_controller_test.rb +++ b/test/controllers/order_items_controller_test.rb @@ -19,9 +19,10 @@ describe "edit" do it "succeeds with a valid order_item" do - get edit_order_item_path(order_items(:fruit_salad).id), params: { + login(users(:beyonce)) + get edit_order_item_path(order_items(:fruit_salad), params: { :id => order_items(:fruit_salad).id - } + }) must_respond_with :success end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 189b84cac4..22d8e58e7f 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -133,13 +133,13 @@ describe "update" do it "succeeds for valid data and a logged on user with permissions" do user = users(:beyonce) - product = products(:cherries) - login(user) + product = products(:cherries) + patch product_path(product.id), params: { product: { - name: 'yellow cherries', + name: "yellow cherries", price: 3.0, description: '1kg ranier cherries', image: 'image_url', @@ -148,7 +148,7 @@ } } - product.name.must_equal 'yellow cherries' + product.name.must_equal "yellow cherries" must_respond_with :redirect must_redirect_to product_path(product.id) end From 1b6d4dac988c2a294d2a54a2365a99f16932975f Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 27 Apr 2018 13:47:01 -0700 Subject: [PATCH 320/320] more things --- app/assets/stylesheets/application.css | 5 +++++ app/views/sessions/index.html.erb | 9 ++++++++- db/ReviewsSeed.csv | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index d2dabc773f..c3bf170562 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -174,3 +174,8 @@ h1 { text-align: center; color: gray; } + +.empty_basket { + margin-left: auto; + margin-right: auto; +} diff --git a/app/views/sessions/index.html.erb b/app/views/sessions/index.html.erb index 7444c7aebf..c6a6099089 100644 --- a/app/views/sessions/index.html.erb +++ b/app/views/sessions/index.html.erb @@ -1,8 +1,15 @@

                      Fruit Basket

                      <% if session[:order].nil? || session[:order] == {} %> -

                      No Items in Basket

                      + +

                      Your basket is empty

                      <%= link_to "Add to Basket", products_path, class: "button" %>

                      +
                      + + +People walk through an Asian produce market with baskets + + <% else %> diff --git a/db/ReviewsSeed.csv b/db/ReviewsSeed.csv index 6681a46d35..b69170b1de 100644 --- a/db/ReviewsSeed.csv +++ b/db/ReviewsSeed.csv @@ -1,6 +1,6 @@ product_id,rating,text_review 1,5,"I've heard that people put this on their fruit but I prefer to mix it as a drink" -1,3,"Ehh... These apples are okay." +1,1,"Ehh... You really shouldn't pour this on your fruit." 2,4,"Put these in banana bread, you should too!" 3,5,"SOOO yummy" 16,2,