1. Generating a Model

Now that we've got a nice front end, let's work on the backend and actually get the app to do something.

The first thing we are going to do is to create a model. To review, the role of models are to interact with the database, such as fetching information from the database and storing information into the database.

We can create models by running a command like this:

rails generate model ModelName

In our case, let's name our model Idea. Let's go ahead and create the Idea model:

rails generate model Idea

Naming Conventions

In general, the convention for naming models is to use the singular form. For example, instead of Ideas, we want to name the model Idea.

On the other hand, the convention for controllers is to use the plural form for controller names. For example, instead of naming the controller idea, we want to name it ideas.

Not following this convention will lead to bugs, so whenever you create a model or controller, make sure to be careful of the singular or plural form.

  • Models - Singular (for example, Post, Article)
  • Controllers - Plural (for example, Posts, Articles)

This will create a file named something like this: xxxxxxxxx_create_ideas.rb. The "xxxx"s will be replaced by a time stamp of when the file was created. These files are called migration files.

What are Migration Files?

When we want to store new information into the database, we need to create new tables and columns.

Think of a database like an excel spreadsheet. At first, an excel spreadsheet is empty.

image.png

Let's say we are organizing some kind of event, and we need to keep track of the information of the people that are coming to the event. In our excel spreadsheet, we would need to create a new table and new columns to do this:

image.png

Then, when people sign up for the event, we can keep track of the information easily:

image.png

With databases, we need to follow the same steps as we would with spreadsheets.

Initially, the database is empty. Whenever we want to keep track of new information in the database, we need to create new tables and columns. The way we create new tables and columns in the database in Rails is by running database migrations.

The first step in migrating new tables and columns into the database is by telling Rails what tables and columns we should add to the database. We can do this by entering the information in the migration file.

In short, the role of migration files is to specify what tables and columns we need to add or change in the database.

It's also important to note that in Rails, every time you generate a model, a migration file is generated. We will get into the details of how migrations work again in later lessons.

Go into VScode and press Command + P and type in "create ideas" and it should find your migration file that looks like xxxxxxxxx_create_ideas.rb. Inside this file, we can specify the database columns we want to add.

What we are going to add into the database:

class CreateIdeas < ActiveRecord::Migration
  def change
    create_table :ideas do |t|
      t.text :description
      t.string :author
      t.timestamps
    end
  end
end

Make your file look exactly like above and save the file.

Now that we have edited our migration file, we have to tell Rails to migrate these columns. Type in the following command in the terminal and press enter:

rails db:migrate

What does rails db:migrate do?

We talked about how migration files specify what tables and columns need to be added or modified. What is this rails db:migrate command that we just ran here?

First, let's think about what "migrate" means. In Rails, migrate means to update the database structure, for example adding a new table or adding a new column to the database.

Running rails db:migrate will migrate, or update the database based on migration files.

In short, Migration files tell what database tables and columns to add or modify, and rails db:migrate takes that information and updates the database.

Getting Errors?

Chances are you have a typo in the migration file. Double check your file to make sure you don't have any typos before you run your migrations. Make sure the file looks exactly like the code above.

As a rule of thumb, every time you run a migration, you should restart your server. So let's go ahead and restart our server (Control + C to stop the server and rails s to start the server again).

If done correctly, if you go into schema.rb, you should now see the columns added to the ideas table.

What is schema.rb?

Every Rails application includes a file called schema.rb. schema.rb is the file that lays out all of the database tables and columns in the application.

For example, if we look at our schema.rb file now, it should look something like this:

ActiveRecord::Schema[7.1].define(version: 2023_12_18_065455) do 
  create_table "ideas", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
    t.text "description"
    t.string "author"
    t.datetime "created_at", null: false t.datetime "updated_at", null: false
  end
end

schema.rb is updated automatically every time you run a migration to reflect the new changes to the database.

In short, schema.rb specifies what database tables and columns are included in the application.

image.png

Awesome! You've set up your first model! :)

Now that we've got a model and a controller for our Ideas, we can start interacting with the database. Get ready to do some web developerly things!

Let's go to our terminal (the one that is not running the rails server) and type in rails console (or rails c for short) to open up the rails console. In the rails console, we can type in ruby code to interact with our rails application.

Rails Console

The rails console is used to execute ruby commands. However, you cannot run commands such as git add . or rails routes since they are not commands written in the ruby language.

When you want to run commands that are not in the ruby language, make sure to exit out of the rails console. You can do that by typing in the following command:

exit

First, let's create an idea in our database through the console. Type in the following in the rails console:

Idea.create(description: "This is the greatest idea ever", author: "Me")

Press enter to create the idea and save it into the database.

create

Rails offers a method called create. The create method will create a new instance of the object and save it into the database.

For instance, if we want to create a new idea, we can run the following command:

Idea.create

However, this will create an Idea object that is empty.

Idea.create(description: "This is the greatest idea ever", author: "Me")

In this case, we are passing in description: "This is the greatest idea ever", author: "Me" as the parameters. By passing these values as parameters, we are telling Rails what the description should be and who the author should be for the idea.

image.png

In short, you can create an instance of an object with the following format:

