Invalid Records History
Reminder: to run the rails console, you need to run either
rails c
orrails console
in the terminal to prompt, even though it ispry
you cannot just runpry
in the terminal to get it started, you will need to run the other one to make sure that all you models and tables are being queried correctly.
As soon as you start serving data from external sources (ex. users, CSVs, or APIs) you have to start worrying about whether that data is valid
If you do encounter invalid records and they become apart of your database, you will have to begin writing your code defensively, utilizing
if/elsif/else/end
, just to guard against the invalid data.It’s best not to allow invalid data that doesn’t meet our criteria to enter our database in the first place; then, we don’t need to worry about writing lots of defensive conditionals downstream in our code
ActiveRecord provides the feature: validations
Validations are a way that we can specify constraints on what we allow in each column in a model. It is crucial that we have the
.save
method, this will allow us not to place records into the database we don't want to. Thus, returning to usfalse
Validations are a super-useful tool that ActiveRecord provides for maintaining the integrity of our data.
How to Insert Validations in Models
question to address
let’s say we don’t want to allow any rows to enter our movies table with a blank director_id
attribute.
how to fix & add validations
to address this problem we want to move into the Movie
model insert a Validation inside of it.
class Movie < ApplicationRecord
validates(:director_id, presence: true)
def director
# ...
end
The first argument to validates is a Symbol; the name of the column we are declaring constraints for.
The second argument to validates is a Hash.
The keys in the Hash are the constraints we are applying. There is a fixed list of constraints built-in to ActiveRecord that we can choose from. By far, the three most common are :presence, :uniqueness, and :numericality.
the value that we are adding to either
true
, which would allow you wanting the simplest use of validation. On the other hand, you can also have a hash in there clarifying the configuration options, like whether you want want the:numerically
validation to have maximum or minimum
Testing our New Validations with Tests
type these commands inot the
rails console
termnialm = Movie.new
creating a new instance of a moviethe return value should look something like this
[1] pry(main)> m = Movie.new
(0.4ms) SELECT sqlite_version(*)
=> #<Movie:0x00007f93ab387430
id: nil,
title: nil,
year: nil,
duration: nil,
description: nil,
image: nil,
director_id: nil,
created_at: nil,
updated_at: nil>
next, we will type
m.save
, which if done correctly should return afalse
-
we can double check that its not in there by typing
m
into the console again to see that there was nocreated_at:
orupdated_at:
values inserted so we know that it was never created.The Errors Collection
we can even find out why the object didn’t save. each ActiveRecord object has an attribute called errors, which contains an instance of ActiveModel::Errors — a collection of validation failures
we can then type
m.errors
into our terminal and ActiveModel::Errors will prompt an output like this
[4] pry(main)> m.errors
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=director_id, type=blank, options={}>]>
- next we can try to get the message
[5] pry(main)> m.errors.messages
=> {:director_id=>["can't be blank"]}
- there is also a very helpful method we can place onto the error which will return a list of arrays of detailed messages on how to fix our issue on why it is not saving.
[6] pry(main)> m.errors.full_messages
=> ["Director can't be blank"]
- later on down the road we can actually take those error messages, say in like logging in to an account or making a password and actually provide the user the string from the error to realize their mistakes and fix the issue. this is a good alternative than creating a for loop and making it so you have a ton of code. you can really be utilizing the ActiveRecord::Errors to make it so you are personally doing less code and using more resources.
Helpful Methods for Validations
validates(:something_id, presence: true)
checks to see if a a specific "something" in a table has the presents of the thing it needs before saving to the tablevalidates(:something, uniqueness: true)
checks to see if no other rows have the same value in that column, very helpful for usernames and stuff where each value has to be unique to the specific id so there is no confusion.
Top comments (0)