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
18 changes: 9 additions & 9 deletions app/controllers/customers_controller.rb
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
class CustomersController < ApplicationController
SORT_FIELDS = %w(name registered_at postal_code)

before_action :parse_query_args

def index
if @sort
data = Customer.all.order(@sort)
else
data = Customer.all
end

data = data.paginate(page: params[:p], per_page: params[:n])

render json: data.as_json(
only: [:id, :name, :registered_at, :address, :city, :state, :postal_code, :phone, :account_credit],
methods: [:movies_checked_out_count]
only: [:id, :name, :registered_at, :address, :city, :state, :postal_code, :phone, :account_credit],
methods: [:movies_checked_out_count]
)
end

private
private
def parse_query_args
errors = {}
@sort = params[:sort]
if @sort and not SORT_FIELDS.include? @sort
errors[:sort] = ["Invalid sort field '#{@sort}'"]
end

unless errors.empty?
render status: :bad_request, json: { errors: errors }
end
Expand Down
55 changes: 52 additions & 3 deletions app/controllers/movies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,56 @@ def index
if params[:query]
data = MovieWrapper.search(params[:query])
else
data = Movie.all
data = Movie.all.order("title")
end

render status: :ok, json: data
end

def show
if @movie
render(
status: :ok,
json: @movie.as_json(
only: [:title, :overview, :release_date, :inventory],
methods: [:available_inventory]
)
)
else
render(
status: :not_found
)
end
end

def create
@movie = Movie.find_by title: params[:title]
if @movie
render status: :bad_request, json: { errors: { title: ["Rental library already has movie with title #{params[:title]}"] } }
else
@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: params["inventory"]
)
if @movie.save
render json: @movie.as_json, status: :ok
return
else
render json: { errors: { title: ["Failed to save to rental library"] } }, status: :bad_request
return
end
end

render(
status: :ok,
json: @movie.as_json(
only: [:title, :overview, :release_date, :inventory],
methods: [:available_inventory]
)
)
)
end

private
Expand All @@ -29,4 +65,17 @@ def require_movie
render status: :not_found, json: { errors: { title: ["No movie with title #{params["title"]}"] } }
end
end

def parse_query_args
errors = {}
@sort = params[:sort]
if @sort and not SORT_FIELDS.include? @sort
errors[:sort] = ["Invalid sort field '#{@sort}'"]
end

unless errors.empty?
render status: :bad_request, json: { errors: errors }
end
end

end
93 changes: 54 additions & 39 deletions app/controllers/rentals_controller.rb
Original file line number Diff line number Diff line change
@@ -1,62 +1,77 @@
class RentalsController < ApplicationController
before_action :require_movie, only: [:check_out, :check_in]
before_action :require_customer, only: [:check_out, :check_in]

# 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])

if rental.save
render status: :ok, json: {}
else
render status: :bad_request, json: { errors: rental.errors.messages }
end
end

def check_in
rental = Rental.first_outstanding(@movie, @customer)
unless rental
return render status: :not_found, json: {
errors: {
rental: ["Customer #{@customer.id} does not have #{@movie.title} checked out"]
}
}
end
rental.returned = true
if rental.save
render status: :ok, json: {}
else
render status: :bad_request, json: { errors: rental.errors.messages }
end
end
errors: {
rental: ["Customer #{@customer.id} does not have #{@movie.title} checked out"]
}
}
end
rental.returned = true
if rental.save
render status: :ok, json: {}
else
render status: :bad_request, json: { errors: rental.errors.messages }
end
end

def overdue
rentals = Rental.overdue.map do |rental|
{
title: rental.movie.title,
customer_id: rental.customer_id,
name: rental.customer.name,
postal_code: rental.customer.postal_code,
checkout_date: rental.checkout_date,
due_date: rental.due_date
}
end
render status: :ok, json: rentals
end
def overdue
rentals = Rental.overdue.map do |rental|
{
title: rental.movie.title,
customer_id: rental.customer_id,
name: rental.customer.name,
postal_code: rental.customer.postal_code,
checkout_date: rental.checkout_date,
due_date: rental.due_date
}
end
render status: :ok, json: rentals
end

