© Brady Somerville, Adam Gamble, Cloves Carneiro Jr and Rida Al Barazi 2020
B. Somerville et al.Beginning Rails 6https://doi.org/10.1007/978-1-4842-5716-6_5

5. Working with a Database: Active Record

Brady Somerville1 , Adam Gamble2, Cloves Carneiro Jr.3 and Rida Al Barazi4
(1)
Bowling Green, KY, USA
(2)
Gardendale, AL, USA
(3)
Hollywood, FL, USA
(4)
FONTHILL, ON, Canada
 

Earlier, you took a whirlwind tour through creating a basic Rails application using the built-in scaffolding feature. You sketched out a basic model for a blog application and created the project databases. You used the built-in web server to run the application locally and practiced adding and managing articles from the web browser. This chapter will take a more in-depth look at how things work, starting with what is arguably the most important part of Rails: Active Record.

You may recall from Chapter 1 that Active Record is the Ruby object-relational mapping (ORM) library that handles database abstraction and interaction for Rails. Whether you realized it or not, in Chapter 3 all access to the database—adding, editing, and deleting articles—happened through the magic of Active Record.

If you’re not sure what exactly object-relational mapping is, don’t worry. By the end of this chapter, you’ll know. For now, it’s best if you think of Active Record as being an intermediary that sits between your code and your database, allowing you to work with data effectively and naturally. When you use Active Record, you communicate with your database using pure Ruby code. Active Record translates the Ruby you write into a language that databases can understand.

This chapter teaches you how to use Active Record to talk to your database and perform basic operations. It introduces the concepts you need to know about communicating with databases and object-relational mapping. Then, you will look at Active Record and walk through the techniques you need to know to effectively work with a database from Rails. If you don’t have a lot of database experience under your belt, don’t worry. Working with databases through Active Record is a painless and even enjoyable experience. If you’re an experienced database guru, you’ll find that Active Record is an intelligent and efficient way to perform database operations without the need for low-level database-specific commands.

Note

