ActiveRecord is popular Ruby gem (library) that acts as an Object-Relational-Mapper (ORM) for Ruby.
ActiveRecord allows us to combine the object-oriented nature of Ruby with the functionality of relational databases. Using ActiveRecord we can easily define Ruby Classes and map those Classes to columns in a database. We can then instantiate--i.e. create--new instances of those Ruby Classes and map those instances to records (rows) in a database column. We can then finally interact with our newly constructed database with methods from the ActiveRecord gem inside of a Ruby/.rb file.
Before continuing please note that ActiveRecord uses strict naming conventions. This is what allows its default configuration to handle a lot of work for us.
- capitol, singular
Classname for your model (Food) - lowercase, plural table names (
foods)
Suppose we have this table of foods (from a Food Ruby class model that inherits from ActiveRecord::Base if you are keeping track at home) :
Table: foods
| id | name | tastiness |
|---|---|---|
| 1 | hotdog | 8 |
| 2 | burger | 7 |
| 3 | ramen | 9 |
| 4 | rice | 10 |
| 5 | cheese | 4 |
We could begin to access or manipulate this table using the Food class in a rake console session for example or in the model's .rb file. Here are some common methods & manipulations:
get first record
Food.first
=> <Object Instance corresponding to id:1 name: "hotdog" tastiness: 8>
- returns the first record/
Objectinstance in a column
get record by id
Food.find(3)
=> <Object Instance corresponding to id:3 name: "ramen" tastiness: 9>
- returns the first record/
Objectinstance with theidpassed as an argument
get record by attribute (first match only)
Food.find_by(name: rice)
=> <Object Instance corresponding to id:4 name: "rice" tastiness: 10>
- returns the first record/
Objectinstance with an attribute that matches the.find_by()argument
get all records by criteria (all matches)
Food.where(' tastiness < 8 ')
=> [<Object Instance corresponding to id:2 name: "burger" tastiness: 7>,
<Object Instance corresponding to id:5 name: "cheese" tastiness: 4>]
- returns all records/
Objectinstances with an attribute that matches what was passed as an argument -
.wherereturns anActiveRecord::Collectionwhich is anarray-like data structure that can be indexed or iterated through using array methods. Even if there is only 1 match.wherewill always return the results in a collection.
get all values in a column
Food.pluck(:name)
=> ["hotdog", "burger" , "ramen", "rice", "cheese"]
Food.pluck(:tastiness)
=> [8, 7 , 9, 10, 4]
- returns each value in a column as an element in an
array
create a new record/instance in a table (with persistence)
Food.create(name: "eggs", tastiness: 5)
| id | name | tastiness |
|---|---|---|
| 1 | hotdog | 8 |
| 2 | burger | 7 |
| 3 | ramen | 9 |
| 4 | rice | 10 |
| 5 | cheese | 4 |
| 6 | eggs | 5 |
- under the hood this is working similar to using
.new&.savetogether..newwill only create a new instance of aclassin Ruby memory. It will not persist until it is written to the database using.save..createdoes both of these for you.
count number of records in a column
Food.count(:name)
=> 6
- counts the number of records in a column
remove a record/instance in a table (with persistence)
Food.find(2).destroy
| id | name | tastiness |
|---|---|---|
| 1 | hotdog | 8 |
| 3 | ramen | 9 |
| 4 | rice | 10 |
| 5 | cheese | 4 |
| 6 | eggs | 5 |
-
.destroyshould be used to destroy a single record/instance -
.destroy_allshould be used to destroy multiple records such as every instance of aclass(i.e.Food.destroy_all) or to destroy every member of anActiveRecord::Collection(i.e. after a.whereto do a targeted removal)
update a record/instance in a table (with persistence)
Food.find(6).update(name: "bread", tastiness: 9)
| id | name | tastiness |
|---|---|---|
| 1 | hotdog | 8 |
| 3 | ramen | 9 |
| 4 | rice | 10 |
| 5 | cheese | 4 |
| 6 | bread | 9 |
- you can update a single attribute such as only the name or only the tastiness or do both
You are now familiar with basic ActiveRecord ORM methods. If you want to try experimenting with this data at home continue below:
Set this up at home:
Provided you have an Ruby & ActiveRecord environment already configured and you are in that directory, you can try this yourself after creating (and migrating) this migration:
Brief configuration guidance:
Gemfile:
source "https://rubygems.org"
gem "activerecord", "~> 5.2"
gem "sinatra-activerecord"
gem "sqlite3"
gem "pry"
gem "require_all"
gem "rake"
Rakefile:
require_relative 'config/environment'
require 'sinatra/activerecord/rake'
desc 'starts a Pry console'
task :console do
# Comment out the line below if you don't want to see the SQL logs in your terminal
ActiveRecord::Base.logger = Logger.new(STDOUT)
# Start a Pry session
Pry.start
end
config/database.yml:
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
config/environment.rb:
require 'bundler'
Bundler.require
require_all 'app'
Now, on to actually creating this database:
# In a terminal window run:
$ bundle install
$ bundle exec rake db:create_migration NAME=create_foods
# inside of the db/migrate folder
# update your migration to have these attributes
# (the 5.2 should match whatever version of the activerecord gem
# you have installed in your gemfile)
class CreateFoods < ActiveRecord::Migration[5.2]
def change
create_table :foods do |t|
t.string :name
t.integer :tastiness
end
end
end
migrate your newly created migration:
# In a terminal window run:
$ bundle exec rake db:migrate
create this model:
# create a /app folder inside the root of your directory and put a /models folder inside of it.
# create a .rb file with your model name inside of /models
# singular and lowercase i.e. /app/models/food.rb
class Food < ActiveRecord::Base
end
populate/seed your database with data (create instances of the Food class that will exist inside of your foods table
# create a "seeds.rb" file inside of the /db directory
Food.create(name: "hotdog", tastiness: 8)
Food.create(name: "burger", tastiness: 7)
Food.create(name: "ramen", tastiness: 9)
Food.create(name: "rice", tastiness: 10)
Food.create(name: "cheese", tastiness: 4)
# In a terminal window run:
$ bundle exec rake db:seed
You have now:
1) Defined your table structure
2) Created your table
3) Defined what class belongs your the table
4) Filled your table with instances of your class
You can new view your database using an IDE + an extension (such as Visual Studio Code /w the SQLite extension or using a standalone database viewer app).
Feel free to try access and manipulate your table inside of a rake console session in your terminal or from inside your model's class definition now.
Happy rubying!
Top comments (0)