We have a table of horses
. An individual Horse
has a name
, age
, and total_winnings
.
Your job is to start exploring ActiveRecord methods. If you open app/models/horse.rb
, you'll notice that our Horse
class inherits from ActiveRecord::Base
. This is how we have access to all of ActiveRecord's methods.
In order to get started, you'll need to run the following commands from the command line:
bundle install
rake db:create
rake db:migrate
rake db:seed
Once you've run these commands, if you run tux
from the command line, you'll enter a console with your code loaded (pretty sweet, right?!).
ActiveRecord gives you reader and setter methods for each field in your database. In this example, a Horse
has a name
, age
, and total_winnings
. So, if we have an instance of Horse
, we can access each of these pieces of data like so:
horse = Horse.first
horse.name
# Penelope
horse.age
# 29
horse.total_winnings
# 34000
ActiveRecord's #find
takes an integer as an argument (the id of the record you're looking for). It returns the record if it finds it; if it doesn't find it - it returns an ActiveRecord::RecordNotFound
error.
If I was looking for the horse with id 90, I would run Horse.find(90)
Practice using #find
. See if you can find the following:
- The Horse with id 3
- The Horse with id 1
- The Horse with id 7
Similar to find
, find_by
will run a SQL query to find the specific record based on the data you pass it. The difference between find
and find_by
is that find
only accepts the id
, but with find_by
, we can pass it the attribute we want to lookup by.
For example, if I wanted to find the horse with the name "Penelope", I'd run Horse.find_by(name: "Penelope")
. You can also pass find_by
more than one argument. If I wanted to find the horse with the name "Penelope" and age 29, I could run Horse.find_by(name: "Penelope", age: 29)
. Notice that I'm passing in key/value pairs to find_by
.
Another important note is if we pass find_by
a value that our database doesn't have (for example: Horse.find_by(name: "Hola")
), the return value with be nil
. ActiveRecord will not through an error, but rather return nil
.
Practice using #find_by
.
See if you can write and execute (in tux
) ActiveRecord queries to accomplish the following:
- Find the Horse with age 95.
- Find the Horse with total winnings of 4000 and age 55
- Find the Horse with name "Paulo" and total winnings of 45000
What happens if we have more than one record in our database that satisfies the conditions we pass to our #find_by
method?
Similar to #find_by
, #where
accepts arguments in key/value pairs and queries our database accordingly. We can pass #where
as many key/value pairs as we'd like and it will return every record that it finds that matches our query.
The difference between #find_by
and #where
is that #find_by
will always return the first match from the database. #where
returns every match that it can find in an Array. If it only finds one match, it will still return the findings in an Array.
If I wanted to find all the horses who are named "Penelope", I'd execute Horse.where(name: "Penelope")
.
Practice using #where
. See if you can write and execute (in tux
) ActiveRecord queries to accomplish the following:
- Find all horses that are 39 years old.
- Find all horses that have total winnings of 78000.
- Find all horses that are named Patricia and 49.
In order to create a new horse, we can use the #new
method. Similar to the method we created previously, this will take a Hash of arguments. This method can be a bit deceving though. When you execute Horse.new(name: "Patty")
in your tux
console, what is the return value? Do you see that any SQL was executed?
The answer is no because this Horse
was not actually sent to the database. #new
simply creates a new instance of Horse. In order to save this in the database, we need to call #save
on the instance of Horse
. You should see an INSERT INTO
statement in the console after you call this method.
Example:
Horse.new(name: "Piper", age: 10, total_winnings: 134203)
# <Horse id: nil, name: "Piper", age: 10, total_winnings: 134203, created_at: nil, updated_at: nil>
Notice that the id this specific Horse
is nil
along with created_at
and updated_at
. We need to save
this instance if we want it to persist in our database.
horse = Horse.new(name: "Piper", age: 10, total_winnings: 134203)
# <Horse id: nil, name: "Piper", age: 10, total_winnings: 134203, created_at: nil, updated_at: nil>
horse.save
# true
Practice using #new
and #save
in tux
. Pay attention to the return values of both methods.
Wouldn't it be nice if there was a method that did both #new
and #save
in one go? ActiveRecord helps us out with this! It's called #create
. This method will create the new instance AND save it to the database. It takes the same arguments as #new
does, but it's return value is different.
Practice using #create
by creating at least 3 new horses. Pay special attention to what calling #create
returns.
ActiveRecord is very powerful. This is just a brief introduction to the methods that ActiveRecord gives us access to. If you have time and want to dive deeper, start by reading some documentation here.