diff --git a/Gemfile b/Gemfile index 25fddaae..7159c815 100644 --- a/Gemfile +++ b/Gemfile @@ -49,6 +49,7 @@ gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] group :development, :test do gem 'pry-rails' + gem 'dotenv-rails' end group :development do diff --git a/app/controllers/customers_controller.rb b/app/controllers/customers_controller.rb index be25f1be..3b1b7918 100644 --- a/app/controllers/customers_controller.rb +++ b/app/controllers/customers_controller.rb @@ -18,6 +18,30 @@ def index ) end + def show + @customer = Customer.find_by(id: params[:id]) + + if @customer + @customer_rentals = @customer.rentals.map{|rental| { + title: rental.movie.title, + checkout_date: rental.checkout_date, + due_date: rental.due_date, + status: rental.returned, + }} + render json: + @customer_rentals.as_json(), + status: :ok + return + else + render json: { + errors: [ + 'Customer Not Found' + ] + }, status: :not_found + return + end + end + private def parse_query_args errors = {} diff --git a/app/controllers/movies_controller.rb b/app/controllers/movies_controller.rb index 362e2791..20cb85ae 100644 --- a/app/controllers/movies_controller.rb +++ b/app/controllers/movies_controller.rb @@ -20,6 +20,22 @@ def show ) ) end + + def create + movie = Movie.new(movie_params) + + if movie.save + render json: movie.as_json(only: [:id]), status: :ok + return + else + render json: { + ok: false, + errors: movie.errors.messages + }, + status: :bad_request + return + end + end private @@ -29,4 +45,8 @@ def require_movie render status: :not_found, json: { errors: { title: ["No movie with title #{params["title"]}"] } } end end + + def movie_params + params.permit(:title, :overview, :release_date, :image_url, :external_id) + end end diff --git a/app/controllers/rentals_controller.rb b/app/controllers/rentals_controller.rb index 67e77073..d56db346 100644 --- a/app/controllers/rentals_controller.rb +++ b/app/controllers/rentals_controller.rb @@ -4,7 +4,8 @@ class RentalsController < ApplicationController # TODO: make sure that wave 2 works all the way def check_out - rental = Rental.new(movie: @movie, customer: @customer, due_date: params[:due_date]) + rental = Rental.new(movie: @movie, customer: @customer) + rental.due_date = Date.today + 7.days if rental.save render status: :ok, json: {} diff --git a/app/models/movie.rb b/app/models/movie.rb index fda94941..7a589c1c 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, presence: true, uniqueness: true + def available_inventory self.inventory - Rental.where(movie: self, returned: false).length end diff --git a/config/routes.rb b/config/routes.rb index f4c99688..593e5f15 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,9 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html - resources :customers, only: [:index] + resources :customers, only: [:index, :show] - 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/test/controllers/movies_controller_test.rb b/test/controllers/movies_controller_test.rb index 9172cf6e..6ef9b5b4 100644 --- a/test/controllers/movies_controller_test.rb +++ b/test/controllers/movies_controller_test.rb @@ -1,6 +1,15 @@ require 'test_helper' class MoviesControllerTest < ActionDispatch::IntegrationTest + def check_response(expected_type: ,expected_status: :success) + must_respond_with expected_status + expect(response.header['Content-Type']).must_include 'json' + + body = JSON.parse(response.body) + expect(body).must_be_kind_of expected_type + return body + end + describe "index" do it "returns a JSON array" do get movies_url @@ -75,4 +84,52 @@ class MoviesControllerTest < ActionDispatch::IntegrationTest end end + + describe 'create' do + let(:movies_data) { + { + + title: 'Harry Potter 3', + overview: 'The best movie ever!', + release_date: 'Wed, 22 Jun 1960', + inventory: 10, + image_url: "some image", + external_id: 1547, + } + } + + it 'can create a new movies' do + expect { + post movies_path, params: movies_data + }.must_differ 'Movie.count', 1 + + check_response(expected_type: Hash, expected_status: :ok) + end + + it 'will respond with bad_request for invalid data' do + movies_data[:external_id] = nil + + expect { + post movies_path, params: movies_data + }.wont_change "Movie.count" + body = check_response(expected_type: Hash, expected_status: :bad_request) + expect(body["errors"].keys).must_include 'external_id' + end + + it 'cannot be added twice for the same movie' do + first_count = Movie.count + + expect { + post movies_path, params: movies_data + }.must_differ 'Movie.count', 1 + + second_count = Movie.count + + expect { + post movies_path, params: movies_data + }.wont_change 'Movie.count' + + end + end + end diff --git a/test/models/movie_test.rb b/test/models/movie_test.rb index 70b6a7c6..f89eb62c 100644 --- a/test/models/movie_test.rb +++ b/test/models/movie_test.rb @@ -6,7 +6,8 @@ class MovieTest < ActiveSupport::TestCase "title": "Hidden Figures", "overview": "Some text", "release_date": "1960-06-16", - "inventory": 8 + "inventory": 8, + "external_id": 1233454, } } @@ -78,4 +79,27 @@ class MovieTest < ActiveSupport::TestCase after_ai.must_equal before_ai + 1 end end + + describe 'validations' do + it 'is valid when all the required fields are provided' do + new_movie = Movie.new( + title: 'Harry Potter 3', + overview: 'The best movie ever!', + release_date: 'Wed, 22 Jun 1960', + inventory: 10, + image_url: "some image", + external_id: 15482656, + ) + + expect(new_movie.valid?).must_equal true + end + + it 'fails validation when there is one or more required field is missing' do + @movie.external_id = nil + + expect(@movie.valid?).must_equal false + expect(@movie.errors.messages).must_include :external_id + + end + end end