Rails Guide — Part 5 Database Models Continued
In our previous blog, we took a look at the model component (The M in MVC) in a Rails application. We learned how to manually create a model and a table, add and remove columns to the table, as well as some commonly used associations between models: has many, belongs to, has many through. Today we will explore the alternative to has many through, the has and belongs to many association.
Before we start coding, let’s take a look at what we want to build:
We will have a landlord and tenant model, the relationship I want for the two is many to many, but without any joiner model. A tenant will have one custodian, and in the end we will connect the landlord and custodian tables through tenant. The examples are arbitrary and simply to demonstrate, in real life, a residential tenant most likely will only have one landlord, and a commercial tenant (such as a restaurant or shop that has many branches) will definitely have many landlords.
Let’s create a new Rails app first by running rails new ModelApp and then rails db:create
Inside of our application directory, let’s create those three models using a powerful Rails generator called scaffold. We have seen how the resource generator can quickly create a model, controller, migration for the table, a directory for view files and all CRUD routes for us, similarly, the scaffold generator does all of the above, AND also generates all the index/show/new/edit controller action codes and the view file codes.
We will make use of scaffold generator to get our boilerplate codes done and we will create the associations manually.
As you can see from running the scaffold generator, Rails created a lot of files for us. Do the same for our tenant and custodian models.
Switching to Visual Studio Code, we can see Rails has already taken care of generating all the CRUD functionalities in our controllers, and view files. At this point we can simply run the rails db:migrate to finalize our migrations, then rails s and navigate to localhost:3000/landlords or tenants or custodians:
We can see everything is working. We can add new landlords or edit existing ones from our pages.
Now comes the fun part. Typically in a many to many relationship, we would have a joiner model. However there might be times where a joiner model is irrelevant or unnecessary, Rails gives us the option to connect two tables using the has_and_belongs_to_many association. We will still need to create a table that holds the primary key (or reference) for our landlord and tenant tables. By convention, this table should be called landlords_tenants. I will name the table building, just to show it’s possible to name it however you want. By overwriting it, we will also need to let our models know what is the joiner table later on.
Let’s run rails g migration create_buildings landlord:belongs_to tenant:belongs_to and then run rails db:migrate
Taking a look at our new migration file:
The final step is to add the association in the respective models. This is how you would do it if you went with the convention name landlords_tenants for the joiner table name.
However we named our table buildings. There’s an extra step to let our models know where the joiner is:
Now let’s create a few landlords and tenants, we can do it in localhost:3000/landlords/new, localhost:3000/tenants/new or in the seeds.rb file. I will be creating mine in the seeds file since we will also need to create the associations. A simple seeds file might look like this:
Running rails db:seed
Now let’s go modify the show page for each landlord, so their tenants will be shown. And we will do the same for each tenant.
Run the Rails server, going to localhost:3000/landlords. So far so good:
If we go to each landlord’s show page, we can see the tenants associated with them:
And going to the tenant’s show page, we can see it’s also working perfectly:
Great job so far! Let’s take a break and finish off our discussion on model next week, where we will look at the has one association, data validations and custom scopes!