diff --git a/.generators b/.generators new file mode 100644 index 00000000..16189766 --- /dev/null +++ b/.generators @@ -0,0 +1,8 @@ + + diff --git a/.idea/.generators b/.idea/.generators new file mode 100644 index 00000000..16189766 --- /dev/null +++ b/.idea/.generators @@ -0,0 +1,8 @@ + + diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..8bf4d45d --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,6 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.rakeTasks b/.idea/.rakeTasks new file mode 100644 index 00000000..c6865d9a --- /dev/null +++ b/.idea/.rakeTasks @@ -0,0 +1,7 @@ + + diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..510e7fcc --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..f00f0a95 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/video-store-consumer-api.iml b/.idea/video-store-consumer-api.iml new file mode 100644 index 00000000..f72e8960 --- /dev/null +++ b/.idea/video-store-consumer-api.iml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/controllers/videos_controller.rb b/app/controllers/videos_controller.rb index c9a2bb08..6ba4cb5b 100644 --- a/app/controllers/videos_controller.rb +++ b/app/controllers/videos_controller.rb @@ -2,11 +2,11 @@ class VideosController < ApplicationController before_action :require_video, only: [:show] def index - if params[:query] - data = VideoWrapper.search(params[:query]) + data = if params[:query] + VideoWrapper.search(params[:query]) else - data = Video.all - end + Video.all + end render status: :ok, json: data end @@ -15,18 +15,40 @@ def show render( status: :ok, json: @video.as_json( - only: [:title, :overview, :release_date, :inventory], + only: %i[title overview release_date inventory], methods: [:available_inventory] ) ) end + def create + video = Video.new(video_params) + result = video.save + if result + render( + status: :ok, + json: result.as_json( + only: %i[title overview release_date inventory], + methods: [:available_inventory] + ) + ) + else + render status: :bad_request, json: { + errors: video.errors.messages + } + end + end + private 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"]}"] } } + render status: :not_found, json: { errors: { title: ["No video with title #{params['title']}"] } } end end + + def video_params + return params.permit(:title, :release_date, :overview, :inventory, :image_url, :external_id) + end end diff --git a/app/models/video.rb b/app/models/video.rb index f47b7f0b..3d6e3062 100644 --- a/app/models/video.rb +++ b/app/models/video.rb @@ -2,6 +2,9 @@ class Video < ApplicationRecord has_many :rentals has_many :customers, through: :rentals + validates :external_id, uniqueness: true + validates :title, presence: true + def available_inventory self.inventory - self.rentals.where(returned: false).length end diff --git a/config/routes.rb b/config/routes.rb index 16fc2214..1111b4bf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,7 +3,7 @@ resources :customers, only: [:index] - resources :videos, only: [:index, :show], param: :title + resources :videos, 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/videos_controller_test.rb b/test/controllers/videos_controller_test.rb index 730915ed..ed3834dd 100644 --- a/test/controllers/videos_controller_test.rb +++ b/test/controllers/videos_controller_test.rb @@ -1,6 +1,7 @@ require 'test_helper' class VideosControllerTest < ActionDispatch::IntegrationTest + describe "index" do it "returns a JSON array" do get videos_url @@ -77,4 +78,45 @@ class VideosControllerTest < ActionDispatch::IntegrationTest expect(data["errors"]).must_include "title" end end + + describe "create" do + it "creates a video" do + video1 = { + "title": 'Hidden Figures', + "overview": 'Some text', + "release_date": '1960-06-16', + "inventory": 8, + "external_id": 99999 + } + + expect { + post videos_path, params: video1 + }.must_differ "Video.count", 1 + end + + it "won't add duplicate videos" do + video1 = { + "title": 'Hidden Figures', + "overview": 'Some text', + "release_date": '1960-06-16', + "inventory": 8, + "external_id": 99999 + } + + post videos_path, params: video1 + + video2 = { + "title": 'Video', + "overview": 'Some new text', + "release_date": '1990-06-16', + "inventory": 4, + "external_id": 99999 + } + + expect { + post videos_path, params: video2 + }.wont_differ "Video.count" + end + end + end diff --git a/test/models/video_test.rb b/test/models/video_test.rb index b440a490..5abfeda8 100644 --- a/test/models/video_test.rb +++ b/test/models/video_test.rb @@ -1,34 +1,46 @@ require 'test_helper' class VideoTest < ActiveSupport::TestCase - let (:video_data) { + let (:video_data1) { { - "title": "Hidden Figures", - "overview": "Some text", - "release_date": "1960-06-16", - "inventory": 8 + "title": 'Hidden Figures', + "overview": 'Some text', + "release_date": '1960-06-16', + "inventory": 8, + "external_id": 99999 + } + } + + let (:video_data2) { + { + "title": 'Video', + "overview": 'Some new text', + "release_date": '1990-06-16', + "inventory": 3, + "external_id": 99999 } } before do - @video = Video.new(video_data) + @video = Video.new(video_data1) + @video2 = Video.new(video_data2) end - describe "Constructor" do - it "Can be created" do - Video.create!(video_data) + describe 'Constructor' do + it 'Can be created' do + Video.create!(video_data1) end - it "Has rentals" do + it 'Has rentals' do expect(@video).must_respond_to :rentals end - it "Has customers" do + it 'Has customers' do expect(@video).must_respond_to :customers end end - describe "available_inventory" do + describe 'available_inventory' do it "Matches inventory if the video isn't checked out" do # Make sure no videos are checked out Rental.destroy_all @@ -37,7 +49,7 @@ class VideoTest < ActiveSupport::TestCase end end - it "Decreases when a video is checked out" do + it 'Decreases when a video is checked out' do Rental.destroy_all video = videos(:one) @@ -55,7 +67,7 @@ class VideoTest < ActiveSupport::TestCase expect(after_ai).must_equal before_ai - 1 end - it "Increases when a video is checked in" do + it 'Increases when a video is checked in' do Rental.destroy_all video = videos(:one) @@ -78,4 +90,20 @@ class VideoTest < ActiveSupport::TestCase expect(after_ai).must_equal before_ai + 1 end end + + describe 'validations' do + it 'external ids must be unique' do + video1 = Video.create(video_data1) + video2 = Video.create(video_data2) + expect(video1.valid?).must_equal true + expect(video2.valid?).must_equal false + + end + + it 'title must not be blank' do + @video.title = '' + assert_not @video.valid? + end + + end end