def cust_rentals
customer_rentals = Rental.rentals_by_customer(params[:customer_id]).map do |rental|
{
title: rental.movie.title,
customer_id: rental.customer_id,
name: rental.customer.name,
postal_code: rental.customer.postal_code,
checkout_date: rental.checkout_date,
due_date: rental.due_date
}
end
render status: :ok, json: customer_rentals

end

private
# TODO: make error payloads arrays
def require_movie
@movie = Movie.find_by title: params[:title]
unless @movie
render status: :not_found, json: { errors: { title: ["No movie with title #{params[:title]}"] } }
end
# TODO: make error payloads arrays
def require_movie
@movie = Movie.find_by title: params[:title]
unless @movie
render status: :not_found, json: { errors: { title: ["No movie with title #{params[:title]}"] } }
end
end

def require_customer
@customer = Customer.find_by id: params[:customer_id]
unless @customer
render status: :not_found, json: { errors: { customer_id: ["No such customer #{params[:customer_id]}"] } }
end
def require_customer
@customer = Customer.find_by id: params[:customer_id]
unless @customer
render status: :not_found, json: { errors: { customer_id: ["No such customer #{params[:customer_id]}"] } }
end
end
end
22 changes: 13 additions & 9 deletions app/models/rental.rb
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
class Rental < ApplicationRecord
belongs_to :movie
belongs_to :customer

# validates :movie, uniqueness: { scope: :customer }
validates :due_date, presence: true
validate :due_date_in_future, on: :create

after_initialize :set_checkout_date
after_initialize :set_returned


def self.first_outstanding(movie, customer)
self.where(movie: movie, customer: customer, returned: false).order(:due_date).first
end

def self.overdue
self.where(returned: false).where("due_date < ?", Date.today)
end

private

def self.rentals_by_customer(customer)
self.where(customer_id: customer).where(returned: false)
end

private
def due_date_in_future
return unless self.due_date
unless due_date > Date.today
errors.add(:due_date, "Must be in the future")
end
end

def set_checkout_date
self.checkout_date ||= Date.today
end

def set_returned
self.returned ||= false
end
Expand Down
12 changes: 7 additions & 5 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
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 :movies, only: [:index, :show], param: :title

get "/movies/search/:query", to: "movies#index"
post "/movies", to: "movies#create"
post "/rentals/:title/check-out", to: "rentals#check_out", as: "check_out"
post "/rentals/:title/return", to: "rentals#check_in", as: "check_in"
get "/rentals/overdue", to: "rentals#overdue", as: "overdue"

get "/rentals/cust_rentals", to: "rentals#cust_rentals"

root 'movies#index'

end
8 changes: 7 additions & 1 deletion db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@

JSON.parse(File.read('db/seeds/movies.json')).each do |movie_data|
sleep(0.1) # Sleep to avoid hammering the API.

movies = MovieWrapper.search(movie_data["title"])
ap "#{movie_data['title']} Added to the library!"
movies.first.inventory = movie_data['inventory']
movies.first.save unless movies.empty?
end

rental_data = JSON.parse(File.read('db/seeds/rentals.json'))

rental_data.each do |rental|
Rental.new(rental).save(validate: false)
end
52 changes: 52 additions & 0 deletions db/seeds/rentals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"customer_id": 178,
"movie_id": 1,
"due_date": "Mon, 16 Dec 2019"
},
{
"customer_id": 178,
"movie_id": 2,
"due_date": "Tue, 24 Dec 2019"
},
{
"customer_id": 178,
"movie_id": 3,
"due_date": "Sat, 20 Dec 2019"
},
{
"customer_id": 159,
"movie_id": 10,
"due_date": "Tue, 10 Dec 2019"
},
{
"customer_id": 159,
"movie_id": 5,
"due_date": "Wed, 01 Jan 2020"
},
{
"customer_id": 159,
"movie_id": 11,
"due_date": "Sun, 15 Dec 2019"
},
{
"customer_id": 155,
"movie_id": 2,
"due_date": "Fri, 27 Dec 2019"
},
{
"customer_id": 155,
"movie_id": 8,
"due_date": "Mon, 30 Dec 2019"
},
{
"customer_id": 46,
"movie_id": 6,
"due_date": "Sat, 04 Jan 2020"
},
{
"customer_id": 146,
"movie_id": 4,
"due_date": "Sun, 05 Jan 2020"
}
]