Learn to create a product maintenance application with SQL support
At the heart of the Depot application is a database. Getting this installed and configured and tested before proceeding will prevent a lot of headaches. If you are not certain about what you want, take the defaults, and it will go easily. If you know what you want, Rails makes it easy for you to describe your configuration.
Creating a Rails application
In Creating a New Application, you saw how to create a new Rails application. We will do the same thing here. Go to a command prompt and type rails new followed by the name of our project. Here, our project is called depot, so make sure you are not inside an existing application directory, and type this:
work> rails new depot
We see a bunch of output scroll by. When it has finished, we find that a new directory, depot, has been created. That’s where we’ll be doing our work:
work> cd depot
depot> ls -p
Creating the database
For this application, we’ll use the open-source SQLite database (which you’ll need if you’re following along with the code). We’re using SQLite version 3 here.
SQLite 3 is the default database for Rails development and was installed along with Rails in Installing Rails. With SQLite 3, no steps are required to create a database, and we have no special user accounts or passwords to deal with. So, now you get to experience one of the benefits of going with the flow (or, convention over configuration, as the Rails folks say…ad nauseam).
If it’s important to you to use a database server other than SQLite 3, the commands to create the database and grant permissions will be different. You can find some helpful hints in the database configuration section of Configuring Rails Applications in the Ruby on Rails Guides.
Generating the scaffold
Back in our initial guess at application data, we sketched out the basic content of the products table. Now let’s turn that into reality. We need to create a database table and a Rails model that lets our application use that table, a number of views to make up the user interface, and a controller to orchestrate the application.
So, let’s create the model, views, controller, and migration for our products
table. With Rails, you can do all that with one command by asking Rails to generate a scaffold for a given model. Note that on the command line that follows, we use the singular form, Product
. In Rails, a model is automatically mapped to a database table whose name is the plural form of the model’s class. In our case, we ask for a model called Product
, so Rails associates it with the table called products
. (And how will it find that table? The development
entry in config/database.yml
tells Rails where to look for it. For SQLite 3 users, that’ll be a file in the DB directory.)
Note that that command is too wide to fit comfortably on the page. To enter a command on multiple lines, put a backslash as the last character on all but the last line, and you’ll be prompted for more input. Windows users need to substitute a caret (^) for the backslash at the end of the first line and a backslash for the forward-slash in bin/rails
:
depot> bin/rails generate scaffold Product \
title:string description:text image_url:string price:decimal
The generator creates a bunch of files. The one we’re interested in first is the migration one, namely,
20190425000001_create_products.rb
.
Migration represents a change we either want to make to a database as a whole or to the data contained within the database, and it’s expressed in a source file in database-independent terms. These changes can update both the database schema and the data in the database tables. We apply these migrations to update our database, and we can unapply them to roll our database back.
The migration has a UTC-based timestamp prefix (20190425000001), a name (create_products)
, and a file extension (.rb
, because it’s Ruby code).
The timestamp prefix that you see will be different. In fact, the timestamps used in this book are clearly fictitious. Typically, your timestamps won’t be consecutive; instead, they’ll reflect the time the migration was created.
Applying the migration
Although we’ve already told Rails about the basic data types of each property, let’s refine the definition of the price to have eight digits of significance and two digits after the decimal point:
class CreateProducts < ActiveRecord::Migration[6.0]def changecreate_table :products do |t|t.string :titlet.text :descriptiont.string :image_urlt.decimal :price, precision: 8, scale: 2t.timestampsendendend
Now that we’re done with our changes, we need to get Rails to apply this migration to our development database. We do this by using the bin/rails db:migrate
command:
depot> bin/rails db:migrate
And that’s it. Rails looks for all the migrations not yet applied to the database and applies them. In our case, the products table is added to the database defined by the development
section of the database.yml
file.
OK, all the groundwork has been done. We set up our Depot application as a Rails project. We created the development database and configured our application to be able to connect to it. We created a products controller and a Product model and used migration to create the corresponding products table. And a number of views have been created for us. It’s time to see all this in action.
Seeing the list of products
With three commands, we’ve created an application and a database (or a table inside an existing database, if you chose something besides SQLite 3). Before we worry too much about what happened behind the scenes here, let’s try our shiny new application.
First, we start a local server, supplied with Rails (remember if you are using a virtual machine, you must do bin/rails server -b 0.0.0.0
):
depot> bin/rails server
As it did with our demo application, this command starts a web server on our localhost
, port 3000
. If you get an error saying Address already in use when you try to run the server, that means you already have a Rails server running on your machine. If you’ve been following along with the examples in the book, that might well be the Hello, World! application. Find its console and kill the server using Ctrl-C
. If you’re running on Windows, you might see the prompt Terminate batch job (Y/N)?. If so, respond with y.
Let’s connect to our application. Remember, the URL which has the name of the controller in lowercase (products
). The application looks like the following screenshot.
That’s pretty boring. It’s showing us an empty list of products. Let’s add some. Click the New Product link. A form should appear, as shown in the following screenshot.
These forms are simply HTML templates, like the ones you created in Hello, Rails!. In fact, we can modify them. Let’s change the number of rows and columns in the Description field:
<%= form_with(model: product, local: true) do |form| %><% if product.errors.any? %><div id="error_explanation"><h2><%= pluralize(product.errors.count, "error") %> prohibited this product from being saved:</h2><ul><% product.errors.full_messages.each do |message| %><li><%= message %></li><% end %></ul></div><% end %><div class="field"><%= form.label :title %><%= form.text_field :title %></div><div class="field"><%= form.label :description %><%= form.text_area :description, rows: 10, cols: 60 %></div><div class="field"><%= form.label :image_url %><%= form.text_field :image_url %></div><div class="field"><%= form.label :price %><%= form.text_field :price %></div><div class="actions"><%= form.submit %></div><% end %>
we’ve adjusted one field to taste, so let’s fill it in, as shown in the following screenshot (note the use of HTML tags in the description—–this is intentional and will make more sense later).
Click the Create button, and you should see that the new product was successfully created. If you now click the Backlink, you should see the new product in the list, as shown in the screenshot below:
Perhaps it isn’t the prettiest interface, but it works, and we can show it to our client for approval. She can play with the other links (showing details, editing existing products, and so on). We explain to her that this is only a first step—we know it’s rough, but we wanted to get her feedback early. (And four commands probably count as early in anyone’s book.)
At this point, we’ve accomplished a lot with only four commands. Before we move on, let’s try one more command:
bin/rails test
Included in the output should be a line that says 0 failures
, 0 errors
. This is for the model and controller tests that Rails generates along with the scaffolding. They’re minimal at this point, but simply knowing that they’re there and that they pass should give you confidence. As you proceed through this course, you’re encouraged to run this command frequently, because it’ll help you spot and track down errors.
Note that if you’ve used a database other than SQLite 3, this step may have failed. Check your database.yml
file.
A live terminal
You can run the commands that are provided in this lesson by using the below terminal.
A running application to add products
The following SPA is the output of all commands which are discussed in this lesson. You do not need to run any command in this section. Just press the run button to see the output. However, if you want to process yourself then first use the terminal to run the commands.
Note: We have already added some dummy products for you but still you can add product(s) of your choice as well.
Get hands-on with 1400+ tech skills courses.