<%# need to figure this out--currently, the index view is a work-around %>
+<% end %>
diff --git a/app/views/orders/show_order.html.erb b/app/views/orders/show_order.html.erb
new file mode 100644
index 0000000000..c936b29ee9
--- /dev/null
+++ b/app/views/orders/show_order.html.erb
@@ -0,0 +1 @@
+
+
+
+<%= form_for @product do |f| %>
+ <%= f.label "Name" %>
+ <%= f.text_field :name %>
+
+ <%= f.label "Description" %>
+ <%= f.text_field :description %>
+
+ <%= f.label "Price" %>
+ <%= f.text_field :price %>
+
+ <%= f.label "Publication_year" %>
+ <%= f.text_field :stock %>
+
+ <%= f.label "Category_id" %>
+ <%= f.text_field :category_id %>
+
+ <%= f.label "Photo_URL" %>
+ <%= f.text_field :photo_URL %>
+
+ <%= f.submit "Update product", :class=>"button" %>
+
+<% end %>
+ <#% end %>
+<#% if @product.category_id %>
+ <#%= f.hidden_field :category_id %>
+<#% else %>
+
+name,description,price,stock,category_id,photo_URL,merchant_id
+Ginger Beer,Bubbly Bits of Ginger,10,10,6,https://static.pexels.com/photos/418225/pexels-photo-418225.jpeg,2
+Bubble Tea,Tea but with Bubbles,3,100,6,https://prods3.imgix.net/images/articles/2017_06/non-feature-bubble-tea-bad-health.jpg,5
+Lemonade,When Life Gives You Lemons,5,5,6,http://www.freefoodphotos.com/imagelibrary/drink/slides/lemonade_glasses.jpg,3
+Fruit Smoothie,This Smoothie Brings all the Vitamins to the Yard,7,4,6,http://www.freefoodphotos.com/imagelibrary/drink/slides/milkshake.jpg,7
+Shakshuka,Tomato and Egg Delight,10,10,2,https://images.food52.com/XriDgBBMyPKkfhmcNBNOfFrHMEY=/753x502/b51df01a-73a1-46df-b311-31fd6111d761--2014-0819_shakshuka-003.jpg,2
+Red Chilaquiles with Fried Eggs,Cheese and Eggs and Sauce Oh My!,17,10,6,https://images.food52.com/rzgZ01EXRiJd1szmmQTaws1UG-4=/753x502/f87d6799-35b8-4d96-a7c5-c624e1f70938--2015_0112_quick-red-chilaquiles-5651.jpg,2
+Brioche,Fancy Pastries to Start Your Day,3 Right,2,12,2,https://images.food52.com/Rt1n7F7N5qpmMofeWadqMJPHtC4=/753x502/12bcfa24-59e6-4b49-9aa2-6b0a31ab8830--brioche_yossy_arefi-15.jpg,1
+Pancakes,Flat and Syrupy,12,5,2,Pancakes_URL,2
+Pork Roll Breakfast Sandwich,New Jersey's Finest,5,10,2,http://myjerseyshorelife.com/wp-content/uploads/2016/08/13654367_621255891372198_576486027620737011_n-1.jpg,4
+Sinangag,Garlic Fried Rice with Vinegar Sauce,15,6,2,https://www.saveur.com/g00/3_c-6bbb.x78fajzw.htr_/c-6RTWJUMJZX77x24myyux78x3ax2fx2fbbb.x78fajzw.htrx2fx78nyjx78x2fx78fajzw.htrx2fknqjx78x2fx78ydqjx78x2f100_6c_x2fuzgqnhx2fnrutwyx2f7569x2f7569-65x2fwjhnuj_x78nsfslfl-knqnunst-lfwqnh-kwnji-wnhj_355c6755.oulx3fnytpx3daEz_3YTx78x26n65h.rfwp.nrflj.yduj_$/$/$/$/$/$/$/$/$/$/$,5
+Baked Ziti,Hometown Favorite,15,10,4,Ziti_URL,1
+Pad Thai,Noodle Delight,12,23,6,Noodle_URL,3
+Apple Pie,Flaky Crust,15,12,5,Pie_URL,3
+Lumpia,Not just Lumps,5,15,6,Lumpia_URL,2
+Cheesy Crackers,Like Crackers and Cheese,5,5,2,CheesyCrackersURL,1
+Tacos,Good Even on Wednesdays,12,12,3,Tacos_URL,3
diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb
new file mode 100644
index 0000000000..84d29af638
--- /dev/null
+++ b/app/views/reviews/new.html.erb
@@ -0,0 +1,14 @@
+
+
Reviewing: <%= @product.name%>
+
+<%= form_for [@product,@review] do |f| %>
+ <%= f.label "Rating: Five is Best!" %>
+
+ <%= f.select :rating, [5, 4, 3, 2, 1] %>
+
+ <%= f.label "Review: Limit 500 Characters" %>
+ <%= f.text_field :reviewtext %>
+
+ <%= f.submit "Submit Review", class: "button" %>
+
+<% end %>
diff --git a/app/views/sessions/login.html.erb b/app/views/sessions/login.html.erb
new file mode 100644
index 0000000000..e69de29bb2
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/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/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..4e681dde07
--- /dev/null
+++ b/config/routes.rb
@@ -0,0 +1,23 @@
+Rails.application.routes.draw do
+ # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
+ root 'products#main'
+
+ # resources :review, except: [:index, :new]
+
+ resources :products do
+ resources :reviews, only: [:index, :new, :create]
+ end
+
+ resources :merchants
+ resources :categories
+ resources :orders
+ resources :orders_products
+
+ delete '/orders_products/', to: 'orders_products#destroy_all', as: 'destroy_all'
+
+ get '/auth/:provider/callback', to: 'sessions#login', as: 'auth_callback'
+ post '/logout', to: 'sessions#logout', as: 'logout'
+ post '/add_to_cart/:id', to: 'orders#add_to_cart', as: 'add_to_cart'
+ get '/billing_form', to: 'orders#billing_form'
+ post '/order/complete', to: 'orders#submit', as: 'complete_order'
+end
diff --git a/config/secrets.yml b/config/secrets.yml
new file mode 100644
index 0000000000..4dbcb51507
--- /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: bec057bb552829dbb276d4fc62d07f866cf4fae50fa58f3179b821d584b0de4426049f372418840189f0645ce3213c1d1aab5b06ccae99c0a3802ae5e44706be
+
+test:
+ secret_key_base: 2453cc316f77e3b903d67935dfc0343a5f3b9ab84fea1a98305bba0d5d2341f869691c5a7e378e5955750ae4e3c5947bb23ee3d4ae54e98b5eff1352e4e577aa
+
+# 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/migrate/20171018000506_create_merchants.rb b/db/migrate/20171018000506_create_merchants.rb
new file mode 100644
index 0000000000..64a57c904c
--- /dev/null
+++ b/db/migrate/20171018000506_create_merchants.rb
@@ -0,0 +1,10 @@
+class CreateMerchants < ActiveRecord::Migration[5.1]
+ def change
+ create_table :merchants do |t|
+ t.string :username
+ t.string :email
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20171018044553_create_products.rb b/db/migrate/20171018044553_create_products.rb
new file mode 100644
index 0000000000..969fae5730
--- /dev/null
+++ b/db/migrate/20171018044553_create_products.rb
@@ -0,0 +1,13 @@
+class CreateProducts < ActiveRecord::Migration[5.1]
+ def change
+ create_table :products do |t|
+ t.string :name
+ t.string :description
+ t.integer :price
+ t.integer :stock
+ t.integer :category_id
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20171018174651_add_photo_url_to_products.rb b/db/migrate/20171018174651_add_photo_url_to_products.rb
new file mode 100644
index 0000000000..e6250547be
--- /dev/null
+++ b/db/migrate/20171018174651_add_photo_url_to_products.rb
@@ -0,0 +1,5 @@
+class AddPhotoUrlToProducts < ActiveRecord::Migration[5.1]
+ def change
+ add_column :products, :photo_URL, :string
+ end
+end
diff --git a/db/migrate/20171018183715_add_merchant_id_to_products.rb b/db/migrate/20171018183715_add_merchant_id_to_products.rb
new file mode 100644
index 0000000000..0e8db5b3d9
--- /dev/null
+++ b/db/migrate/20171018183715_add_merchant_id_to_products.rb
@@ -0,0 +1,5 @@
+class AddMerchantIdToProducts < ActiveRecord::Migration[5.1]
+ def change
+ add_column :products, :merchant_id, :integer
+ end
+end
diff --git a/db/migrate/20171018214616_create_categories.rb b/db/migrate/20171018214616_create_categories.rb
new file mode 100644
index 0000000000..6e136ce0ec
--- /dev/null
+++ b/db/migrate/20171018214616_create_categories.rb
@@ -0,0 +1,9 @@
+class CreateCategories < ActiveRecord::Migration[5.1]
+ def change
+ create_table :categories do |t|
+ t.string :category_name
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20171019164834_create_order_products.rb b/db/migrate/20171019164834_create_order_products.rb
new file mode 100644
index 0000000000..dd0afe94f7
--- /dev/null
+++ b/db/migrate/20171019164834_create_order_products.rb
@@ -0,0 +1,11 @@
+class CreateOrderProducts < ActiveRecord::Migration[5.1]
+ def change
+ create_table :order_products do |t|
+ t.integer :quanitity
+ t.integer :product_id
+ t.integer :order_id
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20171019171402_create_orders.rb b/db/migrate/20171019171402_create_orders.rb
new file mode 100644
index 0000000000..8d3698575f
--- /dev/null
+++ b/db/migrate/20171019171402_create_orders.rb
@@ -0,0 +1,9 @@
+class CreateOrders < ActiveRecord::Migration[5.1]
+ def change
+ create_table :orders do |t|
+ t.string :status
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20171019220543_add_uid_and_provider_to_merchants.rb b/db/migrate/20171019220543_add_uid_and_provider_to_merchants.rb
new file mode 100644
index 0000000000..9d8699705d
--- /dev/null
+++ b/db/migrate/20171019220543_add_uid_and_provider_to_merchants.rb
@@ -0,0 +1,6 @@
+class AddUidAndProviderToMerchants < ActiveRecord::Migration[5.1]
+ def change
+ add_column :merchants, :provider, :string, null: false
+ add_column :merchants, :uid, :string, null: false
+ end
+end
diff --git a/db/migrate/20171020000956_create_reviews.rb b/db/migrate/20171020000956_create_reviews.rb
new file mode 100644
index 0000000000..a5f0a7f677
--- /dev/null
+++ b/db/migrate/20171020000956_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 :reviewtext
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20171020190246_add_user_id_to_order.rb b/db/migrate/20171020190246_add_user_id_to_order.rb
new file mode 100644
index 0000000000..346aa3f7e9
--- /dev/null
+++ b/db/migrate/20171020190246_add_user_id_to_order.rb
@@ -0,0 +1,5 @@
+class AddUserIdToOrder < ActiveRecord::Migration[5.1]
+ def change
+ add_column :orders, :user_id, :integer
+ end
+end
diff --git a/db/migrate/20171020203041_add_order_id_to_orders.rb b/db/migrate/20171020203041_add_order_id_to_orders.rb
new file mode 100644
index 0000000000..360e3b13a2
--- /dev/null
+++ b/db/migrate/20171020203041_add_order_id_to_orders.rb
@@ -0,0 +1,5 @@
+class AddOrderIdToOrders < ActiveRecord::Migration[5.1]
+ def change
+ add_column :orders, :order_id, :integer
+ end
+end
diff --git a/db/migrate/20171023040659_create_billings.rb b/db/migrate/20171023040659_create_billings.rb
new file mode 100644
index 0000000000..2937120149
--- /dev/null
+++ b/db/migrate/20171023040659_create_billings.rb
@@ -0,0 +1,19 @@
+class CreateBillings < ActiveRecord::Migration[5.1]
+ def change
+ create_table :billings do |t|
+ t.string :street, null: false
+ t.string :apt
+ t.string :city, null: false
+ t.string :state, null: false
+ t.integer :ship_zip, null: false, length: 5
+
+ t.string :email, null: false
+ t.integer :credit_card, null: false, length: 16
+ t.integer :exp, null: false, length: 4
+ t.integer :cvv, null: false
+ t.integer :bill_zip, null: false, length: 5
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20171023212500_add_null_false_to_products.rb b/db/migrate/20171023212500_add_null_false_to_products.rb
new file mode 100644
index 0000000000..b554cf53f0
--- /dev/null
+++ b/db/migrate/20171023212500_add_null_false_to_products.rb
@@ -0,0 +1,5 @@
+class AddNullFalseToProducts < ActiveRecord::Migration[5.1]
+ def change
+ # decided not to use this
+ end
+end
diff --git a/db/migrate/20171023221318_remove_null_from_billing.rb b/db/migrate/20171023221318_remove_null_from_billing.rb
new file mode 100644
index 0000000000..ae7659d375
--- /dev/null
+++ b/db/migrate/20171023221318_remove_null_from_billing.rb
@@ -0,0 +1,13 @@
+class RemoveNullFromBilling < ActiveRecord::Migration[5.1]
+ def change
+ change_column_null :billings, :street, :true
+ change_column_null :billings, :city, :true
+ change_column_null :billings, :state, :true
+ change_column_null :billings, :ship_zip, :true
+ change_column_null :billings, :email, :true
+ change_column_null :billings, :credit_card, :true
+ change_column_null :billings, :exp, :true
+ change_column_null :billings, :cvv, :true
+ change_column_null :billings, :bill_zip, :true
+ end
+end
diff --git a/db/migrate/20171023223527_set_length_to_review.rb b/db/migrate/20171023223527_set_length_to_review.rb
new file mode 100644
index 0000000000..38e746ecf0
--- /dev/null
+++ b/db/migrate/20171023223527_set_length_to_review.rb
@@ -0,0 +1,8 @@
+class SetLengthToReview < ActiveRecord::Migration[5.1]
+ def self.down
+ change_column :reviews, :reviewtext
+ end
+ def self.up
+ change_column :reviews, :reviewtext, :string, length: 500
+ end
+end
diff --git a/db/migrate/20171023224545_add_length_to_review.rb b/db/migrate/20171023224545_add_length_to_review.rb
new file mode 100644
index 0000000000..606be91b93
--- /dev/null
+++ b/db/migrate/20171023224545_add_length_to_review.rb
@@ -0,0 +1,5 @@
+class AddLengthToReview < ActiveRecord::Migration[5.1]
+ def change
+ change_column :reviews, :reviewtext, :string, length: 500
+ end
+end
diff --git a/db/migrate/20171024174101_correct_order_product_quantity_spelling.rb b/db/migrate/20171024174101_correct_order_product_quantity_spelling.rb
new file mode 100644
index 0000000000..4358c65455
--- /dev/null
+++ b/db/migrate/20171024174101_correct_order_product_quantity_spelling.rb
@@ -0,0 +1,5 @@
+class CorrectOrderProductQuantitySpelling < ActiveRecord::Migration[5.1]
+ def change
+ rename_column :order_products, :quanitity, :quantity
+ end
+end
diff --git a/db/migrate/20171024174125_change_credit_card_format_to_sting.rb b/db/migrate/20171024174125_change_credit_card_format_to_sting.rb
new file mode 100644
index 0000000000..92b3251e56
--- /dev/null
+++ b/db/migrate/20171024174125_change_credit_card_format_to_sting.rb
@@ -0,0 +1,5 @@
+class ChangeCreditCardFormatToSting < ActiveRecord::Migration[5.1]
+ def change
+ change_column :billings, :credit_card, :string
+ end
+end
diff --git a/db/migrate/20171024180242_add_name_to_billing.rb b/db/migrate/20171024180242_add_name_to_billing.rb
new file mode 100644
index 0000000000..08e50bf566
--- /dev/null
+++ b/db/migrate/20171024180242_add_name_to_billing.rb
@@ -0,0 +1,5 @@
+class AddNameToBilling < ActiveRecord::Migration[5.1]
+ def change
+ add_column :billings, :name, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 0000000000..2756976f80
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,85 @@
+# 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: 20171024180242) do
+
+ # These are extensions that must be enabled in order to support this database
+ enable_extension "plpgsql"
+
+ create_table "billings", force: :cascade do |t|
+ t.string "street"
+ t.string "apt"
+ t.string "city"
+ t.string "state"
+ t.integer "ship_zip"
+ t.string "email"
+ t.string "credit_card"
+ t.integer "exp"
+ t.integer "cvv"
+ t.integer "bill_zip"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.string "name"
+ end
+
+ create_table "categories", force: :cascade do |t|
+ t.string "category_name"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ create_table "merchants", force: :cascade do |t|
+ t.string "username"
+ t.string "email"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.string "provider", null: false
+ t.string "uid", null: false
+ end
+
+ create_table "order_products", force: :cascade do |t|
+ t.integer "quantity"
+ t.integer "product_id"
+ t.integer "order_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ create_table "orders", force: :cascade do |t|
+ t.string "status"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.integer "user_id"
+ t.integer "order_id"
+ end
+
+ create_table "products", force: :cascade do |t|
+ t.string "name"
+ t.string "description"
+ t.integer "price"
+ t.integer "stock"
+ t.integer "category_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.string "photo_URL"
+ t.integer "merchant_id"
+ end
+
+ create_table "reviews", force: :cascade do |t|
+ t.integer "product_id"
+ t.integer "rating"
+ t.string "reviewtext"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+end
diff --git a/db/seed_data/categories.csv b/db/seed_data/categories.csv
new file mode 100644
index 0000000000..54b12cf6ef
--- /dev/null
+++ b/db/seed_data/categories.csv
@@ -0,0 +1,7 @@
+category_name
+Appetizers
+Breakfast
+Lunch
+Dinner
+Desserts
+Drinks
diff --git a/db/seed_data/merchants.csv b/db/seed_data/merchants.csv
new file mode 100644
index 0000000000..5b9b1b0580
--- /dev/null
+++ b/db/seed_data/merchants.csv
@@ -0,0 +1,8 @@
+username,email,provider,uid
+john_smith,john_smith@fakemail.com,github,1234
+liza_lee,liza_lee@fakemail.com,github,12345
+linda_loop,linda_loop@fakemail.com,github,789
+jenny_jones,jenny_jones@mailing.com,github,900
+henny_penny,henny_penny@skyisfalling.com,github,1000
+dixie_pixie,dixie_pixie@pixiedust.com,github,42
+sally_racket,sally_racket@seashanty.edu,github,423
diff --git a/db/seed_data/products.csv b/db/seed_data/products.csv
new file mode 100644
index 0000000000..d9539a8ed5
--- /dev/null
+++ b/db/seed_data/products.csv
@@ -0,0 +1,26 @@
+name,description,price,stock,category_id,photo_URL,merchant_id
+Ginger Beer,Bubbly Bits of Ginger,10,10,6,https://static.pexels.com/photos/418225/pexels-photo-418225.jpeg,2
+Bubble Tea,Tea but with Bubbles,3,100,6,https://prods3.imgix.net/images/articles/2017_06/non-feature-bubble-tea-bad-health.jpg,5
+Lemonade,When Life Gives You Lemons,5,5,6,http://www.freefoodphotos.com/imagelibrary/drink/slides/lemonade_glasses.jpg,3
+Fruit Smoothie,This Smoothie Brings all the Vitamins to the Yard,7,4,6,http://www.freefoodphotos.com/imagelibrary/drink/slides/milkshake.jpg,7
+Shakshuka,Tomato and Egg Delight,10,10,2,https://images.food52.com/XriDgBBMyPKkfhmcNBNOfFrHMEY=/753x502/b51df01a-73a1-46df-b311-31fd6111d761--2014-0819_shakshuka-003.jpg,2
+Red Chilaquiles with Fried Eggs,Cheese and Eggs and Sauce Oh My!,17,10,6,https://images.food52.com/rzgZ01EXRiJd1szmmQTaws1UG-4=/753x502/f87d6799-35b8-4d96-a7c5-c624e1f70938--2015_0112_quick-red-chilaquiles-5651.jpg,2
+Brioche,Fancy Pastries to Start Your Day,3 Right,2,12,2,https://images.food52.com/Rt1n7F7N5qpmMofeWadqMJPHtC4=/753x502/12bcfa24-59e6-4b49-9aa2-6b0a31ab8830--brioche_yossy_arefi-15.jpg,1
+Pork Roll Breakfast Sandwich,New Jersey's Finest,5,10,2,http://myjerseyshorelife.com/wp-content/uploads/2016/08/13654367_621255891372198_576486027620737011_n-1.jpg,4
+Sinangag,Garlic Fried Rice with Vinegar Sauce,15,6,2,https://www.saveur.com/g00/3_c-6bbb.x78fajzw.htr_/c-6RTWJUMJZX77x24myyux78x3ax2fx2fbbb.x78fajzw.htrx2fx78nyjx78x2fx78fajzw.htrx2fknqjx78x2fx78ydqjx78x2f100_6c_x2fuzgqnhx2fnrutwyx2f7569x2f7569-65x2fwjhnuj_x78nsfslfl-knqnunst-lfwqnh-kwnji-wnhj_355c6755.oulx3fnytpx3daEz_3YTx78x26n65h.rfwp.nrflj.yduj_$/$/$/$/$/$/$/$/$/$/$,5
+Baked Ziti,Hometown Favorite,15,10,4,Ziti_URL,1
+Pad Thai,Noodle Delight,12,23,6,Noodle_URL,3
+Apple Pie,Flaky Crust,15,12,5,Pie_URL,3
+Lumpia,Not just Lumps,5,15,6,Lumpia_URL,2
+Cheesy Crackers,Like Crackers and Cheese,5,5,2,CheesyCrackersURL,1
+Tacos,Good Even on Wednesdays,12,12,3,Tacos_URL,3
+Japanese Chicken Skewers,Deliciously mouth-watering chicken from Japan,5,10,1,https://www.justonecookbook.com/wp-content/uploads/2014/04/Yakitori-II-600x900.jpg,2
+Brined and Cured fish,Raved Russian Snack,1,10,1,https://fthmb.tqn.com/FYTIvysPnUzMnypTZuuDicxyWWQ=/960x0/filters:no_upscale()/caviar-56a277413df78cf772764cc2.jpg,4
+Pan Fried Tofu with Spicy Sauce,KO-rean taste,1,1,https://www.maangchi.com/wp-content/uploads/2009/09/pan-fried-tofu.jpg,3
+Peel and Eat Shrimp with BBQ Sauce,American BBQ,5,10,1,https://imagesvc.timeincapp.com/v3/mm/image?url=http%3A%2F%2Fcdn-image.foodandwine.com%2Fsites%2Fdefault%2Ffiles%2FHD-fw200605_peelAndEat.jpg&w=800&q=85,4
+Laghman,Kyrgastan Dumpling,2,10,1,http://www.flickr.com/photos/garysoup/3581616346/,5
+Vigoron,Nicaraguan Lunch,5,10,3,http://www.whats4eats.com/files/styles/teaser/public/vegetables-vigoron-wikipedia-nicaraguan-food-4x3.jpg?itok=CWvTuYY3,6
+Scotch Egg,English Egg,3,2,3,http://www.whats4eats.com/appetizers/scotch-eggs-recipe,4
+Lechona,Colombian Meats!,4,2,3,https://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=imgres&cd=&cad=rja&uact=8&ved=0ahUKEwjvkOzD8IrXAhWl0FQKHb-PCtYQjRwIBw&url=http%3A%2F%2Fconfidencialcolombia.com%2Fes%2F1%2F402%2F10245%2FSe-aprieta-la-%25E2%2580%2598lechona-navide%25C3%25B1a%25E2%2580%2599-en-Risaralda-cerdo-lechona-risaralda-salud-sacrificio-emfermedades.htm&psig=AOvVaw28-D8-bZBk9fOtzSEfIQok&ust=1508990155431524
+NYC Pizza,Crustalious Pizza,3,4,3,https://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&cad=rja&uact=8&ved=0ahUKEwisx87v8orXAhXnilQKHZ4PDJMQjRwIBw&url=https%3A%2F%2Fwww.roughguides.com%2Farticle%2Fthe-true-history-of-new-york-pizza-a-grand-tour%2F&psig=AOvVaw1FybMpsRSeTTX2mP826a6h&ust=1508990765099947,7
+Steak Salad, Blue cheese topped steak,10,5,3,https://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&cad=rja&uact=8&ved=0ahUKEwj9j_iG9IrXAhVlqlQKHZC4BAYQjRwIBw&url=https%3A%2F%2Fwww.pinterest.com%2Fexplore%2Fsteak-salad%2F&psig=AOvVaw0dRibumt33_Kz_b2OKC7wP&ust=1508991082719039,5
diff --git a/db/seed_data/reviews.csv b/db/seed_data/reviews.csv
new file mode 100644
index 0000000000..53544701fb
--- /dev/null
+++ b/db/seed_data/reviews.csv
@@ -0,0 +1,76 @@
+product_id,rating,reviewtext
+1,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+1,3,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+1,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+2,4,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+2,4,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+2,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+2,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+3,3,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+3,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+3,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+4,2,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+4,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+5,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+5,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+5,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+6,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+6,3,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+6,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+7,4,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+7,4,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+7,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+7,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+8,3,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+8,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+8,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+9,2,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+9,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+10,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+10,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+10,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+11,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+11,3,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+11,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+12,4,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+12,4,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+12,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+12,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+13,3,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+13,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+13,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+14,2,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+14,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+15,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+15,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+15,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+16,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+16,3,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+16,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+17,4,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+17,4,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+17,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+17,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+18,3,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+18,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+18,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+19,2,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+19,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+20,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+20,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+20,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+21,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+21,3,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+21,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+22,4,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+22,4,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+22,5,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+22,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+23,3,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+23,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+23,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
+24,2,Cake donut powder powder marshmallow jelly-o chocolate bar jelly beans croissant. Lemon drops jelly-o cake jelly-o pastry muffin. Cotton candy I love muffin oat cake croissant. I love lollipop tart pastry I love.
+24,1,Bonbon tart macaroon powder jelly-o cookie pie. Chocolate bar marzipan jelly beans cake pudding lollipop candy canes sugar plum. Dragée cotton candy carrot cake.
+25,1,Icing I love cake gummi bears candy topping liquorice I love liquorice. Biscuit biscuit gingerbread. Halvah cotton candy jujubes I love sesame snaps jelly chupa chups. Powder gummies dragée chupa chups cupcake cake gingerbread tootsie roll dessert.
+25,5,Oat cake I love marzipan macaroon lollipop I love tootsie roll chupa chups. Gingerbread I love sesame snaps dragée croissant tart powder pudding cheesecake. Jujubes I love sesame snaps chupa chups biscuit cookie dragée.
+25,5,Dessert cookie marshmallow sesame snaps. Tart fruitcake I love. Croissant fruitcake muffin I love pastry fruitcake pie ice cream pastry. I love cookie cake I love liquorice I love.
diff --git a/db/seeds.rb b/db/seeds.rb
new file mode 100644
index 0000000000..cd00a6cd0a
--- /dev/null
+++ b/db/seeds.rb
@@ -0,0 +1,97 @@
+# 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)
+require 'csv'
+
+
+#merchant data
+MERCHANT_FILE = Rails.root.join('db', 'seed_data', 'merchants.csv')
+puts "Loading raw merchant data from #{MERCHANT_FILE}"
+
+merchant_failures = []
+CSV.foreach(MERCHANT_FILE, :headers => true) do |row|
+ merchant = Merchant.new
+ merchant.username = row['username']
+ merchant.email = row['email']
+ merchant.provider = row['provider']
+ merchant.uid = row['uid']
+
+ puts "Created merchant: #{merchant.inspect}"
+ successful = merchant.save
+ if !successful
+ merchant_failures << merchant
+ end
+end
+
+puts "Added #{Merchant.count} merchant records"
+puts "#{merchant_failures.length} merchants failed to save"
+
+# category data
+
+CATEGORY_FILE = Rails.root.join('db', 'seed_data', 'categories.csv')
+puts "Loading raw category data from #{CATEGORY_FILE}"
+
+category_failures = []
+CSV.foreach(CATEGORY_FILE, :headers => true) do |row|
+ category = Category.new
+ category.category_name = row['category_name']
+
+
+ puts "Created category: #{category.inspect}"
+ successful = category.save
+ if !successful
+ category_failures << category
+ end
+end
+
+puts "Added #{Category.count} category records"
+puts "#{category_failures.length} categories failed to save"
+#product data
+
+PRODUCT_FILE = Rails.root.join('db', 'seed_data', 'products.csv')
+puts "Loading raw product data from #{PRODUCT_FILE}"
+product_failures = []
+CSV.foreach(PRODUCT_FILE, :headers => true) do |row|
+ product = Product.new
+ product.name = row['name']
+ product.description = row['description']
+ product.price = row["price"]
+ product.stock = row["stock"]
+ product.category_id = row["category_id"]
+ product.photo_URL = row["photo_URL"]
+ product.merchant_id = row["merchant_id"]
+
+ puts "Created product: #{product.inspect}"
+ successful = product.save
+ if !successful
+ product_failures << product
+ end
+end
+
+puts "Added #{Product.count} product records"
+puts "#{product_failures.length} products failed to save"
+
+# reviews
+
+REVIEW_FILE = Rails.root.join('db', 'seed_data', 'reviews.csv')
+puts "Loading raw product data from #{REVIEW_FILE}"
+product_failures = []
+CSV.foreach(REVIEW_FILE, :headers => true) do |row|
+ review = Review.new
+ review.product_id = row['product_id']
+ review.rating = row['rating']
+ review.reviewtext = row["reviewtext"]
+
+ puts "Created review: #{review.inspect}"
+ successful = review.save
+ if !successful
+ review_failures << review
+ end
+end
+
+puts "Added #{Product.count} product records"
+puts "#{product_failures.length} products failed to save"
diff --git a/feedback.md b/feedback.md
index b958bb8713..399771e2d3 100644
--- a/feedback.md
+++ b/feedback.md
@@ -10,10 +10,10 @@
| Heroku instance is online | |
| **General** | |
| Nested routes follow RESTful conventions | |
-| oAuth used for User authentication | |
+| oAuth used for Merchant authentication | |
| Functionality restricted based on user roles | |
| Products can be added and removed from cart | |
-| Users can view past orders | |
+| Merchants can view past orders | |
| Merchants can add, edit and view their products | |
| Errors are reported to the user | |
| **Order Functionality** | |
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/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb
new file mode 100644
index 0000000000..3dd7095cb8
--- /dev/null
+++ b/test/controllers/categories_controller_test.rb
@@ -0,0 +1,187 @@
+require "test_helper"
+require 'pry'
+
+
+describe CategoriesController do
+
+ describe "index" do
+ it "gets a list of categories" do
+ get categories_path
+ must_respond_with :success
+ end #gets list of categories
+
+ it "returns a success status when no categories" do
+ Category.destroy_all
+ get categories_path
+ must_respond_with :success
+ end #no categories
+ end #index tests
+
+ describe "show" do
+ it "should get show" do
+ get category_path(categories(:cat_one).id)
+ must_respond_with :success
+ end #get show
+
+ it "return success when given a valid category id" do
+ category_id = Category.first.id
+ get category_path(category_id)
+ must_respond_with :success
+ end #return success
+
+ it "returns not found when given an invalid product id" do
+ category_id = Category.last.id + 1
+ get category_path(category_id)
+ must_respond_with :not_found
+ end #return not found
+ end #return show
+
+### Guest user restrictions
+
+#things guess users can/cannot do
+describe "Guest user access" do
+ it "can access the index" do
+ get categories_path
+ must_respond_with :success
+ end #index
+
+ it "can access show page" do
+ category_id = Category.first.id
+ get category_path(category_id)
+ must_respond_with :success
+ end
+
+ it "cannot access new" do
+ get new_category_path
+ must_redirect_to root_path
+ flash[:message].must_equal "You must be logged in to do that!"
+ end #new
+
+ it "cannot access edit" do
+ category_id = Category.first.id
+ get edit_category_path(category_id)
+ must_redirect_to root_path
+ flash[:message].must_equal "You must be logged in to do that!"
+ end
+
+ it "cannot access destroy" do
+ category_id = Category.first.id
+ delete category_path(category_id)
+ must_redirect_to root_path
+ flash[:message].must_equal "You must be logged in to do that!"
+ end
+end #guest users
+
+
+#### Logged in users only
+ describe "Logged in users" do
+ before do
+ login(merchants(:fake_user))
+ end #login
+
+ describe "new" do
+ it "returns a success status" do
+ get new_category_path
+ must_respond_with :success
+ end #return success
+ end #new tests
+
+ describe "create" do
+ it "creates a valid category when data is valid" do
+
+ category_data = {
+ category: {
+ category_name: "abcdefg"
+ }
+ }
+
+ start_category_count = Category.count
+ Category.new(category_data[:category]).must_be :valid?
+
+ post categories_path, params: category_data
+
+ must_respond_with :redirect
+ must_redirect_to categories_path
+
+ Category.count.must_equal start_category_count + 1
+
+ end #valid data test
+
+
+ it "will not create a new category when data is invalid" do
+ invalid_category_data = {
+ category: {
+ category_name: ""
+ }
+ }
+ start_category_count = Category.count
+
+ Category.new(invalid_category_data[:category]).wont_be :valid?
+
+ post categories_path, params: invalid_category_data
+ must_respond_with :bad_request
+
+ Category.count.must_equal start_category_count
+ end #invalid data test
+ end #create tests
+
+
+ describe "edit" do
+ it "returns success when given a valid category id" do
+ get edit_category_path(categories(:cat_one).id)
+ must_respond_with :success
+ end #success for edit
+
+ it "returns not found when given an invalid cateogry id" do
+ invalid_category_id = Category.last.id + 1
+ get edit_category_path(invalid_category_id)
+ must_respond_with :not_found
+ end #not found when not found
+ end #all edit tests
+
+ describe "update" do
+ it "returns success if category id is valid and change is valid" do
+ category = Category.first
+ category_data = {
+ category: {
+ category_name: "Test"
+ }
+ }
+ category.update_attributes(category_data[:category])
+ category.must_be :valid?
+ patch category_path(category), params: category_data
+ end #return success on valid change
+
+ it "returns not found if the work id is invalid" do
+ category_id = Category.last.id + 1
+ get category_path(category_id)
+ must_respond_with :not_found
+ end #returns not found if work is invalid
+ end #update tests
+
+ describe "destroy" do
+ it "destroys the category when given a valid ID and that category is empty and redirects to categories path" do
+ category_id = Category.last.id
+ delete category_path(category_id)
+
+ must_respond_with :redirect
+ must_redirect_to categories_path
+ Category.find_by(id: category_id).must_be_nil
+ end #successful destroy
+
+ it "returns not_found when given an invalid ID" do
+ invalid_category_id = Category.last.id + 1
+ start_category_count = Category.count
+ delete category_path(invalid_category_id)
+ must_respond_with :not_found
+ Category.count.must_equal start_category_count
+ end #invalid id destroy
+
+ it "will not destroy a category that contains products." do
+ category_id = Category.first.id
+ delete category_path(category_id)
+ must_respond_with :bad_request
+ end
+ end #destroy tests
+end #logged in user tests
+end #all tests
diff --git a/test/controllers/merchants_controller_test.rb b/test/controllers/merchants_controller_test.rb
new file mode 100644
index 0000000000..87a7286267
--- /dev/null
+++ b/test/controllers/merchants_controller_test.rb
@@ -0,0 +1,101 @@
+require "test_helper"
+
+describe MerchantsController do
+ describe "index" do
+ it "renders page with all merchants" do
+ get merchants_path
+ must_respond_with :success
+ end
+
+ it "responds with success when there are no merchants" do
+ Merchant.destroy_all
+ get merchants_path
+ must_respond_with :success
+ end
+ end #end index
+
+
+ describe "show" do
+ it "success for vaild merchant ID" do
+ get merchant_path(Merchant.first.id)
+ must_respond_with :success
+ end
+
+ it "gives not_found for bogus merchant ID" do
+ bogus_merchant = Merchant.last.id + 1
+
+ get merchant_path(bogus_merchant)
+ must_respond_with :not_found
+
+ end
+ end # end show
+end #all
+# describe "new" do
+# it "Successfully makes a new merchant" do
+# get new_merchant_path
+# must_respond_with :success
+# end
+# end # end new
+
+# describe "create" do
+# it "adds the merchant to the DB and redirects when the merchant data is valid" do
+# merchant_data = {
+# merchant: {
+# username: "Test merchant",
+# email: "fake@email.com"
+# }
+# }
+#
+# start_merchant_count = Merchant.count
+#
+# Merchant.new(merchant_data[:merchant]).must_be :valid?
+#
+# post merchants_path, params: merchant_data
+#
+# must_respond_with :redirect
+# must_redirect_to merchants_path
+#
+# Merchant.count.must_equal start_merchant_count + 1
+# end
+# end
+
+
+
+# describe "edit" do
+# it "success for vaild merchant ID" do
+# get edit_merchant_path(Merchant.first.id)
+# must_respond_with :success
+# end
+#
+# it "gives not_found for bogus merchant ID" do
+# bogus_merchant = Merchant.last.id + 1
+# get edit_merchant_path(bogus_merchant)
+# must_respond_with :not_found
+# end
+# end
+#
+# describe "update" do
+# it "returns success if the merchant ID is valid and the change is valid" do
+# merchant = Merchant.first
+# merchant_data = {
+# merchant: {
+# username: "test-user",
+# email: "fake@fake.com"
+# }
+# }
+# merchant.update_attributes(merchant_data[:merchant])
+#
+# merchant.must_be :valid?, "Test is invalid because the provided data will produce an invalid merchant"
+#
+# patch merchant_path(merchant), params: merchant_data
+#
+#
+# must_respond_with :redirect
+# must_redirect_to merchant_path(merchant)
+#
+# # Check that the change went through
+# merchant.reload
+# merchant.username.must_equal merchant_data[:merchant][:username]
+#
+#
+# end
diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb
new file mode 100644
index 0000000000..84771c534e
--- /dev/null
+++ b/test/controllers/orders_controller_test.rb
@@ -0,0 +1,70 @@
+require "test_helper"
+
+describe OrdersController do
+
+ describe "show" do
+ it "return success when given a valid order id" do
+ merchant = merchants(:fake_user)
+ order = orders(:one)
+ setup { login(merchant) }
+
+ session[:order_id].must_equal order.id
+
+ # order_id = Order.first.id
+ # get order_path(order_id)
+ # must_respond_with :success
+ end #valid
+
+ it "gives not_found for a bogus order id" do
+ bogus_order_id = Order.last.id + 1
+
+ get order_path(bogus_order_id)
+ must_respond_with :not_found
+ end # invalid id
+
+ #will create new cart if doesn't find one
+ # it "returns not found when given an invalid product id" do
+ # order_id = Order.last.id + 1
+ # get order_path(order_id)
+ # must_respond_with :not_found
+ # end #invalid
+ end #show
+
+ describe "Billing Form" do
+ it "Will Render the Billing Form" do
+ order_id = 1
+ get billing_form_path
+ must_respond_with :success
+ end
+ end
+
+ describe "Submit" do
+ it "will return success if order was submitted" do
+ @billing = billings(:one)
+ must_respond_with :success
+ end
+
+ it "will return failure if order was not submitted" do
+ end
+ end
+
+ # def submit
+ # # billing = Billing.find_by(id:session[:order_id])
+ # @order = Order.find_by(id:session[:order_id], status: "pending")
+ # @order.subtract_products
+ #
+ # @billing = Billing.new(billing_params)
+ #
+ # if @billing.save
+ # @order.status = "paid"
+ # flash[:status] = :success
+ # flash[:message] = "Successfully submitted your order"
+ # session[:order_id] = nil
+ # else
+ # flash.now[:status] = :failure
+ # flash.now[:message] = "Failed submit your order"
+ # end
+ # render :show_order
+ # end
+
+end #all
diff --git a/test/controllers/orders_products_controller_test.rb b/test/controllers/orders_products_controller_test.rb
new file mode 100644
index 0000000000..371d50824e
--- /dev/null
+++ b/test/controllers/orders_products_controller_test.rb
@@ -0,0 +1,4 @@
+require "test_helper"
+
+describe OrdersProductsController do
+end
diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb
new file mode 100644
index 0000000000..f9ad3c4863
--- /dev/null
+++ b/test/controllers/products_controller_test.rb
@@ -0,0 +1,182 @@
+require "test_helper"
+
+
+describe ProductsController do
+
+#all users
+ describe "index" do
+ it "gets a list of products" do
+ get products_path
+ must_respond_with :success
+ end #get list
+
+ it "returns a success status when no products" do
+ Product.destroy_all
+ get products_path
+ must_respond_with :success
+ end #no products
+ end #index tests
+
+ describe "show" do
+ it "return success when given a valid product id" do
+ product_id = Product.first.id
+ get product_path(product_id)
+ must_respond_with :success
+ end
+
+ it "returns not found when given an invalid product id" do
+ product_id = Product.last.id + 1
+ get product_path(product_id)
+ must_respond_with :not_found
+ end
+ end
+
+#things guess users can/cannot do
+describe "Guest user access" do
+ it "can access the index" do
+ get products_path
+ must_respond_with :success
+ end #index
+
+ it "can access show page" do
+ product_id = Product.first.id
+ get product_path(product_id)
+ must_respond_with :success
+ end
+
+ it "cannot access new" do
+ get new_product_path
+ must_redirect_to root_path
+ flash[:message].must_equal "You must be logged in to do that!"
+ end #new
+
+ it "cannot access edit" do
+ product_id = Product.first.id
+ get edit_product_path(product_id)
+ must_redirect_to root_path
+ flash[:message].must_equal "You must be logged in to do that!"
+ end
+
+ it "cannot access destroy" do
+ product_id = Product.first.id
+ delete product_path(product_id)
+ must_redirect_to root_path
+ flash[:message].must_equal "You must be logged in to do that!"
+ end
+
+end #guest users
+
+
+ #Tests for things only logged in users can do
+ describe "Logged in users" do
+ before do
+ login(merchants(:fake_user))
+ end #login
+
+ describe "new" do
+ it "returns a success status" do
+ get new_product_path
+ must_respond_with :success
+ end #succes
+ end #new tests
+
+ describe "create" do
+ it "redirects to products_path when product data is valid" do
+ # test failing because i need to add test data for merchant and category
+ valid_product_data = {
+ product: {
+ name: "test product",
+ stock: 10,
+ price: 12,
+ merchant_id: merchants(:fake_user).id,
+ category_id: categories(:cat_one).id
+ }
+ }
+ start_product_count = Product.count
+
+ Product.new(valid_product_data[:product]).must_be :valid?
+ post products_path, params: valid_product_data
+ must_respond_with :redirect
+ must_redirect_to products_path
+
+ Product.count.must_equal start_product_count + 1
+ end #create when data is valid
+
+ it "sends bad request when product data is invalid" do
+ invalid_product_data = {
+ product: {
+ name: "",
+ price: "12"
+ }
+ }
+ Product.new(invalid_product_data[:product]).wont_be :valid?
+
+ start_product_count = Product.count
+ post products_path, params: invalid_product_data
+ must_respond_with :bad_request
+
+ Product.count.must_equal start_product_count
+ end #create when data is not valid
+ end #create tests
+
+ describe "edit" do
+ it "returns success when given a valid product id" do
+ product_id = Product.first.id
+ get edit_product_path(product_id)
+ must_respond_with :success
+ end #edit success
+
+ it "returns not found when given an invalid product id" do
+ invalid_product_id = Product.last.id + 1
+ get edit_product_path(invalid_product_id)
+ must_respond_with :not_found
+ end #edit failure
+ end #all edit
+
+ describe "update" do
+ it "returns success if product id valid and change is valid" do
+ product = Product.first
+ valid_product_data = {
+ product: {
+ name: "test product",
+ stock: 10,
+ price: 12,
+ merchant_id: merchants(:fake_user).id,
+ category_id: categories(:cat_one).id
+ }
+ }
+ product.update_attributes(valid_product_data[:product])
+ product.must_be :valid?
+ patch product_path(product), params: valid_product_data
+ end #update
+
+ it "returns not found if the work id is invalid" do
+ product_id = Product.last.id + 1
+ get product_path(product_id)
+ must_respond_with :not_found
+ end #invalid
+ end #all update tests
+
+ describe "destroy" do
+ it "succeeds for an extant work ID" do
+ product_id = Product.first.id
+
+ delete product_path(product_id)
+ must_redirect_to root_path
+
+ Product.find_by(id: product_id).must_be_nil
+ end #success
+
+ it "does not destroy a product that does not exist and renders not found." do
+ start_count = Product.count
+
+ bogus_work_id = Product.last.id + 1
+ delete product_path(bogus_work_id)
+ must_respond_with :not_found
+
+ Product.count.must_equal start_count
+ end #failure
+ end #destroy tests
+ end #logged in
+
+end #all tests
diff --git a/test/controllers/reviews_controller_test.rb b/test/controllers/reviews_controller_test.rb
new file mode 100644
index 0000000000..2aa6d7bcd8
--- /dev/null
+++ b/test/controllers/reviews_controller_test.rb
@@ -0,0 +1,69 @@
+require "test_helper"
+
+describe ReviewsController do
+
+ describe "new" do
+ it "returns success with a valid product_id" do
+ valid_product_id = Product.first.id
+ get new_product_review_path(valid_product_id)
+ must_respond_with :success
+ end #valid id
+
+ it "returns not found in product doesn't exist" do
+ invalid_product_id = Product.last.id + 1
+ get new_product_review_path(invalid_product_id)
+ must_respond_with :not_found
+ end #no product
+ end #new tests
+ # @product = Product.find(params[:product_id])
+ # @review = @product.reviews.build(review_params)
+
+ describe "create" do
+ it "creates a review when data is valid" do
+
+ review_data = {
+ review: {
+ product_id: 1,
+ rating: 3,
+ reviewtext: "review text"
+ }
+ }
+
+ @product = Product.first
+ start_review_count = Review.count
+ a = @product.reviews.build(review_data[:review])
+ a.must_be :valid?
+
+ post product_reviews_path(@product.id), params:review_data
+
+ must_respond_with :redirect
+ must_redirect_to root_path
+
+ Review.count.must_equal start_review_count + 1
+ end #valid data test
+
+ it "will not create a new review when data is invalid" do
+ invalid_review_data = {
+ review: {
+ rating: ""
+ }
+ }
+ start_review_count = Review.count
+
+ @product = Product.first
+ start_review_count = Review.count
+ a = @product.reviews.build(invalid_review_data[:review])
+ a.wont_be :valid?
+
+ post product_reviews_path(@product.id), params:invalid_review_data
+
+ must_respond_with :bad_request
+ # must_redirect_to root_path
+
+ Review.count.must_equal start_review_count
+ end #invalid data test
+ end #create tests
+end #all tests
+# product_reviews GET /products/:product_id/reviews(.:format) reviews#index
+# POST /products/:product_id/reviews(.:format) reviews#create
+# new_product_review GET /products/:product_id/reviews/new(.:format) reviews#new
diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb
new file mode 100644
index 0000000000..053e7a4f0b
--- /dev/null
+++ b/test/controllers/sessions_controller_test.rb
@@ -0,0 +1,111 @@
+require "test_helper"
+
+describe SessionsController do
+ describe "auth_callback" do
+ it "logs in an existing user" do
+ start_count = Merchant.count
+ merchant = merchants(:fake_user)
+
+ login(merchant)
+ must_redirect_to root_path
+ session[:merchant_id].must_equal merchant.id
+
+ # Should *not* have created a new user
+ Merchant.count.must_equal start_count
+ end
+
+ it "creates a new user" do
+ start_count = Merchant.count
+ user = Merchant.new(provider: "github", uid: 99999, username: "test_user", email: "test@user.com")
+
+ OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user))
+ get auth_callback_path(:github)
+
+ must_redirect_to root_path
+
+ # Should have created a new user
+ Merchant.count.must_equal start_count + 1
+
+ # The new user's ID should be set in the session
+ session[:merchant_id].must_equal Merchant.last.id
+ end
+ #
+ # it "redirects to the login route if given invalid user data" do
+ # end
+ it "tells a users that they are already logged in if that is true" do
+
+ end
+ end
+
+ # describe 'login' do
+ # it 'sign in should redirect to root_path' do
+ # fake_user = Merchant.first
+ #
+ # post '/auth/developer/callback', params: {
+ # name: fake_user.username,
+ # email: fake_user.email
+ # }
+ # assert_not_nil @response.cookies[Rails.application.config.session_options[:key]]
+ # assert_equal merchant.id, session[:merchant_id]
+ # assert_redirected_to root_path
+ # end
+
+ # describe "login" do
+ # it "allows a new merchant to log in" do
+ # username = "username"
+ #
+ # Merchant.find_by(username: username).must_be_nil
+ # # should find no merchant with this username
+ #
+ # post login_path, params: { username: username }
+ # # do the actions defined in sessions#create (as defined in routes for login_path) using the information defined in username: username (in this case, username: username)
+ #
+ # must_redirect_to root_path
+ # end
+ #
+ # it "creates " do
+ # skip
+ # end
+ #
+ # it "allows a returning user to log in" do
+ # Merchant.create(username: 'finn', email: 'puppies@kittens.com')
+ # # creates a new merchant in the db
+ # username = Merchant.first.username
+ # # this sets the username as the first existing merchant (that already exists)
+ #
+ # post login_path, params: { username: username }
+ # # (same as test one)
+ # # do the actions defined in sessions#create (as defined in routes for login_path) using the information defined in username: username (in this case, a returning user)
+ #
+ # must_redirect_to root_path
+ # end
+ #
+ # it "renders bad_request if the username entered is blank" do
+ # post login_path, params: { username: "" }
+ #
+ # must_respond_with :bad_request
+ # end
+ #
+ # it "renders bad_request if a merchant is already logged in" do
+ # skip
+ # end
+ # end
+ #
+ # describe "logout" do
+ # it "succeeds if the user is logged in" do
+ # skip
+ # # Gotta be logged in first
+ # post login_path, params: { username: "test user" }
+ # must_redirect_to root_path
+ #
+ # post logout_path
+ # must_redirect_to root_path
+ # end
+ #
+ # it "succeeds if the user is not logged in" do
+ # post logout_path
+ # must_redirect_to root_path
+ # end
+ # end
+ # end
+end
diff --git a/test/fixtures/.keep b/test/fixtures/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test/fixtures/billings.yml b/test/fixtures/billings.yml
new file mode 100644
index 0000000000..2dae520c50
--- /dev/null
+++ b/test/fixtures/billings.yml
@@ -0,0 +1,17 @@
+# # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+#
+
+one:
+ name: Finn Dog
+ street: 1313 Puppy Lane
+ apt: Apt 13
+ city: Seattle
+ state: WA
+ ship_zip: 98101
+ email: finn.dog@gmail.com
+ credit_card: "1111222233334444"
+ exp: 0120
+ cvv: 123
+ bill_zip: 98101
+
+# #
diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml
new file mode 100644
index 0000000000..f626324429
--- /dev/null
+++ b/test/fixtures/categories.yml
@@ -0,0 +1,14 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+
+cat_one:
+ id: 1
+ category_name: Dinner
+
+cat_two:
+ id: 2
+ category_name: Breakfast
+
+cat_three:
+ id: 20
+ category_name: Empty
diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test/fixtures/merchants.yml b/test/fixtures/merchants.yml
new file mode 100644
index 0000000000..e3ac419cd0
--- /dev/null
+++ b/test/fixtures/merchants.yml
@@ -0,0 +1,19 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+# This model initially had no columns defined. If you add columns to the
+# model remove the "{}" from the fixture names and add the columns immediately
+# below each fixture, per the syntax in the comments below
+#
+
+
+fake_user:
+ username: amy
+ email: blah@123.com
+ uid: a_uid
+ provider: github
+
+fake_user2:
+ username: angela
+ email: blah@123.com
+ uid: b_uid
+ provider: github
diff --git a/test/fixtures/order_products.yml b/test/fixtures/order_products.yml
new file mode 100644
index 0000000000..b9c40e9326
--- /dev/null
+++ b/test/fixtures/order_products.yml
@@ -0,0 +1,20 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+op_one:
+ quantity: 1
+ product: fake_product1
+ order: one
+
+op_two:
+ quantity: 1
+ product: fake_product2
+ order: one
+
+op_three:
+ quantity: 2
+ product: fake_product2
+
+op_four:
+ quantity: 1
+ order_id: 1
+ product_id: 1
diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml
new file mode 100644
index 0000000000..309a7b8216
--- /dev/null
+++ b/test/fixtures/orders.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ status: pending
+
+two:
+ status: MyString
diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml
new file mode 100644
index 0000000000..5d83a69cae
--- /dev/null
+++ b/test/fixtures/products.yml
@@ -0,0 +1,17 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+fake_product1:
+ name: MyString
+ description: MyString
+ price: 1
+ stock: 3
+ category_id: 1
+ merchant_id: 1
+
+fake_product2:
+ name: MyString
+ description: MyString
+ price: 1
+ stock: 1
+ category_id: 2
+ merchant_id: 2
diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml
new file mode 100644
index 0000000000..b06217e9fc
--- /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
+ reviewtext: MyString
+
+two:
+ product_id: 1
+ rating: 1
+ reviewtext: MyString
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/models/billing_test.rb b/test/models/billing_test.rb
new file mode 100644
index 0000000000..2bf80429d1
--- /dev/null
+++ b/test/models/billing_test.rb
@@ -0,0 +1,85 @@
+require "test_helper"
+
+describe Billing do
+ before do
+ @billing = billings(:one)
+ end #before billing
+
+ describe 'validate' do
+ it "can be created and required fields cannot be nil" do
+ @billing.must_be_kind_of Billing
+ refute_nil @billing.id
+ refute_nil @billing.name
+ refute_nil @billing.street
+ refute_nil @billing.apt
+ refute_nil @billing.city
+ refute_nil @billing.state
+ refute_nil @billing.ship_zip
+ refute_nil @billing.email
+ refute_nil @billing.credit_card
+ refute_nil @billing.exp
+ refute_nil @billing.cvv
+ refute_nil @billing.bill_zip
+ end #can be created
+
+ it "is invalid if any required fields are missing" do
+ @billing.name = nil
+ @billing.valid?.must_equal false
+
+ @billing.street = nil
+ @billing.valid?.must_equal false
+
+ @billing.city = nil
+ @billing.valid?.must_equal false
+
+ @billing.state = nil
+ @billing.valid?.must_equal false
+
+ @billing.ship_zip = nil
+ @billing.valid?.must_equal false
+
+ @billing.email = nil
+ @billing.valid?.must_equal false
+
+ @billing.credit_card = nil
+ @billing.valid?.must_equal false
+
+ @billing.exp = nil
+ @billing.valid?.must_equal false
+
+ @billing.cvv = nil
+ @billing.valid?.must_equal false
+
+ @billing.bill_zip = nil
+ @billing.valid?.must_equal false
+ end #presence validation
+
+ it "ship_zip must be 5 characters" do
+ @billing.ship_zip = 123
+ @billing.valid?.must_equal false
+ @billing.errors.messages.must_include :ship_zip
+
+ @billing.ship_zip = 12345
+ @billing.valid?.must_equal true
+ end #ship_zip
+
+ it "bill_zip must be 5 characters" do
+ @billing.bill_zip = 123
+ @billing.valid?.must_equal false
+ @billing.errors.messages.must_include :bill_zip
+
+ @billing.bill_zip = 12345
+ @billing.valid?.must_equal true
+ end #bill zip
+
+ it "Credit card number must be 16 characters" do
+ @billing.credit_card = 123456789123456
+ @billing.valid?.must_equal false
+ @billing.errors.messages.must_include :credit_card
+
+ @billing.credit_card = 1234567891234567
+ @billing.valid?.must_equal true
+ end #credit card
+ end #all validations
+
+end #all
diff --git a/test/models/category_test.rb b/test/models/category_test.rb
new file mode 100644
index 0000000000..f505312224
--- /dev/null
+++ b/test/models/category_test.rb
@@ -0,0 +1,39 @@
+require "test_helper"
+#
+
+describe Category do
+ let(:category) { Category.new }
+
+ words = "a" * 30
+ long = "a" * 31
+
+ it "can be created with required fields" do
+ b = Category.new(category_name: "Category")
+ b.must_be :valid?
+ end #can be created
+
+ it "requires a name" do
+ b = Category.new(category_name: "")
+ b.wont_be :valid?
+ b.errors.messages.must_include :category_name
+ end #requires a name
+
+ it "requires a unique name" do
+ name = "test name"
+ b1 = Category.create!(category_name: name)
+ b2 = Category.new(category_name: name)
+
+ b2.wont_be :valid?
+ end #unique name
+
+ it "will allow a name up to 30 characters" do
+ b = Category.new(category_name: words)
+ b.must_be :valid?
+ end
+
+ it "will not accept a name over 30 characters" do
+ b = Category.new(category_name: long)
+ b.wont_be :valid?
+ b.errors.messages.must_include :category_name
+ end
+end
diff --git a/test/models/merchant_test.rb b/test/models/merchant_test.rb
new file mode 100644
index 0000000000..ff5d77d7f6
--- /dev/null
+++ b/test/models/merchant_test.rb
@@ -0,0 +1,9 @@
+require "test_helper"
+
+# describe Merchant do
+# let(:merchant) { Merchant.new }
+#
+# it "must be valid" do
+# value(merchant).must_be :valid?
+# end
+# end
diff --git a/test/models/order_product_test.rb b/test/models/order_product_test.rb
new file mode 100644
index 0000000000..4813f6410d
--- /dev/null
+++ b/test/models/order_product_test.rb
@@ -0,0 +1,19 @@
+require "test_helper"
+
+describe OrderProduct do
+
+ before do
+ @order_product = order_products(:op_four)
+ end
+
+ describe "associations" do
+ it "responds to order" do
+ @order_product.must_respond_to :order
+ end
+
+ it "responds to order" do
+ @order_product.must_respond_to :product
+ end
+ end
+
+end
diff --git a/test/models/order_test.rb b/test/models/order_test.rb
new file mode 100644
index 0000000000..9e5f762088
--- /dev/null
+++ b/test/models/order_test.rb
@@ -0,0 +1,108 @@
+require "test_helper"
+
+describe Order do
+ let(:order) { Order.new }
+
+ describe "validations" do
+ ## no validations currently
+ end
+
+ describe "associations" do
+ it "responds to order_product" do
+ order = Order.first
+ order.must_respond_to :order_products
+ end
+
+ it "responds to product" do
+ order = Order.first
+ order.must_respond_to :products
+ end
+ end
+
+ describe "start new order method" do
+ it "can be created" do
+ start_order_count = Order.count
+ Order.start_new_order
+ Order.count.must_equal start_order_count + 1
+ end
+
+ it "is created with a 'pending' status" do
+ order = Order.start_new_order
+ order.status.must_equal "pending"
+ end
+ end
+
+ describe "find or create cart method" do
+ it "Successfully finds order if order is in session" do
+ new_order = Order.start_new_order
+ order_id = new_order.id
+ order = Order.find_or_create_cart(order_id)
+ order.id.must_equal order_id
+ end
+ it "Creates a new order if no order exist" do
+ order_id = order.id
+ start_order_count = Order.count
+ Order.find_or_create_cart(order_id)
+ Order.count.must_equal start_order_count + 1
+ end
+ end
+
+ describe "subtract_products" do
+ it "returns true when the database is updated" do
+ product1 = products(:fake_product1)
+ product2 = products(:fake_product2)
+
+ op1 = order_products(:op_one)
+ op2 = order_products(:op_two)
+
+ # order = Order.create!(
+ # status: "pending"
+ # )
+
+ op1.order = order
+ op1.save!
+ op2.order = order
+ op2.save!
+
+
+
+ order.subtract_products.must_equal true
+ # use reload when the database has changed and the local variable goes stale e.g. subtract_products updates the database and product1 was not updated.
+ expected_stock = product1.stock - op1.quantity
+ product1.reload
+ product1.stock.must_equal expected_stock
+
+ expected_stock = product2.stock - op2.quantity
+ product2.reload
+ product2.stock.must_equal expected_stock
+
+ end
+
+ it "returns false when the database is not updated for any reason" do
+ # step 1 (set up for the test)
+
+ product1 = products(:fake_product1)
+ product2 = products(:fake_product2)
+
+ op1 = order_products(:op_one)
+ op2 = order_products(:op_three)
+
+ op1.order = order
+ op1.save!
+ op2.order = order
+ op2.save!
+
+ order.subtract_products.must_equal false
+
+ expected_stock = product1.stock
+ product1.reload
+ product1.stock.must_equal expected_stock
+
+
+ expected_stock = product2.stock
+ product2.reload
+ product2.stock.must_equal expected_stock
+
+ end
+ end
+end
diff --git a/test/models/product_test.rb b/test/models/product_test.rb
new file mode 100644
index 0000000000..8b7f1e1839
--- /dev/null
+++ b/test/models/product_test.rb
@@ -0,0 +1,93 @@
+require "test_helper"
+
+describe Product do
+ before do
+ @product = products(:fake_product1)
+ end
+
+ describe 'relationships' do
+ it "responds to merchant" do
+ @product.must_respond_to :merchant
+ end
+
+ it "responds to category" do
+ @product.must_respond_to :category
+ end
+
+ it "responds to order_products" do
+ @product.must_respond_to :order_products
+ end
+
+ it "responds to order" do
+ @product.must_respond_to :orders
+ end
+
+ it "responds to reviews" do
+ @product.must_respond_to :reviews
+ end
+ # ========================= #
+ it "has a merchant" do
+ @product.merchant.id.must_equal 1
+ @product.merchant.must_equal merchants(:fake_user)
+ @product.merchant_id.must_equal merchants(:fake_user).id
+ end
+
+ it "has a category" do
+ @product.category.id.must_equal 1
+ @product.category.must_equal categories(:cat_one)
+ @product.category_id.must_equal categories(:cat_one).id
+ end
+ end
+
+ describe 'validate' do
+ it "can be created and required fields cannot be nil" do
+ @product.must_be_kind_of Product
+
+ refute_nil @product.id
+ refute_nil @product.name
+ refute_nil @product.price
+ refute_nil @product.stock
+ refute_nil @product.merchant_id
+ refute_nil @product.category_id
+ end
+
+ it "is invalid if any required fields are missing" do
+ @product.name = nil
+ @product.valid?.must_equal false
+
+ @product.price = nil
+ @product.valid?.must_equal false
+
+ @product.stock = nil
+ @product.valid?.must_equal false
+
+ @product.merchant_id = nil
+ @product.valid?.must_equal false
+
+ @product.category_id = nil
+ @product.valid?.must_equal false
+ end
+
+ it "requires price to be an integer greater than 0" do
+ @product.price = -1
+ @product.valid?.must_equal false
+ @product.errors.messages.must_include :price
+
+ @product.price = 0
+ @product.valid?.must_equal false
+ @product.errors.messages.must_include :price
+
+ @product.price = 1
+ @product.valid?.must_equal true
+ end
+
+ it "requires stock to be greater than or equal to 0" do
+ @product.stock = -1
+ @product.valid?.must_equal false
+ @product.errors.messages.must_include :stock
+
+ @product.stock = 0
+ @product.valid?.must_equal true
+ end
+ end
+end
diff --git a/test/models/review_test.rb b/test/models/review_test.rb
new file mode 100644
index 0000000000..753c76d4d6
--- /dev/null
+++ b/test/models/review_test.rb
@@ -0,0 +1,32 @@
+require "test_helper"
+
+
+describe Review do
+ let(:review) { Review.new }
+
+ words = "a" * 500
+ long = "a" * 501
+
+ it "can be created with required fields" do
+ b = Review.new(rating: 1, product_id: Product.first.id)
+ b.must_be :valid?
+ end #can be created
+
+ it "can only take an integer between 1 and 5 as a rating" do
+ b = Review.new(rating: 10, product_id: Product.first.id)
+ b.wont_be :valid?
+ b.errors.messages.must_include :rating
+ end
+
+ it "will allow a text review up to 500 characters" do
+ b = Review.new(rating: 1, product_id: Product.first.id, reviewtext: words)
+ b.must_be :valid?
+ end
+
+ it "will not accept a text review over 500 characters" do
+ b = Review.new(rating: 1, product_id: Product.first.id, reviewtext: long)
+ b.wont_be :valid?
+ b.errors.messages.must_include :reviewtext
+ end
+
+end
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..26ceaa0115
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,47 @@
+ENV["RAILS_ENV"] = "test"
+require File.expand_path("../../config/environment", __FILE__)
+require "rails/test_help"
+require "minitest/rails"
+require "minitest/reporters" # for Colorized output
+require 'simplecov'
+SimpleCov.start
+
+# 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...
+ def setup
+ OmniAuth.config.test_mode = true
+ end
+
+ def mock_auth_hash(merchant)
+ return {
+ provider: merchant.provider,
+ uid: merchant.uid,
+ info: {
+ email: merchant.email,
+ nickname: merchant.username
+ }
+ }
+ end
+
+ def login(merchant)
+ OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(merchant))
+ get auth_callback_path(:github)
+ end
+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