If you need to get the code at the exact point where you finished Chapter 3, download the zip file from GitHub (https://github.com/nicedawg/beginning-rails-6-blog/archive/chapter-03.zip).

Introducing Active Record: Object-Relational Mapping on Rails

The key feature of Active Record is that it maps tables to classes, table rows to objects, and table columns to object attributes. This practice is commonly known as object-relational mapping (ORM). To be sure, Active Record isn’t the only ORM in existence, but it may well be the easiest to use of the bunch.

One of the reasons Active Record is so easy to use is that almost no configuration is required to have it map a table to a class. You just need to create a Ruby class that’s named after the table you want to map and extend the Active Record Base class :
class Book < ApplicationRecord
end

Notice the part that reads < ApplicationRecord. The less-than sign indicates that the Book class on the left is a subclass of the one on the right, ApplicationRecord. In Ruby, when you inherit from a class like this, you automatically gain access to all the functionality in the parent class. ApplicationRecord is defined in your app/models/application_record.rb. Initially, it simply inherits from ActiveRecord::Base. There’s a lot of code in the ActiveRecord::Base class, but you don’t need to look at it. Your class merely inherits it, and your work is finished.

Assuming Active Record knows how to find your database and that you have a table called books (note that the table name is plural, whereas the class name is singular), the table is automatically mapped. If you know your books table contains the fields title, publisher, and published_at, you can do this in any Ruby context:
book = Book.new
book.title = "Beginning Rails 6"
book.publisher = "Apress"
book.published_at = "2020-04-15"
book.save

These five lines write a new record to the books table. You gain a lot of ability by the simple act of subclassing! And that’s why Active Record is easy to use. Notice how the table’s fields (title, publisher, and published_at) can be read and written to using methods on the object you created (book). And you didn’t need to tell Active Record what your fields were named or even that you had any fields. It figured this out on its own. Of course, Active Record doesn’t just let you create new records. It can also read, update, and delete records, plus a lot more.

Active Record is database agnostic, so it doesn’t care which database software you use, and it supports nearly every database out there. Because it’s a high-level abstraction, the code you write remains the same no matter which database you’re using. For the record (no pun intended), in this book you use SQLite. As explained in Chapter 2, SQLite is open source, easy to use, and fast, and it’s the default database used for Rails development. (Along with the SQLite site, https://sqlite.org, the Wikipedia entry on SQLite is a good resource: https://en.wikipedia.org/wiki/SQLite.)

At some point, you may need to switch to another database backend. (SQLite is great for development, but not appropriate for many production apps.) Rails 6 has added a command—rails db:system:change—which makes it easy to switch databases. We won’t run this command for this book, but just know this command exists.

Note

Rails is also ORM agnostic: it allows you to hook up your ORM of choice. There are several alternatives to Active Record which you can use if you think Active Record has some deficiencies. (See www.ruby-toolbox.com/categories/orm for a list of popular ones.) However, we feel that sticking to the default ORM is the best way to learn. We don’t cover alternative ORMs in this book.

What About SQL?

To be sure, you don’t need Active Record (or any ORM) to talk to and manipulate your database. Databases have their own language: SQL, which is supported by nearly every relational database in existence. Using SQL, you can view column information, fetch a particular row or a set of rows, and search for rows containing certain criteria. You can also use SQL to create, drop, and modify tables and insert, update, and destroy the information stored in those tables. The problem with SQL is that it’s not object oriented. If you want to learn the basic SQL syntax, look at Appendix B.

Object-oriented programming and relational databases are fundamentally different paradigms. The relational paradigm deals with relations and is mathematical by nature. The object-oriented paradigm, however, deals with objects, their attributes, and their associations to one another. As soon as you want to make objects persistent using a relational database, you notice something: there is a rift between these two paradigms—the so-called object-relational gap. An ORM library like Active Record helps you bridge that gap.

Note

Active Record is based on a design pattern. Design patterns are standard solutions to common problems in software design. Well, it turns out that when you’re working in an object-oriented environment, the problem of how to effectively communicate with a database (which isn’t object oriented) is quite common. Therefore, many smart people have wrapped their minds around the problem of how best to bring the object-oriented paradigm together with the relational database. One of those smart people is Martin Fowler, who, in his book Patterns of Enterprise Application Architecture (Addison Wesley, 2002), first described a pattern that he called an Active Record. In the pattern Fowler described, a one-to-one mapping exists between a database record and the object that represents it. When Rails creator David Heinemeier Hansson sought to implement an ORM for his framework, he based it on Fowler’s pattern.

Active Record lets you model real-world things in your code. Rails calls these real-world things models—the M in MVC. A model might be named Person, Product, or Article, and it has a corresponding table in the database: people, products, or articles. Each model is implemented as a Ruby class and is stored in the app/models directory. Active Record provides the link between these classes and your tables, allowing you to work with what look like regular objects, which, in turn, can be persisted to the database. This frees you from having to write low-level SQL to talk to the database. Instead, you work with your data as if they were an object, and Active Record does all the translation into SQL behind the scenes. This means that in Rails, you get to stick with one language: Ruby.

Note

Just because you’re using Active Record to abstract your SQL generation doesn’t mean SQL is evil. Active Record makes it possible to execute SQL directly whenever that’s necessary. The truth is that raw SQL is the native language of databases, and there are some (albeit rare) cases when an ORM won’t cut it.

Active Record Conventions

Active Record achieves its zero-configuration reputation by way of convention. Most of the conventions it uses are easy to grasp. After all, they’re conventions, so they’re already in wide use. Although you can override most of the conventions to suit the particular design of your database, you’ll save a lot of time and energy if you stick to them.

Let’s take a quick look at the two main conventions you need to know:
  • Class names are singular; table names are plural.

  • Tables contain an identity column named id.

Active Record assumes that the name of your table is the plural form of the class name. If your table name contains underscores, then your class name is assumed to be in CamelCase. Table 5-1 shows some examples.
Table 5-1

Table and Class Name Conventions

Table

Class

events

Event

people

Person

categories

Category

order_items

OrderItem

All tables are assumed to have a unique identity column named id. This column should be the table’s primary key (a value used to uniquely identify a table’s row). This is a fairly common convention in database design. (For more information on primary keys in database design, the Wikipedia entry has a wealth of useful information and links: https://en.wikipedia.org/wiki/Unique_key.)

The belief in convention over configuration is firmly entrenched in the Rails philosophy, so it should come as no surprise that there are more conventions at work than those listed here. You’ll likely find that they all make good sense, and you can use them without paying much attention.

Introducing the Console

Ruby comes with a great little tool: an interactive interpreter called irb (for Interactive Ruby). irb is Ruby’s standard REPL—a Read-Eval-Print Loop. Many programming languages have REPL tools, and Ruby has REPL tools other than irb. (pry is a popular alternative REPL for ruby with some great features.)

Most of the time, you invoke irb using the rails console command that ships with Rails, but you can start up an irb session whenever you want by typing irb at the command prompt. The advantage of the console is that it enjoys the special privilege of being integrated with your project’s environment. This means it has access to and knowledge of your models (and, subsequently, your database).

You use the console as a means to get inside the world of your Article model and to work with it in the exact same way your Rails application would. As you’ll see in a minute, this is a great way to showcase the capabilities of Active Record interactively.

You can execute any arbitrary Ruby code in irb and do anything you might otherwise do inside your Ruby programs: set variables, evaluate conditions, and inspect objects. The only essential difference between an interactive session and a regular old Ruby program is that irb echoes the return value of everything it executes. This saves you from having to explicitly print the results of an evaluation. Just run the code, and irb prints the result.

You can tell whenever you’re inside an irb session by looking for the double greater-than sign (>>)—or a slightly different sign depending on your environment—which indicates the irb prompt, and the arrow symbol (=>), which indicates the response.

As you continue to progress with both Ruby and Rails, you’ll find that irb is an essential tool. Using irb, you can play around with code and make sure it works as you expect before you write it into your programs.

If you’ve been following along with the previous chapters, then you should have a model called Article (in app/models/article.rb), and you’ve probably already entered some sample data when playing with scaffolding in Chapter 3. If not, make sure you get up to speed by reading Chapters 2 and 3 before moving on.

Let’s load irb and start to experiment with the Article model. Make sure you’re inside the blog application directory, and then type rails console on your command line. This causes the irb console to load with your application’s development environment and leaves you at a simple prompt, waiting for you to enter some code:
$ rails console
Loading development environment.
>>
From the console, you can interrogate your Article model for information. For instance, you can ask it for its column names:
>> Article.column_names
=> ["id", "title", "body", "published_at", "created_at", "updated_at",
"excerpt", "location"]
Look at that! All your columns are presented as a Ruby array (you can tell by the fact that they’re surrounded by square brackets). Another quick trick you may use often is to type just the name of your model class in the console to find out not only the column names but also the data type of each column:
>> Article
=> Article(id: integer, title: string, body: text, published_at: datetime,
created_at: datetime, updated_at: datetime, excerpt: string, location: string)
You get the column_names class method courtesy of the ActiveRecord::Base class from which your Article class ultimately inherits. Actually, you get a lot of methods courtesy of ActiveRecord::Base. To see just how many, you can ask
>> Article.methods.size
=> 690
Note

Depending on the version of Rails you are using and what gems you have installed, the number of methods might be different from 690. This is normal.

That’s a lot of methods! You may get a different number of methods depending on your environment. Many of the methods are inherited from ActiveRecord, but many of them come from classes that Active Record ultimately inherits from—like Ruby’s base Object class and its parent classes. Don’t worry—you don’t need to memorize all of these methods. Most of them are used internally so you’ll never have to use them directly. Still, it’s important, if for no other reason than to get a sense of what you get for free just by subclassing Active Record. Although in this case ApplicationRecord is considered the superclass, it sure makes your lowly Article class super, doesn’t it? (Sorry, enough bad humor.)

A Crash Course in Ruby Class Design

Object-oriented programming is all about objects. You create a class that encapsulates all the logic required to create an object, along with its properties and attributes, and use the class to produce new objects, each of which is a unique instance, distinct from other objects of the same class. That may sound a little abstract (and with good reason—abstraction, after all, is the name of the game), but if it helps, you can think of a class as being an object factory.

The obvious example is that of a car factory. Contained within a car factory are all the resources, tools, workers, and processes required to produce a shiny new car. Each car that comes off the assembly line is unique. The cars may vary in size, color, and shape, or they may not vary from one another much at all. The point is that even if two cars share the exact same attributes, they aren’t the same car. You certainly wouldn’t expect a change to the color of one car to affect all the others, would you? Well, in object-oriented programming, it’s not much different. The class is the factory that produces objects, which are called instances of a class. From a single factory, an infinite number of objects can be produced:
class Car
end
car1 = Car.new
car2 = Car.new
car1 is a Car object, which is to say it’s an instance of the class Car. Each car is a different object, created by the same factory. Each object knows which class it belongs to (which factory created it), so if you’re ever in doubt, you can ask it:
car2.class #=> Car
Your Car class doesn’t really do anything that useful—it has no attributes. So let’s give it some. You start by giving it a make—something like Toyota or Nissan. Of course, you need to define a way to read and write these attributes. You do this by creating aptly named reader and writer methods. Some object-oriented languages refer to these as getters and setters. The two sets of terms are pretty much interchangeable, but Ruby favors the former. Let’s add a reader and writer for the make attribute:
class Car
  # A writer method. Sets the value of the @make attribute
  def make=(text)
    @make = text
  end
  # A reader method. Returns the value of the @make attribute
  def make
    @make
  end
end
The methods you just defined (make() and make=()) are instance methods. This is because they can be used only on instances of the class, which is to say the individual objects that have been created from the class. To create a new instance of the Car class, you use the new constructor:
my_car = Car.new
That’s all that’s required to create a new instance of the class Car in a local variable called my_car. The variable my_car can now be considered a Car object. Although you have a new Car object, you haven’t yet given it a make. If you use the reader method you created to ask your car what its make is, you see that it’s nil:
my_car.make #=> nil

Apparently, if you want your car to have a make, you have to set it. This is where the writer method comes in handy:

my_car.make = 'Toyota'

This sets the value of the make attribute for your car to Toyota. If you had other Car objects, their makes would remain unchanged. You’re setting the attribute only on the my_car object. Now, when you use the reader method, it confirms that the make attribute has been updated:
my_car.make #=> 'Toyota'
Of course, you can change the value any time you want:
my_car.make = 'Mazda'
And again, if you ask your Car object its make, it will tell you:
my_car.make #=> 'Mazda'

That’s a simple example, but it illustrates a couple of very important points: classes are used to create objects, and objects have attributes. Every object has a unique set of attributes, different from other objects of the same class.

The reason for this crash course in Ruby class design is to illustrate the point that modeling with Active Record is a lot like modeling with standard Ruby classes. If you decided to think of Active Record as being an extension to standard Ruby classes, you wouldn’t be very far off. In practice, this fact makes using Active Record in Ruby quite natural. And because Active Record can reflect on your tables to determine which fields to map automatically, you need to define your attributes in only one place: the database. That’s DRY (don’t repeat yourself)! See Chapter 4 to learn more about Ruby’s syntax, classes, and objects.

Active Record Basics: CRUD

Active Record is a big topic, so let’s start with the basics. You’ve seen the so-called big four earlier, but here they are again: create, read, update, and delete, affectionately known as CRUD. In one way or another, most of what you do with Active Record in particular, and with databases in general, relates to CRUD. Rails has embraced CRUD as a design technique and as a way to simplify the modeling process. It’s no surprise then that this chapter takes an in-depth look at how to do CRUD with Active Record.

Let’s build on the blog application you started in Chapter 3. Although your application doesn’t do much yet, it’s at a stage where it’s easy to demonstrate these concepts in a more concrete fashion.

This section uses the console, so keep it open as you work, and feel free to experiment as much as you want. The more experimentation you do, the deeper your understanding will be.

Creating New Records

You start by creating a new article in the database so you have something to work with. There are a few different ways to create new model objects, but they’re all variations on the same theme. This section shows how each approach works and explains the often subtle differences among them.

Resetting the Database

Before we begin creating records, we’ll reset our database to a clean state. If we had data we cared about keeping, this would be a bad idea! But since we don’t, resetting our database will help your output more closely match the output shown in the following examples. From a directory within your Rails project, issue the following command:
$ rails db:reset
Dropped database 'db/development.sqlite3'
Dropped database 'db/test.sqlite3'
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'

This command drops the database, recreates it, loads the schema, and seeds your database with seed data according to your db/seeds.rb file (which is empty at this point).

Using the new Constructor

The most basic way to create a new model object is with the new constructor. If you read the crash course section on Ruby classes earlier, you’re sure to recognize it. If you didn’t, then it’s enough that you know new is the usual way to create new objects of any type. Active Record classes are no different. Try it now:
>> article = Article.new
=> #<Article id: nil, title: nil, body: nil, published_at: nil, created_at: nil,
updated_at: nil, excerpt: nil, location: nil>
All you’re doing here is creating a new Article object and storing it in the local variable article. True to form, the console responds with the return value of the method, which in this case is a string representation of the model object. It may look a little funny, but this is what all Ruby objects look like when you inspect them. The response lists the attributes of the Article class. Starting here, you could call a few of the article variable methods. For example, the new_record? method tells you whether this object has been persisted (saved) to the database, and the attributes method returns a hash of the attributes that Active Record garnered by reflecting on the columns in the table. Each key of the hash will be the name of a column (body, created_at, etc.).
>> article.new_record?
=> true
>> article.attributes
=> {"id"=>nil, "title"=>nil, "body"=>nil, "published_at"=>nil, "created_at"=>nil, "updated_at"=>nil, "excerpt"=>nil, "location"=>nil}
Here, you’re using reader methods, which read and return the value of the attribute in question. Because this is a brand-new record and you haven’t given it any information, all your attributes are nil, which means they have no values. Let’s remedy that now using (what else?) writer methods:
>> article.title = 'RailsConf'
=> "RailsConf"
>> article.body = 'RailsConf is the official gathering for Rails developers..'
=> "'RailsConf is the official gathering for Rails developers.."
>> article.published_at = '2020-01-31'
=> "2020-01-31"
Note

A return of nil always represents nothing. It’s a helpful little object that stands in the place of nothingness. If you ask an object for something and it returns false, then false is something, so it’s not a helpful representation. As a nerdy fact, in logics, false and true are equal and opposite values, but they’re values in the end. The same is true of zero (0). The number 0 isn’t truly nothing—it’s an actual representation of an abstract nothing, but it’s still something. That’s why in programming you have nil (or null in other languages).

Now, when you inspect your Article object, you can see that it has attributes:
>> article
=> #<Article id: nil, title: "RailsConf", body: "RailsConf is the official
 gathering for Rails devel...", published_at: "2020-01-31 00:00:00",
 created_at: nil, updated_at: nil, excerpt: nil, location: nil>
You still haven’t written a new record. If you were to look at the articles table in the database, you wouldn’t find a record for the object you’re working with. (If you squint really hard at the preceding object-inspection string, notice that no id has been assigned yet.) That’s because you haven’t yet saved the object to the database. Fortunately, saving an Active Record object couldn’t be any easier:
>> article.save
   (0.1ms)  begin transaction
  Article Create (0.7ms)  INSERT INTO "articles" ("title", "body", "published_at", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["title", "RailsConf"], ["body", "RailsConfig is the official gathering for Rails developers.."], ["published_at", "2020-01-31 00:00:00"], ["created_at", "2020-02-01 01:04:01.870579"], ["updated_at", "2020-02-01 01:04:01.870579"]]
   (5.0ms)  commit transaction
=> true
When you save a new record, an SQL INSERT statement is constructed behind the scenes; notice that Rails has displayed the generated SQL for you. If the INSERT is successful, the save operation returns true; if it fails, save returns false. You can ask for a count of the number of rows in the table just to be sure that a record was created:
>> Article.count
=> 1
Sure enough, you have a new article! You’ve got to admit, that was pretty easy. (You may have created some articles during the scaffolding session. If so, don’t be surprised if you have more than one article already.) Additionally, if you ask the article whether it’s a new_record?, it responds with false. Because it’s saved, it’s not “new” anymore:
y
>> article.new_record?
=> false
Let’s create another article. This time, we’ll omit all the chatter from the console so you can get a better sense of how the process plays out. You create a new object and place it in a variable, you set the object’s attributes, and finally you save the record. Note that although you’re using the local variable article to hold your object, it can be anything you want. Usually, you use a variable that indicates the type of object you’re creating, like article or, if you prefer shorthand, just a:
>> article = Article.new
>> article.title       = "Introduction to SQL"
>> article.body    = "SQL stands for Structured Query Language, .."
>> article.published_at         = Time.zone.now
>> article.save
Note

Although writer methods look like assignments, they’re really methods in disguise. article.title = 'something' is the functional equivalent of article.title=('something'), where title=() is the method. Ruby provides a little syntactic sugar to make writers look more natural.

Now you’re rolling! You’ve already created a few articles and haven’t had to write a lick of SQL. Given how easy this is, you may be surprised that you can do it in even fewer steps, but you can. Instead of setting each attribute on its own line, you can pass all of them to new at once. Here’s how you can rewrite the preceding process of creating a new record in fewer lines of code:
>> article = Article.new(title: "Introduction to Active Record",
body: "Active Record is Rails's default ORM..", published_at: Time.zone.now)
>> article.save

Not bad, but you can do even better. The new constructor creates a new object, but it’s your responsibility to save it. If you forget to save the object, it will never be written to the database. There is another method available that combines the creating and saving steps into one.

Using the create Method

When you want to create an object and save it in one fell swoop, you can use the create method. Use it now to create another article:
>> Article.create(title: "RubyConf 2020", body: "The annual RubyConf will
take place in..", published_at: '2020-01-31')
=> #<Article id: 4, title: "RubyConf 2020", body: "The annual RubyConf will take
place in..", published_at: "2020-01-31 00:00:00", created_at: "2020-01-31
23:17:19", updated_at: "2020-01-31 23:17:19", excerpt: nil, location: nil>
Instead of returning true or false, the create method returns the object it created—in this case, an Article object. You’re actually passing a hash of attributes to the create method. Although hashes are normally surrounded by curly braces, when a hash is the last argument to a Ruby method, the braces are optional. You can just as easily create the attribute’s hash first and then give that to create:
>> attributes = { title: "Rails Pub Nite", body: "Rails Pub Nite is every
3rd Monday of each month, except in December.", published_at: "2020-01-31"}
=> {:title=>"Rails Pub Nite", :body=>"Rails Pub Nite is every
3rd Monday of each month, except in December.", :published_at=>" 2020-01-31"}
>> Article.create(attributes)
=> #<Article id: 5, title: "Rails Pub Nite", body: "Rails Pub Nite is every 3rd
Monday of each month, e...", published_at: "2020-01-31 00:00:00",
created_at: "2020-01-31 23:36:07", updated_at: "2020-01-31 23:36:07",
excerpt: nil, location: nil>
Let’s see how many articles you’ve created by doing a count:
>> Article.count
=> 5

You’re getting the hang of this now. To summarize, when you want to create a new object and save it manually, use the new constructor; when you want to create and save in one operation, use create. You’ve already created five new records, which are plenty for now, so let’s move on to the next step: finding records.

Reading (Finding) Records

Now that you have a few articles to play with, it’s time to practice finding them. Every model class understands the find method. It’s quite versatile and accepts a number of options that modify its behavior.

Let’s start with the basics. find is a class method. That means you use it on the model class rather than an object of that class, just as you did the new and create methods. Like new and create , a find operation, if successful, returns a new object.

You can call find four ways:
  • find(:id): Finds a single record by its unique id or multiple records if :id is an array of ids

  • all: Finds all records in the table

  • first: Finds the first record

  • last: Finds the last record

The following sections go through the different ways to call find and explain how to use each.

Finding a Single Record Using an ID

The find, first, and last methods mostly return a single record. The :id option is specific; you use it when you’re looking for a specific record and you know its unique id. If you give it a single id, it either returns the corresponding record (if there is one) or raises an exception (if there isn’t one). If you pass an array of ids—like [4, 5]—as the parameter, the method returns an array with all records that match the passed in ids. The first method is a little more forgiving; it returns the first record in the table or nil if the table is empty, as explained in the next section.

You can find a single record using its unique id by using find(:id). Here’s how it works:
>> Article.find(3)
=> #<Article id: 3, title: "Introduction to Active Record", body: "Active Record
is Rails's default ORM..", published_at: "2020-01-31 04:00:00",
created_at: "2020-01-31 23:15:37", updated_at: "2020-01-31 23:15:37",
excerpt: nil, location: nil>
As you can see, you found the article with the id of 3. If you want to take a closer look at what was returned, you can store the result in a local variable:
>> article = Article.find(3)
=> #<Article id: 3 ...>
>> article.id
=> 3
>> article.title
=> "Introduction to Active Record"

Here, you store the object that find returned in the local variable article. Then, you can interrogate it and ask for its attributes.

All this works because an article with the id 3 actually exists. If instead you search for a record that you know doesn’t exist (say, 1037), Active Record raises an exception:
>> Article.find 1037
ActiveRecord::RecordNotFound: (Couldn't find Article with ‘id’=1037)
...

Active Record raises a RecordNotFound exception and tells you it couldn’t find any articles with the id of 1037. Of course it couldn’t. You know that no such record exists. The lesson here is that you use find(:id) when you’re looking for a specific record that you expect to exist. If the record doesn’t exist, it’s probably an error you want to know about; therefore, Active Record raises RecordNotFound.

Recovering From Recordnotfound Errors
When you use find with a single id, you expect the record to exist. Usually we don’t want to display Rails error messages directly to the user, but we can make them nicer and customize the verbiage. So how can you recover gracefully from a RecordNotFound exception if you need to? You can use Ruby’s facility for error handling: begin and rescue. Here’s how this works:
begin
  Article.find(1037)
rescue ActiveRecord::RecordNotFound
  puts "We couldn't find that record"
end

First, you open a begin block. Then, you cause a RecordNotFound error by deliberately searching for a record that you know doesn’t exist. When the error occurs, Ruby runs the code you put inside the rescue part of the body, which prints a friendly message.

You can put anything you like in the rescue block—you might want to render a specific view here, log the error, or even redirect to another location. Error handling works the same way with other error messages also. If you need to rescue from any error at all, you can just use rescue without specifying an error class.

Finding a Single Record Using first

You can find the first record that the database returns by using the first method. This always returns exactly one item, unless the table is empty, in which case nil is returned:
>> Article.first
=> #<Article id: 1, title: "RailsConf", body: "RailsConf is the official
 gathering for Rails devel...", published_at: "2020-01-31 00:00:00",
 created_at: "2020-01-31 23:12:09", updated_at: "2020-01-31 23:12:09",
 excerpt: nil, location: nil>

Keep in mind that this isn’t necessarily the first record in the table. It depends on the database software you’re using and the default order in which you want your records to be retrieved. Usually records are ordered by either created_at or updated_at. If you need to be sure you get the first record you’re expecting, you should specify an order. It’s the equivalent of saying SELECT * FROM table LIMIT 1 in SQL. If you need to find a record and don’t particularly care which record it is, first can come in handy. Note that first doesn’t raise an exception if the record can’t be found.

The last method works exactly the same as first; however, records are retrieved in the inverse order of first. For example, if records from articles are listed in chronological order for first, they’re retrieved in inverse chronological order for last:
>> Article.last
=> #<Article id: 5, title: "Rails Pub Nite", body: "Rails Pub Nite is every 3rd
Monday of each month, e...", published_at: "2020-01-31 00:00:00",
created_at: "2020-01-31 23:36:07", updated_at: "2020-01-31 23:36:07",
excerpt: nil, location: nil>

Finding All Records

So far, you’ve looked at finding a single record. In each case, find, first, or last returns a single Article object. But what if you want to find more than one article? In your application, you want to display all the articles on the home page.

If you run the all method , it returns all records for that class:
>> articles = Article.all
=> #<ActiveRecord::Relation [#<Article id: 1,..> #<Article id: 2,..>, #<Article id: 3,..>,
#<Article id: 4,..> , #<Article id: 5,..>]>

Look closely at the response, and you’ll see that an instance of ActiveRecord::Relation was returned. Most ActiveRecord query methods return an instance of ActiveRecord::Relation. Why do this instead of simply returning an array of Article instances? By returning an ActiveRecord::Relation, it allows more query methods to be chained together and for the SQL to be executed at the last possible moment. We’ll see an example of that soon.

Even though articles at this point is an ActiveRecord::Relation object, it can behave in many cases like an array. Like all Ruby arrays, you can ask for its size:
>> articles.size
=> 5
Because articles acts like an array, you can access the individual elements it contains by using its index , which is numeric, starting at 0:
>> articles[0]
=> #<Article id: 1, title: "RailsConf", body: "RailsConf is the official
 gathering for Rails devel...", published_at: "2020-01-31 00:00:00",
 created_at: "2020-01-31 23:12:09", updated_at: "2020-01-31 23:12:09",
 excerpt: nil, location: nil>
And after you’ve isolated a single Article object, you can find its attributes:
>> articles[0].title
=> "RailsConf"
What’s happening here is that all produces an array, and you access the object at the 0 index and call the title method. You can also use the first method, which all arrays respond to, and get the same result, but with a little more natural syntax:
>> articles.first.title
=> "RailsConf"
If you want to iterate over the collection, you can use the each method, which, again, works with all arrays. Here, you loop over the array, extract each item into a variable called article, and print its title attribute using the puts command:
>> articles.each { |article| puts article.title }
RailsConf
Introduction to SQL
Introduction to Active Record
RubyConf 2020
Rails Pub Nite
=> [#<Article id: 1,..> #<Article id: 2,..>, #<Article id: 3,..>,
#<Article id: 4,..> , #<Article id: 5,..>]
Sometimes you want your results ordered. For example, if you’re listing all your articles, you might want them listed alphabetically by title. To do so, you can use the order method, which accepts as argument the name of the column or columns. For you SQL heroes, it corresponds to the SQL ORDER clause:
>> articles = Article.order(:title)
=> #<ActiveRecord::Relation [#<Article id: 3,..> #<Article id: 2,..>, #<Article id: 5,..>,
#<Article id: 1,..> , #<Article id: 4,..>]>
>> articles.each {|article| puts article.title }
Introduction to Active Record
Introduction to SQL
Rails Pub Nite
RailsConf
RubyConf 2020
=> [#<Article id: 3,..> #<Article id: 2,..>, #<Article id: 5,..>,
#<Article id: 1,..> , #<Article id: 4,..>]

Notice that when you call the order method, it returns an ActiveRecord::Relation object, as you may have expected. As mentioned earlier, one feature of ActiveRecord::Relation is that it allows you to chain calls to multiple methods before sending the command to the database; so you can call all, followed by order, and some other methods we’ll talk about in Chapter 6, to create more precise database queries. Also, Active Record is smart enough to use lazy loading , a practice that only hits the database when necessary—in this example, when you call the each method.

By default, any column is ordered in ascending order (e.g., 1–10 or az). If you want to reverse this to get descending order, use the :desc modifier (similar to how you would in SQL):
>> articles = Article.order(published_at: :desc)
=> [#<Article id: 3,..> #<Article id: 2,..>, #<Article id: 1,..>,
#<Article id: 4,..> , #<Article id: 5,..>]
>> articles.each {|article| puts article.title }
Introduction to Active Record
Introduction to SQL
RailsConf
RubyConf 2020
Rails Pub Nite
=> [#<Article id: 3,..> #<Article id: 2,..>, #<Article id: 1,..>,
#<Article id: 4,..> , #<Article id: 5,..>]

Finding with Conditions

Although finding a record by its primary key is useful, it requires that you know the id to begin with, which isn’t always the case. Sometimes you want to find records based on other criteria. This is where conditions come into play. Conditions correspond to the SQL WHERE clause. If you want to find a record by its title, you call the where method and pass a value that contains either a hash of conditions or an SQL fragment.

Here, you use a hash of conditions to indicate you want the first article with the title RailsConf:
>> Article.where(title: 'RailsConf').first
=> #<Article id: 1, title: "RailsConf", body: "RailsConf is the official
 gathering for Rails devel...", published_at: "2020-01-31 00:00:00",
 created_at: "2020-01-31 23:12:09", updated_at: "2020-01-31 23:12:09",
 excerpt: nil, location: nil>
Because you use first, you get only one record (the first one in the result set, even if there is more than one result). If you instead use all , you get back a collection, even if the collection has only one item in it:
>> Article.where(title: 'RailsConf').all
=> #<ActiveRecord::Relation [#<Article id: 1, title: "RailsConf", body: "RailsConf is the official  gathering for Rails devel...", published_at: "2020-01-31 00:00:00",
 created_at: "2020-01-31 23:12:09", updated_at: "2020-01-31 23:12:09",
 excerpt: nil, location: nil>]>
Notice the square brackets, and remember that they indicate an array. More often than not, when you’re doing an all operation, you expect more than one record in return. But all always produces an array, even if that array is empty:
>> Article.where(title: 'Unknown').all
=> #<ActiveRecord::Relation []>

Updating Records

Updating a record is a lot like creating a record. You can update attributes one at a time and then save the result, or you can update attributes in one fell swoop. When you update a record, an SQL UPDATE statement is constructed behind the scenes. First, you use a find operation to retrieve the record you want to update; next, you modify its attributes; and finally, you save it back to the database:
>> article = Article.first
>> article.title = "Rails 6 is great"
>> article.published_at = Time.zone.now
>> article.save
=> true

This should look pretty familiar by now. The only real difference between this process and the process of creating a new record is that instead of creating a brand-new row, you fetch an existing row. You update the attributes the exact same way, and you save the record the same way. Just as when you create a new record, when save operates on an existing record, it returns true or false, depending on whether the operation was successful.

When you want to update an object’s attributes and save it in a single operation, you use the update_attributes method. Unlike when you create a new record with create, because you’re updating a record, you need to fetch that record first. That’s where the other subtle difference lies. Unlike create, which is a class method (it operates on the class, not on an object), update_attributes is an instance method. Instance methods work on objects or instances of a class. Here’s an example:
>> article = Article.first
>> article.update_attributes(title: "RailsConf2020", published_at: 1.day.ago)
=> true

Deleting Records

You’re finally at the last component of CRUD: delete. When you’re working with databases, you inevitably need to delete records. If a user cancels their order or if a book goes out of stock or even if you have an error in a given row, you may want to delete it. Sometimes you need to delete all rows in a table, and sometimes you want to delete only a specific row. Active Record makes deleting rows every bit as easy as creating them.

There are two styles of row deletion: destroy and delete. The destroy style works on the instance . It instantiates the object, which means it finds a single row first and then deletes the row from the database. The delete style operates on the class, which is to say it operates on the table rather than a given row from that table.

Using destroy

The easiest and most common way to remove a record is to use the destroy method , which means the first thing you need to do is find the record you want to destroy:
>> article = Article.last
>> article.destroy
=> #<Article id: 5, title: "Rails Pub Nite", body: "Rails Pub Nite is every 3rd
Monday of each month, e...", published_at: "2020-01-31 00:00:00",
created_at: "2020-01-31 23:36:07", updated_at: "2020-01-31 23:36:07",
excerpt: nil, location: nil>
If you’re interested, the SQL that Active Record generates in response to the destroy operation is as follows:
DELETE FROM articles WHERE id = 5;
As a result, the article with the id of 5 is permanently deleted. But you still have the object hanging around in the variable article, so how can it really be gone? The answer is that although the object remains hydrated (retains all its attributes), it’s frozen . You can still access its attributes, but you can’t modify them. Let’s see what happens if you try to change the location:
>> article.location = 'Toronto, ON'
RuntimeError (Can't modify frozen hash)
It appears that the deleted article is now frozen. The object remains, but it’s read-only, so you can’t modify it. Given this fact, if you’re going to delete the record, you don’t really need to create an explicit Article object after all. You can do the destroy in a one-line operation:
>> Article.last.destroy

Here, the object instantiation is implicit. You’re still calling the destroy instance method, but you’re not storing an Article object in a local variable first.

You can still do better. You can use the class method destroy, which does a find automatically. As with find and create, you can use destroy directly on the class (i.e., you don’t create an object first). Because it operates on the table and not the row, you need to help it by telling it which row or rows you want to target. Here’s how you delete the article with the id 1:
>> Article.destroy(1)
=> [#<Article id: 1, title: "RailsConf", body: "RailsConf is the official
 gathering for Rails devel...", published_at: "2020-01-31 00:00:00",
 created_at: "2020-01-31 23:12:09", updated_at: "2020-01-31 23:12:09",
 excerpt: nil, location: nil>]
Sometimes you want to destroy more than one record. Just as with find, you can give destroy an array of primary keys whose rows you want to remove. Use square brackets ([]) to indicate that you’re passing an array:
>> Article.destroy([2,3])
=> [#<Article id: 2, ..>, #<Article id: 3, ..>]

Using delete

The second style of row deletion is delete. Every Active Record class has class methods called delete and delete_all. The delete family of methods differs from destroy in that they don’t instantiate or perform callbacks on the object they’re deleting. They remove the row immediately from the database.

Just like find and create, you use delete and delete_all directly on the class (i.e., you don’t create an object first). Because the method operates on the table and not the row, you need to help it by telling it which row or rows you want to target:
>> Article.delete(4)
=> 1

Here you specify a single primary key for the article you want to delete. The operation responds with the number of records removed. Because a primary key uniquely identifies a single record, only one record is deleted.

Just as with find, you can give delete an array of primary keys whose rows you want to delete. Use square brackets ([]) to indicate that you’re passing an array:
>> Article.delete([5, 6])
=> 0

The return of the delete method in this case is 0, since we didn’t have records with id’s 5 and 6 in our database. Zero records were deleted.

Note

Unlike find, which is capable of collecting any arguments it receives into an array automatically, delete must be supplied with an array object explicitly. So, although Model.find(1,2,3) works, Model.delete(1,2,3) fails with an argument error (because it’s really receiving three arguments). To delete multiple rows by primary key, you must pass an actual array object. The following works, because it’s a single array (containing three items) and thus a single argument: Model.delete([1,2,3]).

Deleting with Conditions

You can delete all rows that match a given condition with the delete_by class method. The following deletes all articles before a certain date:
>> Article.delete_by("published_at < '2011-01-01'")
>> 0

The return value of delete_by is the number of records deleted.

When Good Models Go Bad

So far, you’ve been nice to your models and have made them happy by providing just the information they need. But in Chapter 3 you provided validations that prevented you from saving bad records to the database. Specifically, you told the Article model that it should never allow itself to be saved to the database if it isn’t given a title and body. Look at the Article model, as shown in Listing 5-1, to recall how validations are specified.
class Article < ApplicationRecord
    validates :title, :body, presence: true
end
Listing 5-1

The app/models/article.rb File

You may have noticed in your generated scaffolding that you use a helper method called errors.full_messages to print out a helpful error message. That helper isn’t black magic; it’s a bit of code that asks the model associated with the form for its list of errors (also referred to as the errors collection) and returns a nicely formatted block of HTML to show the user.

Note

You may have noticed that you call methods in Ruby with a dot (.). For instance, you say article.errors to get the errors collection back. However, Ruby documentation uses the # symbol along with the class name to let the reader know that there is a method it can call on for an instance of that class. For example, on the Article class, you can use the method article.title as Article#title, because it’s something that acts on a particular article but not the Article class itself. You’ve also seen that you can write the code Article.count, because you don’t need to know about a particular @article, but only Article objects in general. Keep this convention in mind when you’re reading Ruby documentation.

The secret to this is that every Active Record object has an automatic attribute added to it called errors . To get started, create a fresh Article object:
>> article = Article.new
=> #<Article id: nil, title: nil, body: nil, published_at: nil, created_at: nil,
updated_at: nil, excerpt: nil, location: nil>
>> article.errors.any?
=> false
This seems odd: you know this new article should have errors, because it’s invalid—you didn’t give it a title or a body. This is because you haven’t triggered the validations yet. You can cause them to occur a couple of ways. The most obvious way is to attempt to save the object:
>> article.save
=> false

Every time you’ve used save before, the model has happily chirped true back to you. But this time, save returns false. This is because before the model allows itself to be saved, it runs through its gauntlet of validations, and one or more of those validations failed.

You would be right to guess that if you tried article.errors.any? again, it would return true:
>> article.errors.any?
=> true
Let’s interrogate the errors collection a little more closely with the full_messages method :
>> article.errors.full_messages
=> ["Title can't be blank", "Body can't be blank"]

Voilà! Look how helpful the model is being. It’s passing back an array of error messages.

If there is only one attribute that you care about, you can also ask the errors collection for a particular attribute’s errors:
>> article.errors.messages[:title]
=> "can't be blank"
Notice that because you tell it which attribute you’re looking for, the message returns a slightly different result than before. What if you ask for an attribute that doesn’t exist or doesn’t have errors?
>> article.errors.messages(:nonexistent)
=> []

You get back an empty array, which lets you know that you didn’t find anything.

Another helpful method is size, which, as you saw earlier, works with all arrays:
>> article.errors.size
=> 2
Saving isn’t the only way you can cause validations to run. You can ask a model object if it’s valid?:
>> article.valid?
=> false

If you try that on a new object, the errors collection magically fills up with your pretty errors.

Summary

In this chapter, you’ve become familiar with using the console to work with models. You’ve learned how to create, read, update, and destroy model objects. Also, you’ve briefly looked into how to see the simple errors caused by the validations you set up on your model in Chapter 3.

The next chapter discusses how to create relationships (called associations) among your models, and you begin to see how Active Record helps you work with your data in extremely powerful ways. It also expands on the concept of validations and shows how you can do a lot more with validates. You’ll see that Rails provides a bevy of prewritten validators and an easy way to write your own customized validators.