Rails Guide — Part 6 Database Models Continued
Last week we looked at the has and belongs to many association in Rails and how it was different from the has many through/belongs to association. Today we will discuss the has one relationship, as well as data validation, custom scopes in the model component.
As a reminder, our models are as below. We already created them last week.
Suppose we want each tenant to have exactly ONE custodian, we can use the has_one association.
Let’s go ahead and create the reference column in the custodians table first:
This creates a migration in our db directory. Let’s also remove the code where it says null: false. If we leave this in, Rails will reject any custodians that are not associated with a tenant.
The new migration file should look like this, and we can run rails db:migrate now.
Checking our schema file, we can see everything is correct so far:
The next step is to add the instance method in our tenant model file:
We can also make the association bi-directional by adding belongs_to in the custodian model. For our simple app, we will skip this part.
Now in our seeds.rb file, we can create some custodians:
Remember we have to run rails db:reset at this point. Running rails db:seed will duplicate our seed data. After that, we can quickly go into the Rails console to confirm if we have the correct data.
The final step is to modify the view files so we can see each tenant’s custodian in the show page. In the case where he does not have one, we can show a customized message:
Run rails s to start the server and navigate to localhost:3000/tenants:
If we go to the show page for each tenant:
Great job so far! The next topic I want to focus on is data validation. If you look at our custodian model, you can see it has a specialty column. However both of our custodian objects from a moment ago were put into the database without any value. We can check this in the Rails console with Custodian.all:
Suppose we want to have some data validation to make sure a specialty must be entered in order to create a custodian, we can achieve this in the custodian model file:
Now if we run rails db:reset we would get an error, because the specialty is missing from our custodian objects:
Similarly, if we go to localhost:3000/custodians and try to create a new custodian from the webpage, we would get the same error:
Let’s go back and update our seeds.rb file, as well as add in a few more custodians like so and run rails db:reset.
We can go to localhost:3000/custodians to verify everything is updated:
On the index page, imagine the scenario where we only want to display the custodians that are available, in the words, ones whose tenant_id is nil. This is where custom scope would come in.
Inside of the custodian model, we can create a new class method:
Remember we have to use where() because find() only returns the first matching query. Whereas where returns a collection, even if that collection only has one item. The method name available is something I create, of course you can use whatever descriptive method name you prefer.
Moving onto the custodians controller, within the index method, instead of calling Custodian.all, we can use our custom scope method to call Custodian.available and assign it to the same variable:
After saving our files and refresh the index page for custodians, we can see only 1 is shown, which is the expected result.
We are moving along nicely! In the next blog, we will take a look at the view component in a Rails application, see you then!