diff --git a/.gitignore b/.gitignore index 4a494a75..3b91322a 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ # Ignore master key for decrypting credentials and more. /config/master.key + +.env \ No newline at end of file diff --git a/app/controllers/movies_controller.rb b/app/controllers/movies_controller.rb index 362e2791..462c1da5 100644 --- a/app/controllers/movies_controller.rb +++ b/app/controllers/movies_controller.rb @@ -5,7 +5,7 @@ def index if params[:query] data = MovieWrapper.search(params[:query]) else - data = Movie.all + data = Movie.all.order('title ASC') end render status: :ok, json: data @@ -16,9 +16,27 @@ def show status: :ok, json: @movie.as_json( only: [:title, :overview, :release_date, :inventory], - methods: [:available_inventory] - ) - ) + methods: [:available_inventory], + ), + ) + end + + def create + movie = Movie.new( + title: params[:title], + overview: params[:overview], + release_date: params[:release_date], + image_url: params[:image_url], + external_id: params[:external_id], + inventory: 3 + ) + + if movie.save + render json: movie.as_json(only: [:id]), status: :created + return + else + render status: :bad_request, json: { errors: movie.errors.messages } + end end private diff --git a/app/controllers/rentals_controller.rb b/app/controllers/rentals_controller.rb index 67e77073..bcc0caac 100644 --- a/app/controllers/rentals_controller.rb +++ b/app/controllers/rentals_controller.rb @@ -6,9 +6,14 @@ class RentalsController < ApplicationController def check_out rental = Rental.new(movie: @movie, customer: @customer, due_date: params[:due_date]) + if @movie.available_inventory < 1 + render status: :bad_request, json: { errors: rental.errors.messages } + return + end + if rental.save render status: :ok, json: {} - else + else render status: :bad_request, json: { errors: rental.errors.messages } end end diff --git a/app/models/movie.rb b/app/models/movie.rb index fda94941..6517a74d 100644 --- a/app/models/movie.rb +++ b/app/models/movie.rb @@ -2,6 +2,8 @@ class Movie < ApplicationRecord has_many :rentals has_many :customers, through: :rentals + validates :external_id, uniqueness: true + def available_inventory self.inventory - Rental.where(movie: self, returned: false).length end diff --git a/config/puma.rb b/config/puma.rb index c7f311f8..f3398437 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -9,7 +9,7 @@ # Specifies the `port` that Puma will listen on to receive requests, default is 3000. # -port ENV.fetch("PORT") { 3000 } +port ENV.fetch("PORT") { 4000 } # Specifies the `environment` that Puma will run in. # diff --git a/config/routes.rb b/config/routes.rb index f4c99688..76715f9a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,7 +3,7 @@ resources :customers, only: [:index] - resources :movies, only: [:index, :show], param: :title + resources :movies, only: [:index, :show, :create], param: :title post "/rentals/:title/check-out", to: "rentals#check_out", as: "check_out" post "/rentals/:title/return", to: "rentals#check_in", as: "check_in" diff --git a/db/schema.rb b/db/schema.rb index ffb28f7e..c97444b1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,48 +2,51 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). +# This file is the source Rails uses to define your schema when running `rails +# db:schema:load`. When creating a new database, `rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180618042754) do +ActiveRecord::Schema.define(version: 2018_06_18_042754) do - create_table "customers", force: :cascade do |t| - t.string "name" + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "customers", id: :serial, force: :cascade do |t| + t.string "name" t.datetime "registered_at" - t.string "address" - t.string "city" - t.string "state" - t.string "postal_code" - t.string "phone" - t.float "account_credit" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "address" + t.string "city" + t.string "state" + t.string "postal_code" + t.string "phone" + t.float "account_credit" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "movies", force: :cascade do |t| - t.string "title" - t.text "overview" - t.date "release_date" - t.integer "inventory" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "image_url" - t.integer "external_id" + create_table "movies", id: :serial, force: :cascade do |t| + t.string "title" + t.text "overview" + t.date "release_date" + t.integer "inventory" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "image_url" + t.integer "external_id" end - create_table "rentals", force: :cascade do |t| - t.integer "customer_id" - t.integer "movie_id" - t.date "checkout_date" - t.date "due_date" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "returned" + create_table "rentals", id: :serial, force: :cascade do |t| + t.integer "customer_id" + t.integer "movie_id" + t.date "checkout_date" + t.date "due_date" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "returned" t.index ["customer_id"], name: "index_rentals_on_customer_id" t.index ["movie_id"], name: "index_rentals_on_movie_id" end diff --git a/test/controllers/movies_controller_test.rb b/test/controllers/movies_controller_test.rb index 9172cf6e..5489216e 100644 --- a/test/controllers/movies_controller_test.rb +++ b/test/controllers/movies_controller_test.rb @@ -1,4 +1,5 @@ require 'test_helper' +require 'pry' class MoviesControllerTest < ActionDispatch::IntegrationTest describe "index" do @@ -75,4 +76,40 @@ class MoviesControllerTest < ActionDispatch::IntegrationTest end end + + describe "create" do + it "Returns a JSON object and 201 created status for new movies from external db with valid params" do + new_movie_params = { + title: "Our test movie", + overview: "Awesome times ahead", + release_date: Date.today, + external_id: 38583, + image_url: "test url string for url" + } + + expect { post movies_url, params: new_movie_params }.must_differ "Movie.count", 1 + must_respond_with :created + expect(response.header['Content-Type']).must_include 'json' + + # Attempt to parse + data = JSON.parse response.body + data.must_be_kind_of Hash + end + + + it "Returns a JSON object with errors and 400 bad request status if movie already exists" do + duplicate_movie_params = { + title: "WowMovie!", + overview: "MyText", + release_date: "2017-01-11", + external_id: 16373 + } + + expect { post movies_url, params: duplicate_movie_params }.wont_change "Movie.count" + must_respond_with :bad_request + expect(response.header['Content-Type']).must_include 'json' + expect(response.body).must_include "external_id" + expect(response.body).must_include "has already been taken" + end + end end diff --git a/test/controllers/rentals_controller_test.rb b/test/controllers/rentals_controller_test.rb index 831b5230..379a33d3 100644 --- a/test/controllers/rentals_controller_test.rb +++ b/test/controllers/rentals_controller_test.rb @@ -115,11 +115,6 @@ class RentalsControllerTest < ActionDispatch::IntegrationTest expect(rental.movie_id).must_equal movie.id expect(rental.due_date).must_equal Date.today + 5 expect(rental.returned).must_equal true - - - - - end it "requires a valid movie title" do diff --git a/test/fixtures/movies.yml b/test/fixtures/movies.yml index caf6e68b..77320b9c 100644 --- a/test/fixtures/movies.yml +++ b/test/fixtures/movies.yml @@ -5,9 +5,11 @@ one: overview: MyText release_date: 2017-01-11 inventory: 4 + external_id: 16373 two: title: MuchFilm overview: MyText release_date: 2017-01-11 inventory: 7 + external_id: 21111