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
47 changes: 47 additions & 0 deletions app/controllers/videos_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,59 @@ def show
)
end

# Adds a video from the external API to the library
def add_to_library
if params[:id]
begin
video = VideoWrapper.get_movie(params[:id])
unless params[:inventory].to_i > 0
render_error("Invalid inventory given", :bad_request)
return
end
video&.inventory = params[:inventory]
rescue ArgumentError
render_error("Unspecified API error", :bad_request)
return
end

if video # If the movie was found
if video.save # If the video saves
render json: {
ok: true,
id: video.id
}, status: :created
return
else # If the video doesn't save
render_error(video.errors.messages, :bad_request)
return
end
else # If the movie wasn't found
render_error("Movie was not found from external API", :not_found)
return
end
else # If no ID given
render_error("No ID given", :bad_request)
return
end
end

private

def render_error(error, status)
render json: {
ok: false,
errors: error
}, status: status
end

def require_video
@video = Video.find_by(title: params[:title])
unless @video
render status: :not_found, json: { errors: { title: ["No video with title #{params["title"]}"] } }
end
end

def video_params
return params.permit(:title, :overview, :release_date, :inventory)
end
end
1 change: 1 addition & 0 deletions app/models/video.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Video < ApplicationRecord
has_many :rentals
has_many :customers, through: :rentals
validates :title, uniqueness: true

def available_inventory
self.inventory - self.rentals.where(returned: false).length
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
resources :customers, only: [:index]

resources :videos, only: [:index, :show], param: :title
post "/videos/:id/:inventory", to: "videos#add_to_library", as: "add_to_library"

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
22 changes: 22 additions & 0 deletions lib/video_wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,28 @@ def self.search(query, retries_left=3)
end
end

# Gets a movie from tmDB by ID
# Returns video object or nil if not found
def self.get_movie(id, retries_left=3)
raise ArgumentError.new("Can't search without a MOVIEDB_KEY. Please check your .env file!") unless KEY

url = BASE_URL + "movie/" + id.to_s + "?api_key=" + KEY

response = HTTParty.get(url)

if response.success?
return self.construct_video(response)
elsif response["status_code"] == 34 # No movie by that ID
return nil
elsif retries_left > 0
sleep(1.0 / (2 ** retries_left))

return self.get_movie(query, retries_left - 1)
else
raise ArgumentError.new("Request failed: #{url}")
end
end

private

def self.construct_video(api_result)
Expand Down
44 changes: 44 additions & 0 deletions test/controllers/videos_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,48 @@ class VideosControllerTest < ActionDispatch::IntegrationTest
expect(data["errors"]).must_include "title"
end
end

describe "add to library" do
it "can add a video to the library successfully" do
post add_to_library_path(id: 568160, inventory: 1)
assert_response :success

response = JSON.parse @response.body

expect(response["ok"]).must_equal true
expect(Video.find_by(id:response["id"]).title).must_equal "Weathering with You"
end

it "does not add a duplicate video to the library" do
post add_to_library_path(id: 568160, inventory: 1)
post add_to_library_path(id: 568160, inventory: 1)

assert_response :bad_request

response = JSON.parse @response.body
expect(response["ok"]).must_equal false
expect(response["errors"]["title"]).must_equal ["has already been taken"]
end

it "does not add a video if not found in external API" do
post add_to_library_path(id: 1, inventory: 1)

assert_response :not_found

response = JSON.parse @response.body
expect(response["ok"]).must_equal false
expect(response["errors"]).must_equal "Movie was not found from external API"
end

it "does not add a video with invalid inventory" do
post add_to_library_path(id: 568160, inventory: -1)

assert_response :bad_request

response = JSON.parse @response.body
expect(response["ok"]).must_equal false
expect(response["errors"]).must_equal "Invalid inventory given"
end

end
end