Rails: Modeling an App

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.

Part 1: Views

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:

  1. Feed
  2. Trending page
  3. Profile / settings
    • Your personal page
  4. Log in / Sign up *
  5. FAQ *

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.

Part 2: Data

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/ ...

Part 3: Actions

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.

Part 4: Models

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!)

Part 5: Relationships

The next step was to be clear about the relationships between the models. There are three types of relationships:

  1. 1-1: If a User could only have one Tweet, and if each Tweet belonged to exactly one User. In Rails, called a has_one relationship.
  2. 1-many: If a User could have many Tweets, and if each Tweet belonged to one User OR if each Tweet had many Users, 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 Players and so on.) Called a has_many relationship in Rails.
  3. Many-many: If a User could have many Tweets, and a Tweet could be tweeted by many Users. Called a has_and_belongs_to_many relationship in Rails.

To describe these relationships between our five models, we drew the following diagram:

  1. User to Profile: 1-1
  2. User to Tweet: 1-many
  3. Tweet to Hashtag: Many-many
  4. User to Follower: 1-many (special scenario)

Part 6: The Whole Database

The last part was learning how to model the relationships in the database.

  1. 1-1: Put a 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.
  2. 1-many: Put a 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!.
  3. Many-many: Create a separate table, called a join table. This is traditionally named 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.