Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions app/controllers/customers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand Down
20 changes: 20 additions & 0 deletions app/controllers/movies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
3 changes: 2 additions & 1 deletion app/controllers/rentals_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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: {}
Expand Down
2 changes: 2 additions & 0 deletions app/models/movie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
57 changes: 57 additions & 0 deletions test/controllers/movies_controller_test.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
26 changes: 25 additions & 1 deletion test/models/movie_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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