diff --git a/Gemfile.lock b/Gemfile.lock index 3e313870..f41ede84 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -81,9 +81,11 @@ GEM marcel (1.0.1) method_source (1.0.0) mini_mime (1.0.3) + mini_portile2 (2.5.3) minitest (5.14.4) nio4r (2.5.7) - nokogiri (1.11.3-x86_64-darwin) + nokogiri (1.11.3) + mini_portile2 (~> 2.5.0) racc (~> 1.4) puma (5.3.0) nio4r (~> 2.0) @@ -141,6 +143,7 @@ GEM PLATFORMS x86_64-darwin-19 + x86_64-linux DEPENDENCIES byebug @@ -151,8 +154,5 @@ DEPENDENCIES sqlite3 (~> 1.4) tzinfo-data -RUBY VERSION - ruby 2.7.3p183 - BUNDLED WITH 2.2.16 diff --git a/app/controllers/movies_controller.rb b/app/controllers/movies_controller.rb index 8a1c0ca9..435f764b 100644 --- a/app/controllers/movies_controller.rb +++ b/app/controllers/movies_controller.rb @@ -7,8 +7,10 @@ def index end def create - movie = Movie.create(movie_params) + movie = Movie.create!(movie_params) render json: movie, status: :created + rescue ActiveRecord::RecordInvalid => e + render json: { errors: e.record.errors.full_messages }, status: :unprocessable_entity end private diff --git a/app/models/movie.rb b/app/models/movie.rb index dc614df1..c33d396a 100644 --- a/app/models/movie.rb +++ b/app/models/movie.rb @@ -1,2 +1,15 @@ class Movie < ApplicationRecord + + CATEGORIES = ['Comedy', 'Drama', 'Animation', 'Mystery', 'Horror', 'Fantasy', 'Action', 'Documentary', 'Science Fiction'] + + validates :title, presence: true + validates :year, numericality: { + greater_than_or_equal_to: 1888, + less_than_or_equal_to: Date.today.year + } + validates :poster_url, presence: true + validates :category, inclusion: { + in: CATEGORIES, + message: "must be one of: #{CATEGORIES.join(', ')}" + } end diff --git a/client/src/components/MovieForm.js b/client/src/components/MovieForm.js index a9d7c97d..2e5e13aa 100644 --- a/client/src/components/MovieForm.js +++ b/client/src/components/MovieForm.js @@ -2,6 +2,8 @@ import { useState } from "react"; import styled from "styled-components"; function MovieForm() { + const [errors, setErrors] = useState([]); + const [formData, setFormData] = useState({ title: "", year: new Date().getFullYear(), @@ -23,9 +25,37 @@ function MovieForm() { }, body: JSON.stringify(formData), }) - .then((response) => response.json()) - .then((newMovie) => console.log(newMovie)); + .then((response) => { + if (response.ok) { + response.json().then((newMovie) => console.log(newMovie)); + } else { + response.json().then((errorData) => setErrors(errorData.errors)); + } + }); + } + //One way we can clean this handleSubmit function using the async/await + /* + // make the function async to enable the await keyword + async function handleSubmit(e) { + e.preventDefault(); + // fetch returns a Promise, we must await it + const response = await fetch("/movies", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(formData), + }); + // response.json() returns a Promise, we must await it + const data = await response.json(); + if (response.ok) { + console.log("Movie created:", data); + } else { + setErrors(data.errors); + } } + */ + function handleChange(e) { const value = @@ -125,6 +155,14 @@ function MovieForm() { /> + + {errors.length > 0 && ( + + )} Add Movie diff --git a/config/database.yml b/config/database.yml index 4a8a1b26..7f6bf9b6 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,25 +1,11 @@ -# SQLite. Versions 3.8.0 and up are supported. -# gem install sqlite3 -# -# Ensure the SQLite 3 gem is defined in your Gemfile -# gem 'sqlite3' -# -default: &default - adapter: sqlite3 - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> - timeout: 5000 - development: - <<: *default + adapter: sqlite3 database: db/development.sqlite3 -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. test: - <<: *default + adapter: sqlite3 database: db/test.sqlite3 production: - <<: *default + adapter: sqlite3 database: db/production.sqlite3