Today we did a lot of practice designing a Rails application: thinking about the structure at a high level and doing a deep dive into models. These notes should serve as a refresher for what we did in class, modeling a simple Twitter app.
Views (the V in MVC) are simply HTML pages that are shown to the user. The first part of the activity was listing out all the different pages:
Note that the ones with *s by them are static pages, meaning that the same content is shown to each user. The ones without *s are dynamic pages, meaning their content depends on the user.
We then talked about all the data that's stored in the application. Remember that some (one the picture below), fell nicely into categories, but some were harder to reason about. For instance, how would we think about which tweets a user has access to (i.e. permissions)? Is that information stored or calculated? How so?
We also discussed how data can be laid out in a database, a lot like an Excel spreadsheet. A sample user table might look like the below (note that all tabes have an id
column, and it starts with 1
).
users
id | handle | display_name | profile_picture_url | ..etc |
---|---|---|---|---|
1 | @daretorant | Salman Ansari | https://avatars3.githubusercontent.com/u/105090?v=3&s=400 | ... |
2 | @khanotations | Rafi Khan | https://pbs.twimg.com/profile_images/557016021148520449/7uIOJwuR.jpeg | ... |
3 | @m-low | M Lowenkamp | http://placekitten.com/ | ... |
What are all the actions that can be taken on your website? Usually actions take the forms of "X does Y to Z"—a user creates a tweet. A lot of the time, they will fit into four main verbs, defined by CRUD: create, read, update, and destroy. When thinking about actions, try to fit them into one of those verbs (though of course, it's not always possible). Then think about who or what is doing the creating, and what is being created.
Now we tried to group our data into models, the M in MVC (we'll get to controllers later, they have to do with the actions above). Models are the conceptual units that allow us to group data into nouns, like User
, Tweet
, Friendship
, etc. (Note that model names are always singular and capitalized.) Which nouns you pick are up to you, and reflect the structure of your application. As you design more and more apps, choosing the right models will become easier and easier—this can, however, often be the toughest part of designing an application.
For our Twitter app, we chose 5 models: User
, Tweet
, Profile
, Hashtag
, and Follower
. (Note that these were revised later—it's also common to revisit the design and change it afterward!)
The next step was to be clear about the relationships between the models. There are three types of relationships:
User
could only have one Tweet
, and if each Tweet
belonged to exactly one User
. In Rails, called a has_one
relationship. User
could have many Tweet
s, and if each Tweet
belonged to one User
OR if each Tweet
had many User
s, and each User
belonged to one Tweet
. (The second example wouldn't really ever happen, but you can imagine another scenario such as a Team
having many Player
s and so on.) Called a has_many
relationship in Rails. User
could have many Tweet
s, and a Tweet
could be tweeted by many User
s. Called a has_and_belongs_to_many
relationship in Rails. To describe these relationships between our five models, we drew the following diagram:
The last part was learning how to model the relationships in the database.
model_id
column in the less significant model. Ex: a user could exist without a profile, but a profile could not exist without a user, so the profile is less significant and thus gets a user_id
column. model_id
column in the "many" side of the relationship. Ex: The tweets table receives a user_id
column. Remember that we rarely, if ever, allow arrays in the database!. firstmodels_secondmodels
(where the first model is whichever comes alphabetically first). It simply stores the ids of both models that are in the relationship. Ex: for the tweets-hashtags relationship, we would make a hashtags_tweets
table, which would have just two columns: hashtag_id
and tweet_id
. Note that the tweet-hashtag example is not included in the picture but the user following example is. Becauser a Follower
is actually just a User
, we can create a model which we call a Following
, with the table followings
. It behaves a lot like a join table in that it stores the follower_id
and the following_id
, which are understood to be user ids. We can also choose to add other information, like created_at
, if we want to keep track of when one user started following another.