diff --git a/guides/source/active_record_basics.md b/guides/source/active_record_basics.md index 11c7d3b3377c0..ae1ed4273cf61 100644 --- a/guides/source/active_record_basics.md +++ b/guides/source/active_record_basics.md @@ -7,9 +7,9 @@ This guide is an introduction to Active Record. After reading this guide, you will know: -* What Object Relational Mapping and Active Record are and how they are used in - Rails. -* How Active Record fits into the Model-View-Controller paradigm. +* How Active Record fits into the Model-View-Controller (MVC) paradigm. +* What Object Relational Mapping and Active Record patterns are and how + they are used in Rails. * How to use Active Record models to manipulate data stored in a relational database. * Active Record schema naming conventions. @@ -20,28 +20,41 @@ After reading this guide, you will know: What is Active Record? ---------------------- -Active Record is the M in [MVC][] - the model - which is the layer of the system -responsible for representing business data and logic. Active Record facilitates -the creation and use of business objects whose data requires persistent storage -to a database. It is an implementation of the Active Record pattern which itself -is a description of an Object Relational Mapping system. +Active Record is part of the M in [MVC][] - the model - which is the layer of +the system responsible for representing data and business logic. Active Record +helps you create and use Ruby objects whose attributes require persistent +storage to a database. + +NOTE: What is the difference between Active Record and Active Model? It's +possible to model data with Ruby objects that do *not* need to be backed by a +database. [Active Model](active_model_basics.html) is commonly used for that in +Rails, making Active Record and Active Model both part of the M in MVC, as well +as your own plain Ruby objects. + +The term "Active Record" also refers to a software architecture pattern. Active +Record in Rails is an implementation of that pattern. It's also a description of +something called an [Object Relational Mapping][ORM] system. The below sections +explain these terms: ### The Active Record Pattern -[Active Record was described by Martin Fowler][MFAR] in his book _Patterns of -Enterprise Application Architecture_. In Active Record, objects carry both -persistent data and behavior which operates on that data. Active Record takes -the opinion that ensuring data access logic as part of the object will educate -users of that object on how to write to and read from the database. +The [Active Record pattern is described by Martin Fowler][MFAR] in the book +_Patterns of Enterprise Application Architecture_ as "an object that wraps a row +in a database table, encapsulates the database access, and adds domain logic to +that data." Active Record objects carry both data and behavior. Active Record +classes match very closely to the record structure of the underlying database. +This way users can easily read from and write to the database, as you will see +in the examples below. ### Object Relational Mapping -[Object Relational Mapping][ORM], commonly referred to as its abbreviation ORM, -is a technique that connects the rich objects of an application to tables in a -relational database management system. Using ORM, the properties and -relationships of the objects in an application can be easily stored and -retrieved from a database without writing SQL statements directly and with less -overall database access code. +Object Relational Mapping, commonly referred to as ORM, is a technique that +connects the rich objects of a programming language to tables in a relational +database management system (RDBMS). In the case of a Rails application, these +are Ruby objects. Using an ORM, the attributes of Ruby objects, as well as the +relationship between objects, can be easily stored and retrieved from a database +without writing SQL statements directly. Overall, ORMs minimize the amount of +database access code you have to write. NOTE: Basic knowledge of relational database management systems (RDBMS) and structured query language (SQL) is helpful in order to fully understand Active @@ -50,11 +63,10 @@ study them by other means if you would like to learn more. ### Active Record as an ORM Framework -Active Record gives us several mechanisms, the most important being the ability -to: +Active Record gives us the ability to do the following using Ruby objects: * Represent models and their data. -* Represent associations between these models. +* Represent associations between models. * Represent inheritance hierarchies through related models. * Validate models before they get persisted to the database. * Perform database operations in an object-oriented fashion. @@ -71,105 +83,236 @@ Convention over Configuration in Active Record When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by -Rails, you'll need to write very little configuration (in some cases no -configuration at all) when creating Active Record models. The idea is that if -you configure your applications in the very same way most of the time then this -should be the default way. Thus, explicit configuration would be needed -only in those cases where you can't follow the standard convention. +Rails, you'll write very little to no configuration code when creating Active +Record models. + +Rails adopts the idea that if you configure your applications in the same way +most of the time, then that way should be the default. Explicit configuration +should be needed only in those cases where you can't follow the convention. + +To take advantage of convention over configuration in Active Record, there are +some naming and schema conventions to follow. And in case you need to, it is +possible to [override naming conventions](#overriding-the-naming-conventions). ### Naming Conventions -By default, Active Record uses some naming conventions to find out how the -mapping between models and database tables should be created. Rails will -pluralize your class names to find the respective database table. So, for -a class `Book`, you should have a database table called **books**. The Rails -pluralization mechanisms are very powerful, being capable of pluralizing (and -singularizing) both regular and irregular words. When using class names composed -of two or more words, the model class name should follow the Ruby conventions, -using the CamelCase form, while the table name must use the snake_case form. Examples: +Active Record uses this naming convention to map between models (represented by +Ruby objects) and database tables: + +Rails will pluralize your model's class names to find the respective database +table. For example, a class named `Book` maps to a database table named `books`. +The Rails pluralization mechanisms are very powerful and capable of pluralizing +(and singularizing) both regular and irregular words in the English language. +This uses the [Active Support](active_support_core_extensions.html#pluralize) +[pluralize](https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-pluralize) method. + +For class names composed of two or more words, the model class name will follow +the Ruby conventions of using a UpperCamelCase name. The database table name, in +that case, will be a snake_case name. For example: -* Model Class - Singular with the first letter of each word capitalized (e.g., `BookClub`). -* Database Table - Plural with underscores separating words (e.g., `book_clubs`). +* `BookClub` - is the model class, singular with the first letter of each word + capitalized. +* `book_clubs` - is the matching database table, plural with underscores + separating words. + +Here are some more examples of model class names and corresponding table names: | Model / Class | Table / Schema | | ---------------- | -------------- | | `Article` | `articles` | | `LineItem` | `line_items` | -| `Deer` | `deers` | -| `Mouse` | `mice` | +| `Product` | `products` | | `Person` | `people` | ### Schema Conventions -Active Record uses naming conventions for the columns in database tables, +Active Record uses conventions for column names in the database tables as well, depending on the purpose of these columns. +* **Primary keys** - By default, Active Record will use an integer column named + `id` as the table's primary key (`bigint` for PostgreSQL and MySQL, `integer` + for SQLite). When using [Active Record Migrations](#migrations) to create your + tables, this column will be automatically created. * **Foreign keys** - These fields should be named following the pattern - `singularized_table_name_id` (e.g., `item_id`, `order_id`). These are the + `singularized_table_name_id` (e.g., `order_id`, `line_item_id`). These are the fields that Active Record will look for when you create associations between your models. -* **Primary keys** - By default, Active Record will use an integer column named - `id` as the table's primary key (`bigint` for PostgreSQL and MySQL, `integer` - for SQLite). When using [Active Record Migrations](active_record_migrations.html) - to create your tables, this column will be automatically created. -There are also some optional column names that will add additional features -to Active Record instances: +There are also some optional column names that will add additional features to +Active Record instances: * `created_at` - Automatically gets set to the current date and time when the record is first created. * `updated_at` - Automatically gets set to the current date and time whenever the record is created or updated. * `lock_version` - Adds [optimistic - locking](https://api.rubyonrails.org/classes/ActiveRecord/Locking.html) to - a model. + locking](https://api.rubyonrails.org/classes/ActiveRecord/Locking.html) to a + model. * `type` - Specifies that the model uses [Single Table Inheritance](https://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord::Base-label-Single+table+inheritance). -* `(association_name)_type` - Stores the type for - [polymorphic associations](association_basics.html#polymorphic-associations). +* `(association_name)_type` - Stores the type for [polymorphic + associations](association_basics.html#polymorphic-associations). * `(table_name)_count` - Used to cache the number of belonging objects on - associations. For example, a `comments_count` column in an `Article` class that - has many instances of `Comment` will cache the number of existent comments - for each article. + associations. For example, a `comments_count` column in an `Article` class + that has many instances of `Comment` will cache the number of existing + comments for each article. -NOTE: While these column names are optional, they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, `type` is a reserved keyword used to designate a table using Single Table Inheritance (STI). If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling. +NOTE: While these column names are optional, they are reserved by Active Record. +Steer clear of reserved keywords when naming your table's columns. For example, +`type` is a reserved keyword used to designate a table using Single Table +Inheritance (STI). If you are not using STI, use a different word to accurately +describe the data you are modeling. Creating Active Record Models ----------------------------- -When generating an application, an abstract `ApplicationRecord` class will be -created in `app/models/application_record.rb`. This is the base class for all -models in an app, and it's what turns a regular ruby class into an Active Record -model. +When generating a Rails application, an abstract `ApplicationRecord` class will +be created in `app/models/application_record.rb`. The `ApplicationRecord` class +inherits from +[`ActiveRecord::Base`](https://api.rubyonrails.org/classes/ActiveRecord/Base.html) +and it's what turns a regular Ruby class into an Active Record model. -To create Active Record models, subclass the `ApplicationRecord` class and you're good to go: +`ApplicationRecord` is the base class for all Active Record models in your app. +To create a new model, subclass the `ApplicationRecord` class and you're good to +go: ```ruby -class Product < ApplicationRecord +class Book < ApplicationRecord end ``` -This will create a `Product` model, mapped to a `products` table at the -database. By doing this you'll also have the ability to map the columns of each -row in that table with the attributes of the instances of your model. Suppose -that the `products` table was created using an SQL (or one of its extensions) statement like: +This will create a `Book` model, mapped to a `books` table in the database, +where each column in the table is mapped to attributes of the `Book` class. An +instance of `Book` can represent a row in the `books` table. The `books` table +can be created using an SQL statement like this: ```sql -CREATE TABLE products ( +CREATE TABLE books ( id int(11) NOT NULL auto_increment, - name varchar(255), + title varchar(255), + author varchar(255), PRIMARY KEY (id) ); ``` -The schema above declares a table with two columns: `id` and `name`. Each row of -this table represents a certain product with these two parameters. Thus, you -would be able to write code like the following: +Database tables in Rails are typically created using [Active Record +Migrations](#migrations) and not raw SQL. A migration for the `books` table +above can be generated like this: + +```bash +$ bin/rails generate migration CreateBooks title:string author:string +``` + +and results in this: + +```ruby +# Note: +# The `id` column, as the primary key, is automatically created by convention. +# Columns `created_at` and `updated_at` are added by `t.timestamps` line. + +# /db/migrate/20240220143807_create_books.rb +class CreateBooks < ActiveRecord::Migration + def change + create_table :books do |t| + t.string :title + t.string :author + + t.timestamps + end + end +end +``` + +The SQL as well as the migration above declare a table with three columns: `id`, +`title`, and `author`. Each row of this table can be represented by an instance +of the `Book` class with the same three attributes: `id`, `title`, and `author`. +You can access a book's attributes like this: + +```irb +irb> book = Book.new +=> # + +irb> book.title = "The Hobbit" +=> "The Hobbit" +irb> book.title +=> "The Hobbit" +``` + +NOTE: You can generate the Active Record model class as well as a matching +migration with this command `bin/rails generate model Book title:string +author:string`. This creates both `/app/models/book.rb` and +`/db/migrate/20240220143807_create_books.rb` files. + +### Creating Namespaced Models + +Active Record models are placed under the `app/models` directory by default. But +you may want to organize your models by placing similar models under their own +folder and namespace. For example, `order.rb` and `review.rb` under +`app/models/product` with `Product::Order` and `Product::Review` class names, +respectively. You can create namespaced models with Active Record. + +In the case where `Product` module does not already exist, the `generate` +command will create everything like this: + +```bash +$ bin/rails generate model Product::Order + invoke active_record + create db/migrate/20240306194227_create_product_orders.rb + create app/models/product/order.rb + create app/models/product.rb + invoke test_unit + create test/models/product/order_test.rb + create test/fixtures/product/orders.yml +``` + +In the case where `Product` module already exists, you will be asked to resolve +the conflict: + +```bash +$ bin/rails generate model Product::Order + invoke active_record + create db/migrate/20240305140356_create_product_orders.rb + create app/models/product/order.rb + conflict app/models/product.rb + Overwrite /Users/bhumi/Code/rails_guides/app/models/product.rb? (enter "h" for help) [Ynaqdhm] +``` + +Once the namespaced model generation is successful, the `Product` and `Order` +classes look like this: + +```ruby +# app/models/product.rb +module Product + def self.table_name_prefix + "product_" + end +end + +# app/models/product/order.rb +class Product::Order < ApplicationRecord +end +``` + +Setting the +[table_name_prefix](https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema.html#method-c-table_name_prefix-3D) +in `Product` will allow `Order` model's database table to be named +`product_orders`, instead of plain `orders`. + +The other possibility is that you already have a `Product` model that you want +to keep in `app/models`. In that case, you can choose `n` to not overwrite +`product.rb` during the `generate` command. + +This will still allow for a namespaced table name for `Product::Order` class, +without needing the `table_name_prefix`: ```ruby -p = Product.new -p.name = "Some Book" -puts p.name # "Some Book" +# app/models/product.rb +class Product < ApplicationRecord + # existing code +end + +Product::Order.table_name +# => "product_orders" ``` Overriding the Naming Conventions @@ -185,20 +328,20 @@ can use the `ActiveRecord::Base.table_name=` method to customize the table name that should be used: ```ruby -class Product < ApplicationRecord - self.table_name = "my_products" +class Book < ApplicationRecord + self.table_name = "my_books" end ``` If you do so, you will have to manually define the class name that is hosting -the fixtures (`my_products.yml`) using the `set_fixture_class` method in your -test definition: +[the fixtures](testing.html#the-low-down-on-fixtures) (`my_books.yml`) using the +`set_fixture_class` method in your test definition: ```ruby -# test/models/product_test.rb -class ProductTest < ActiveSupport::TestCase - set_fixture_class my_products: Product - fixtures :my_products +# test/models/book_test.rb +class BookTest < ActiveSupport::TestCase + set_fixture_class my_books: Book + fixtures :my_books # ... end ``` @@ -207,28 +350,38 @@ It's also possible to override the column that should be used as the table's primary key using the `ActiveRecord::Base.primary_key=` method: ```ruby -class Product < ApplicationRecord - self.primary_key = "product_id" +class Book < ApplicationRecord + self.primary_key = "book_id" end ``` -NOTE: **Active Record does not recommend using non-primary key columns named `id`.** -Using a column named `id` which is not a single-column primary key complicates the access to the column value. -The application will have to use the [`id_value`][] alias attribute to access the value of the non-PK `id` column. +NOTE: **Active Record does not recommend using non-primary key columns named +`id`.** Using a column named `id` which is not a single-column primary key +complicates the access to the column value. The application will have to use the +[`id_value`][] alias attribute to access the value of the non-PK `id` column. [`id_value`]: https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema.html#method-i-id_value NOTE: If you try to create a column named `id` which is not the primary key, -Rails will throw an error during migrations such as: -`you can't redefine the primary key column 'id' on 'my_products'.` -`To define a custom primary key, pass { id: false } to create_table.` +Rails will throw an error during migrations such as: `you can't redefine the +primary key column 'id' on 'my_books'.` `To define a custom primary key, pass { +id: false } to create_table.` CRUD: Reading and Writing Data ------------------------------ CRUD is an acronym for the four verbs we use to operate on data: **C**reate, **R**ead, **U**pdate and **D**elete. Active Record automatically creates methods -to allow an application to read and manipulate data stored within its tables. +to allow you to read and manipulate data stored in your application's database +tables. + +Active Record makes it seamless to perform CRUD operations by using these +high-level methods that abstract away database access details. Note that all of +these convenient methods result in SQL statement(s) that are executed against +the underlying database. + +The examples below show a few of the CRUD methods as well as the resulting SQL +statements. ### Create @@ -236,61 +389,124 @@ Active Record objects can be created from a hash, a block, or have their attributes manually set after creation. The `new` method will return a new object while `create` will return the object and save it to the database. -For example, given a model `User` with attributes of `name` and `occupation`, -the `create` method call will create and save a new record into the database: +For example, given a `Book` model with attributes of `title` and `author`, the +`create` method call will create an object and save a new record to the +database: ```ruby -user = User.create(name: "David", occupation: "Code Artist") +book = Book.create(title: "The Lord of the Rings", author: "J.R.R. Tolkien") + +# Note that the `id` is assigned as this record is committed to the database. +book.inspect +# => "#" ``` -Using the `new` method, an object can be instantiated without being saved: +While the `new` method will instantiate an object *without* saving it to the +database: ```ruby -user = User.new -user.name = "David" -user.occupation = "Code Artist" -``` +book = Book.new +book.title = "The Hobbit" +book.author = "J.R.R. Tolkien" + +# Note that the `id` is not set for this object. +book.inspect +# => "#" + +# The above `book` is not yet saved to the database. + +book.save +book.id # => 107 -A call to `user.save` will commit the record to the database. +# Now the `book` record is committed to the database and has an `id`. +``` Finally, if a block is provided, both `create` and `new` will yield the new -object to that block for initialization, while only `create` will persist -the resulting object to the database: +object to that block for initialization, while only `create` will persist the +resulting object to the database: ```ruby -user = User.new do |u| - u.name = "David" - u.occupation = "Code Artist" +book = Book.new do |b| + b.title = "Metaprogramming Ruby 2" + b.author = "Paolo Perrotta" end + +book.save +``` + +The resulting SQL statement from both `book.save` and `Book.create` look +something like this: + +```sql +/* Note that `created_at` and `updated_at` are automatically set */ + +INSERT INTO "books" ("title", "author", "created_at", "updated_at") VALUES (?, ?, ?, ?) RETURNING "id" [["title", "Metaprogramming Ruby 2"], ["author", "Paolo Perrotta"], ["created_at", "2024-02-22 20:01:18.469952"], ["updated_at", "2024-02-22 20:01:18.469952"]] ``` ### Read -Active Record provides a rich API for accessing data within a database. Below -are a few examples of different data access methods provided by Active Record. +Active Record provides a rich API for accessing data within a database. You can +query a single record or multiple records, filter them by any attribute, order +them, group them, select specific fields, and do anything you can do with SQL. ```ruby -# return a collection with all users -users = User.all +# Return a collection with all books +books = Book.all + +# Return a single book +first_book = Book.first +last_book = Book.last +book = Book.take ``` -```ruby -# return the first user -user = User.first +The above results in the following SQL: + +```sql +# Book.all +SELECT "books".* FROM "books" + +# Book.first +SELECT "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT ? [["LIMIT", 1]] + +# Book.last +SELECT "books".* FROM "books" ORDER BY "books"."id" DESC LIMIT ? [["LIMIT", 1]] + +# Book.take +SELECT "books".* FROM "books" LIMIT ? [["LIMIT", 1]] ``` +We can also find specific books with `find_by` and `where`. While `find_by` +returns a single record, `where` returns a list of records: + ```ruby -# return the first user named David -david = User.find_by(name: 'David') +# Returns the first book with a given title or `nil` if no book is found. +book = Book.find_by(title: "Metaprogramming Ruby 2") + +# Alternative to Book.find_by(id: 42). Will throw an exception if no matching book is found. +book = Book.find(42) +``` + +The above resulting in this SQL: + +```sql +SELECT "books".* FROM "books" WHERE "books"."author" = ? LIMIT ? [["author", "J.R.R. Tolkien"], ["LIMIT", 1]] + +SELECT "books".* FROM "books" WHERE "books"."id" = ? LIMIT ? [["id", 42], ["LIMIT", 1]] ``` ```ruby -# find all users named David who are Code Artists and sort by created_at in reverse chronological order -users = User.where(name: 'David', occupation: 'Code Artist').order(created_at: :desc) +# Find all books with a given an author, sort by created_at in reverse chronological order +Book.where(author: "Douglas Adams").order(created_at: :desc) ``` -You can learn more about querying an Active Record model in the [Active Record -Query Interface](active_record_querying.html) guide. +resulting in this SQL: + +```sql +SELECT "books".* FROM "books" WHERE "books"."author" = ? ORDER BY "books"."created_at" DESC [["author", "Douglas Adams"]] +``` + +There are many more Active Record methods to read and query records. You can +learn more about them in the [Active Record Query](active_record_querying.html) guide. ### Update @@ -298,63 +514,79 @@ Once an Active Record object has been retrieved, its attributes can be modified and it can be saved to the database. ```ruby -user = User.find_by(name: 'David') -user.name = 'Dave' -user.save +book = Book.find_by(title: "The Lord of the Rings") +book.title = "The Lord of the Rings: The Fellowship of the Ring" +book.save ``` A shorthand for this is to use a hash mapping attribute names to the desired value, like so: ```ruby -user = User.find_by(name: 'David') -user.update(name: 'Dave') +book = Book.find_by(title: "The Lord of the Rings") +book.update(title: "The Lord of the Rings: The Fellowship of the Ring") +``` + +the `update` results in the following SQL: + +```sql +/* Note that `updated_at` is automatically set */ + + UPDATE "books" SET "title" = ?, "updated_at" = ? WHERE "books"."id" = ? [["title", "The Lord of the Rings: The Fellowship of the Ring"], ["updated_at", "2024-02-22 20:51:13.487064"], ["id", 104]] ``` -This is most useful when updating several attributes at once. +This is useful when updating several attributes at once. Similar to `create`, +using `update` will commit the updated records to the database. If you'd like to update several records in bulk **without callbacks or validations**, you can update the database directly using `update_all`: ```ruby -User.update_all max_login_attempts: 3, must_change_password: true +Book.update_all(status: "already own") ``` ### Delete -Likewise, once retrieved, an Active Record object can be destroyed, which removes -it from the database. +Likewise, once retrieved, an Active Record object can be destroyed, which +removes it from the database. ```ruby -user = User.find_by(name: 'David') -user.destroy +book = Book.find_by(title: "The Lord of the Rings") +book.destroy +``` + +The `destroy` results in this SQL: + +```sql +DELETE FROM "books" WHERE "books"."id" = ? [["id", 104]] ``` If you'd like to delete several records in bulk, you may use `destroy_by` or `destroy_all` method: ```ruby -# find and delete all users named David -User.destroy_by(name: 'David') +# Find and delete all books by Douglas Adams +Book.destroy_by(author: "Douglas Adams") -# delete all users -User.destroy_all +# Delete all books +Book.destroy_all ``` Validations ----------- Active Record allows you to validate the state of a model before it gets written -into the database. There are several methods that you can use to check your -models and validate that an attribute value is not empty, is unique and not -already in the database, follows a specific format, and many more. +into the database. There are several methods that allow for different types of +validations. For example, validate that an attribute value is not empty, is +unique, is not already in the database, follows a specific format, and many +more. -Methods like `save`, `create` and `update` validate a model before persisting -it to the database. When a model is invalid these methods return `false` and no +Methods like `save`, `create` and `update` validate a model before persisting it +to the database. When a model is invalid these methods return `false` and no database operations are performed. All of these methods have a bang counterpart (that is, `save!`, `create!` and `update!`), which are stricter in that they -raise an `ActiveRecord::RecordInvalid` exception when validation fails. -A quick example to illustrate: +raise an `ActiveRecord::RecordInvalid` exception when validation fails. A quick +example to illustrate: ```ruby class User < ApplicationRecord @@ -377,9 +609,9 @@ Callbacks --------- Active Record callbacks allow you to attach code to certain events in the -life-cycle of your models. This enables you to add behavior to your models by -transparently executing code when those events occur, like when you create a new -record, update it, destroy it, and so on. +lifecycle of your models. This enables you to add behavior to your models by +executing code when those events occur, like when you create a new record, +update it, destroy it, and so on. ```ruby class User < ApplicationRecord @@ -404,8 +636,8 @@ Migrations ---------- Rails provides a convenient way to manage changes to a database schema via -migrations. Migrations are written in a domain-specific language and stored -in files which are executed against any database that Active Record supports. +migrations. Migrations are written in a domain-specific language and stored in +files which are executed against any database that Active Record supports. Here's a migration that creates a new table called `publications`: @@ -425,14 +657,15 @@ class CreatePublications < ActiveRecord::Migration[7.2] end ``` -Note that the above code is database-agnostic: it will run in MySQL, -PostgreSQL, SQLite, and others. +Note that the above code is database-agnostic: it will run in MySQL, PostgreSQL, +SQLite, and others. -Rails keeps track of which migrations have been committed to the database and stores them -in a neighboring table in that same database called `schema_migrations`. +Rails keeps track of which migrations have been committed to the database and +stores them in a neighboring table in that same database called +`schema_migrations`. -To run the migration and create the table, you'd run `bin/rails db:migrate`, -and to roll it back and delete the table, `bin/rails db:rollback`. +To run the migration and create the table, you'd run `bin/rails db:migrate`, and +to roll it back and delete the table, `bin/rails db:rollback`. You can learn more about migrations in the [Active Record Migrations guide](active_record_migrations.html).