Skip to content

Validation Messages and Error Handling #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -141,6 +143,7 @@ GEM

PLATFORMS
x86_64-darwin-19
x86_64-linux

DEPENDENCIES
byebug
Expand All @@ -151,8 +154,5 @@ DEPENDENCIES
sqlite3 (~> 1.4)
tzinfo-data

RUBY VERSION
ruby 2.7.3p183

BUNDLED WITH
2.2.16
4 changes: 3 additions & 1 deletion app/controllers/movies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions app/models/movie.rb
Original file line number Diff line number Diff line change
@@ -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
42 changes: 40 additions & 2 deletions client/src/components/MovieForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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 =
Expand Down Expand Up @@ -125,6 +155,14 @@ function MovieForm() {
/>
</label>
</FormGroup>

{errors.length > 0 && (
<ul style={{ color: "red" }}>
{errors.map((error) => (
<li key={error}>{error}</li>
))}
</ul>
)}
<SubmitButton type="submit">Add Movie</SubmitButton>
</form>
</Wrapper>
Expand Down
20 changes: 3 additions & 17 deletions config/database.yml
Original file line number Diff line number Diff line change
@@ -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