Create the Note and Comment Resources
The Note Resource
The Note resource is a very simple resource. It represents a To Do note. Basically all it contains is a title and a body. Its structure is as follows:
||string|| The UUID of the note, e.g. |
||string|| The title of the note, e.g. |
||text||The body of the note.|
||datetime||The time in UTC when the Note was created.|
||datetime||The time in UTC when the Note was last updated.|
||string||The URI of the ApiUser who created the Note.|
||string||The URI of the ApiUser who last modified the Note.|
||integer||For optimistic locking.|
We will create this resource in two steps. First, we'll create a basic resource using these instructions, then we'll tailor it for our purposes. This is to be considered best practice.
So, first take a look at the instructions for creating an SQL based Resource. If you compare the structure of the standard resource with the one described in the table above, you'll see that the differences are very small.
Go ahead and follow the instructions to create a basic, bog standard resource called Note. Return here when you're done.
Implementing the Differences
Comparing what we now have to what we need as the final result, it's quickly apparent that all we need to do is change the name of the name attribute to title and the name of the description attribute to body. Everything else is identical.
You should do this attribute by attribute, starting with the specs. Routing won't be affected, so start with modifying the model specs. Change the spec that tests for the presence of the name attribute to test for title instead. Run the model specs, see the changed spec fail, and then take actions to correct the situation. To change the name of the attribute, create a migration to do so. Change the corresponding index at the same time. (If you don't know how to do this, google it.) Don't forget to reannotate your source after you've run the migration (annotate -i). Also change the attribute name in specs/factories/note.rb.
Run the specs again; if you've done things right, the specs should pass.
When all specs pass again, proceed with the second change: first modify the spec to test for the desired end result, then run the specs and see the tests fail. Then create a migration, run it, reannotate, and run the specs again; they should pass.
It's important that you do these things in the above order: one attribute at a time. It's also important that you see the test fail before you make any other changes, then make the test succeed again. Don't fall for the temptation to make multiple changes at the same time, and don't change the code before the specs.
You should now have created two migrations and the tests should pass again. You now have the resource as you want it in terms of attributes.
Run the specs for models again – they should pass.
Next, run the tests for views. There will be errors since attributes have changed. Fix them by simply substituting the new names – one by one – first in the specs, then in the view template.
Then continue with the controllers. Fix any errors in the same way: first update the specs, run them again and see them fail, then change the controller code so they pass again.
Finally, run all tests (rspec). When all specs pass, you're ready for the next step.
Adding Further Functionality
With Notes, we want to make sure that there always is a
title present. To do this, first create a test in
spec/models/note_spec.rb, in the attributes section at the top of the file:
it "should require a title" do build(:note, title: nil).should_not be_valid build(:note, title: "").should_not be_valid build(:note, title: " ").should_not be_valid end
This specifies that the title may not be
nil, nor the empty string, nor a string containing only whitespace. Run
rspec. The test will fail, as there is no code to validate the
title. To add validation, open the model at
app/models/note.rb and add the following under the validation section comment:
validates :title, presence: true
rspec will show that all specs now pass. This concludes the creation of the Note resource.
The Comment Resource
The Comment resource is related to the Note resource in a many-to-one relationship: a Note can have many Comments, but each Comment only belongs to one Note. The structure of a Comment is as follows:
||text||The UUID of the Comment.|
||text||The body of the Comment.|
||datetime||The time in UTC when the Comment was created.|
||datetime||The time in UTC when the Comment was last updated.|
||string||The URI of the ApiUser who created the Comment.|
||string||The URI of the ApiUser who last modified the Comment.|
||integer||For optimistic locking.|
||string||The UUID of the Note to which this Comment belongs.|
As you can see, it's identical in structure to Notes, except that Comments have no
title, only a
body. They also have a
note_id attribute which links to the Note to which the Comment belongs.
Create a basic resource for Comments using the instructions for creating an SQL based Resource. Return here when you're done.
Tailoring the Comment Resource
Looking at the Comment resource description above, you'll see that name should be deleted, that description should be renamed body, and that a new attribute named note_id needs to be added.
Do these changes one by one, following the same procedure as before. You will be creating three migrations in total.
note_id is of type
string, and that there's an index on note_id; if not, add one.
Now proceed exactly like described for Note to arrive at the point where all specs again pass.
It's important that you understand that
note_id isn't a replacement for the
title, but something completely different: do not expose the
note_id, and don't allow it to be passed in as a parameter to the CommentsController. Check out the documentation for Comments to see what should be matchable and searchable and set things up accordingly.
Finally, add a requirement for
body to be present (instead of the
title) and make the specs pass. If in doubt, compare your code to the code in the official repo.