ModelName.create(column_name_1: value, column_name_2: value, ...)

Now let's try to display all of our ideas in the console. We can do this by typing the following:

Idea.all

all

You can display all instances of an object in the rails console with the all method. For example, let's say we have 10 ideas stored in our database. We can display all 10 of these ideas in the rails console by running this command:

Idea.all

This is going to print out something like below:

=> #<ActiveRecord::Relation [#<Idea id: 1, description: "This is the greatest idea ever", author: "Me", created_at: "2020-07-02 12:00:14", updated_at: "2020-07-02 12:00:14">]

Think of some other brilliant ideas to add to your app and add a couple more. Once you've done that, take a look at your ideas by typing in Idea.all once again.

You can see that you've successfully added the ideas to your database.

Awesome! You've created your first idea and stored them in the database. Next, let's try to show everything we stored in the database on to our website.

First, let's make sure we exit from the rails console. Type the following in the terminal to exit out of the rails console:

exit

Fetching Records from the Controller

Next, let's go into our ideas_controller.rb and see what we can do.

In our index method, let's add the following:

def index
  @ideas = Idea.all
end

Here we are assigning all ideas stored in the database into an instance variable called @ideas.

Next, let's go into index.html.erb inside the app/ideas directory and change it to look like the following. We'll go over what we are doing and the new syntax right after this.

<% @ideas.each do |idea| %>
  <h3><%= idea.description %></h3>
  <h4><%= idea.author %></h4>
<% end %>

Let's go back into our browser and refresh the page. You should now see all of your ideas listed out.

It seems the things we stored in the database are now being displayed. There's a bunch of new things here, but don't panic - let's go over them step by step.

How Models, Controllers, and Views Work Together in Rails

Let's take a look at the MVC diagram from previous lessons:

image.png

To review:

  • Models: responsible for fetching data from the database and storing data into the database
  • Views: responsible for presenting information
  • Controllers: responsible for being the bridge between the model and the views

Let's take a look at how our application is working.

First, when we visit our webpage, it makes a request to the server.

Next, the router determines which controller action to trigger. In this case, the index action of ideas_controller.rb is triggered (refer back to previous lessons to review).

Inside ideas_controller.rb, we fetch all Idea objects in the database and store it into an instance variable @ideas.

When we fetch all of the Idea objects in the database, the **model is performing that task** (Models: responsible for fetching data from the database and storing data into the database).

image.png

Instance variables declared in controller actions can be used in the view file:

image.png

Here's a diagram that shows how everything is working together:

image.png

What's this new syntax <% %>?

So far, we have saved all of our view files as filename.html.erb. erb stands for Embedded Ruby. As mentioned briefly in a previous lesson, using the erb file extension enables us to embed ruby code into HTML.

We can embed ruby code with the <% %> syntax. To display the result of running the ruby code to the HTML, we use <%= %>.

For example:

<!-- without the %=, it won't display the result of running the ruby code to the user -->
<% number = 1 + 1 %>

<!-- with %= it will display the result of running the ruby code to the user -->
<%= number %>

The above code will result in the following HTML:

2

Overview

Don't worry if this all doesn't make sense yet. With enough practice, all of this will become second-hand nature!

Styling the index page

Our index page looks pretty ugly right now. Let's make this look a little bit nicer.

Let's add some tailwind classes to make the appearance better.

For being able to use default colors from tailwind, require the colors and add them to the theme section in tailwind.config.js. The final tailwind config file should look like below:

const colors = require('tailwindcss/colors')

module.exports = {
  content: [
    './app/views/**/*.html.erb',
    './app/helpers/**/*.rb',
    './app/assets/stylesheets/**/*.css',
    './app/javascript/**/*.js'
  ],
  theme: {
    'fontFamily': {
      'open-sans': ['Open Sans', 'sans-serif'],
      'dosis': ['Dosis', 'sans-serif'],
      'pacifico': ['Pacifico', 'sans-serif']
    },
    'colors': {
      ...colors,
      'primary': {
        500: '#337ab7'
      }
    }
  }
}

Now, let's add the following content in the index.html.erb

<div class="rounded overflow-hidden shadow-lg">
  <div class="px-6 py-8 h-full">
    <div class="font-bold text-xl mb-2">This is some text within the body</div>
  </div>
</div>

Save the file and refresh the page. You'll see that one card is now implemented, but there's no content inside of it. What we want to do is create a new panel for each of our ideas. We can do this by using an each loop to iterate through each idea in @ideas.Make your index.html.erb look like this:

<div class="max-w-screen-xl mx-auto">
  <% @ideas.each do |idea| %>
    <div class="rounded overflow-hidden shadow-lg">
      <div class="px-6 py-8 h-full">
        <div class="font-bold text-xl mb-2"><%= idea.description %></div>
        <p class="text-sm text-gray-700 "><%= idea.author %></p>
      </div>
    </div>
  <% end %>
</div>

Save the file and refresh the page. You should now see that each of the ideas have their own card, this is pretty cool!

Let's go back into the browser and refresh the page. Awesome! You should now see each idea wrapped around in a card.

Lesson list