From 1a153eb3f69b93bb7877dba337e32f718b9fe2ec Mon Sep 17 00:00:00 2001 From: Beatrice T Date: Tue, 19 Jan 2021 23:22:05 -0800 Subject: [PATCH 1/3] Can add videos from external API to library --- app/controllers/videos_controller.rb | 46 ++++++++++++++++++++++++++++ config/routes.rb | 1 + lib/video_wrapper.rb | 24 +++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/app/controllers/videos_controller.rb b/app/controllers/videos_controller.rb index c9a2bb08..633fc574 100644 --- a/app/controllers/videos_controller.rb +++ b/app/controllers/videos_controller.rb @@ -21,12 +21,58 @@ 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) + 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 diff --git a/config/routes.rb b/config/routes.rb index 16fc2214..ed2dd3cc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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" diff --git a/lib/video_wrapper.rb b/lib/video_wrapper.rb index bce82b99..27dd2c85 100644 --- a/lib/video_wrapper.rb +++ b/lib/video_wrapper.rb @@ -31,6 +31,30 @@ 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 + + puts url + + 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) From 96e3d64d6132e0e4e5e00ebd35216104095327aa Mon Sep 17 00:00:00 2001 From: Beatrice T Date: Wed, 20 Jan 2021 11:28:51 -0800 Subject: [PATCH 2/3] Added validation to prevent duplicate videos --- app/models/video.rb | 1 + lib/video_wrapper.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/video.rb b/app/models/video.rb index f47b7f0b..1feeadc4 100644 --- a/app/models/video.rb +++ b/app/models/video.rb @@ -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 diff --git a/lib/video_wrapper.rb b/lib/video_wrapper.rb index 27dd2c85..7effdb64 100644 --- a/lib/video_wrapper.rb +++ b/lib/video_wrapper.rb @@ -40,7 +40,7 @@ def self.get_movie(id, retries_left=3) puts url - response = HTTParty.get(url) + response = HTTParty.get(url) if response.success? return self.construct_video(response) From b15a1c7793774645a913e22691f1242f714c949e Mon Sep 17 00:00:00 2001 From: Beatrice T Date: Thu, 21 Jan 2021 15:59:47 -0800 Subject: [PATCH 3/3] Controller tests for video#add_to_library added --- app/controllers/videos_controller.rb | 3 +- lib/video_wrapper.rb | 2 - test/controllers/videos_controller_test.rb | 44 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/app/controllers/videos_controller.rb b/app/controllers/videos_controller.rb index 633fc574..2d6d2cda 100644 --- a/app/controllers/videos_controller.rb +++ b/app/controllers/videos_controller.rb @@ -28,8 +28,9 @@ def add_to_library 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] + video&.inventory = params[:inventory] rescue ArgumentError render_error("Unspecified API error", :bad_request) return diff --git a/lib/video_wrapper.rb b/lib/video_wrapper.rb index 7effdb64..3a3a7f48 100644 --- a/lib/video_wrapper.rb +++ b/lib/video_wrapper.rb @@ -38,8 +38,6 @@ def self.get_movie(id, retries_left=3) url = BASE_URL + "movie/" + id.to_s + "?api_key=" + KEY - puts url - response = HTTParty.get(url) if response.success? diff --git a/test/controllers/videos_controller_test.rb b/test/controllers/videos_controller_test.rb index 730915ed..e9d51713 100644 --- a/test/controllers/videos_controller_test.rb +++ b/test/controllers/videos_controller_test.rb @@ -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