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.
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:
Then, when people sign up for the event, we can keep track of the information easily:
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:
ideas
tabledescription
column inside of ideas
table (text
type)author
column inside of ideas
table (string
type)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.
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 .
orrails 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
. Thecreate
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.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
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:
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 ofideas_controller.rb
is triggered (refer back to previous lessons to review).Inside
ideas_controller.rb
, we fetch allIdea
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).Instance variables declared in controller actions can be used in the view file:
Here's a diagram that shows how everything is working together:
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
Idea
in the databaseIdea
@ideas
inside the controllerInside index.html.erb
@ideas
variable defined in the controller@idea
holds all of the Idea
objects in the database@ideas
description
and author
Don't worry if this all doesn't make sense yet. With enough practice, all of this will become second-hand nature!
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.