We begin the Microposts resource by creating a Micropost model, which captures the essential characteristics of microposts. What follows builds on the work from “The Microposts resource Section”; as with the model in that section, our new Micropost model will include data validations and an association with the User model. Unlike that model, the present Micropost model will be fully tested, and will also have a default ordering and automatic destruction if its parent user is destroyed.
The basic model
The Micropost model needs only two attributes: a content attribute to hold the micropost’s content and a user_id to associate a micropost with a particular user.
As with the case of the User model, we generate the Micropost model using generate model
Because we expect to retrieve all the microposts associated with a given user id in reverse order of creation, we add an index on the user_id and created_at columns
db/migrate/[timestamp]_create_microposts.js
With the migration, we can update the database as usual
Micropost validations
Now that we’ve created the basic model, we’ll add some validations to enforce the desired design constraints. One of the necessary aspects of the Micropost model is the presence of a user id to indicate which user made the micropost.
The initial micropost tests parallel those for the User model.
test/models/micropost_test.js
The validity test is already successful, but the user id presence test should be failing because there are not currently any validations on the Micropost model
To fix this, we just need to add the user id presence validation
app/models/micropost.js
The model tests should now be successful
Next, we’ll add validations for the micropost’s content attribute. As with the user_id, the content attribute must be present, and it is further constrained to be no longer than 140 characters, making it an honest micropost. We’ll first write some simple tests, which generally follow the examples from the User model validation tests
test/models/micropost_test.js
app/models/micropost.js
At this point, the full test suite should be successful
User/Micropost associations
When constructing data models for web applications, it is essential to be able to make associations between individual models. In the present case, each micropost is associated with one user, and each user is associated with (potentially) many microposts
app/models/micropost.js
app/models/user.js
With the association thus made, we can update the test
test/models/micropost_test.js
Of course, after this minor refactoring the test suite should still be successful
Micropost refinements
In this section, we’ll add a couple of refinements to the user/micropost association. In particular, we’ll arrange for a user’s microposts to be retrieved in a specific order, and we’ll also make microposts dependent on users so that they will be automatically destroyed if their associated user is destroyed.
Default scope
By default, the user.microposts method makes no guarantees about the order of the posts, but (following the convention of blogs and Twitter) we want the microposts to come out in reverse order of when they were created so that the most recent post is first. We’ll arrange for this to happen using a default scope.
test/models/micropost_test.js
The test suite should be failing
Adding this in a default scope for the Micropost model
app/models/micropost.js
With the code, the tests should be successful
Dependent: destroy
Apart from proper ordering, there is a second refinement we’d like to add to microposts. Recall from “Deleting users Section” that site administrators have the power to destroy users. It stands to reason that, if a user is destroyed, the user’s microposts should be destroyed as well.
We can arrange for this behavior by passing an option to the hasMany association method
app/models/user.js
We can verify is working with a test for the User model. All we need to do is save the user (so it gets an id) and create an associated micropost. Then we check that destroying the user reduces the micropost count by 1.