Webpages Adding a Page to the App
In this demonstration, I will show how to add a webpage to an existing Rails web app.
General Steps
In general, the steps for adding a webpage to an existing Rails-based web app are as follows. To understand these steps, you will need to understand the deets on the Rails MVC architecture.
-
Step 1 Add a Route. This step specifies a URL for the web page and tells the web server which controller action to call when requests are made for the webpage.
-
Step 2 Create a Controller (if Needed). In Rails, a controller class must be responsible for handling requests for the webpage. If an appropriate controller class does not already exist, this step creates one.
-
Step 3 Create a Controller Action. This step defines how the controller will handle requests for the webpage, and in particular, specifies which HTML.ERB view template to render for the content of the webpage.
-
Step 4 Create a View Template. This step specifies what content will appear on the webpage.
Creating the Billy Books Home Page
To demonstrate the steps for adding a webpage, we will be making a home page for an online bookstore called Billy Books. Figure 1 shows what the webpage will look like.
We will start with the main base app, which does not have any webpages initially, and we will add this webpage to the app.
Step 1 Add a Route
In Rails, routes specify how the web server will handle different sorts of HTTP requests. Thus, we must create a route that tells the web server how to handle requests for the Billy Books home page.
Routes are declared in the file, config/routes.rb
, which contains only an empty block initially:
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
Substep Specify the HTTP request pattern to match for the route. To begin our route declaration, we add the part that tells the web server which HTTP requests will be for the home page by adding this code to the block:
Rails.application.routes.draw do
get 'home'
end
The get
part specifies that requests for the home page must have the HTTP GET verb. The 'home'
part specifies that requests for the home page must have home
a their resource path (e.g., as in the URL, http://localhost:3000/home).
Substep Specify the controller action to handle requests. Next, we add to our route which controller action should be called if an HTTP request matches the pattern:
Rails.application.routes.draw do
get 'home', to: 'pages#home'
end
The to:
argument above is a string that specifies the controller class and action method. The #
is a separator character, with the controller class name on the left and the class’s action method name on the right. The pages
bit is shorthand for the class name PagesController
(i.e., the snake_case
version of the class name, which is pages_controller
, with the _controller
part omitted). The home
bit specifies to a public method of PagesController
named home
. Note that the PagesController
class has not yet been created, and we will do so later in this demo.
Substep Set the prefix for the path/URL helpers. As a final addition to our route, we add a prefix for the Rails-generated path and URL helper methods:
Rails.application.routes.draw do
get 'home', to: 'pages#home', as: 'home'
end
If an (optional) as:
argument is specified for a route, Rails will generate two helper methods, a path helper and a URL helper. Later, we may need to use the relative path or full URL for this route in our code. For example, we may want to create a hyperlink to the home page. Hard coding such paths as strings makes code brittle—any change to the path would require finding and changing everyplace the path was used, a tedious and error-prone process. Thus, Rails provides path/URL helper methods for us to use instead of hard-coded strings. By specifying the prefix argument as: 'home'
, Rails will automatically generate a home_path
and a home_url
helper method for this route.
Test It!
To confirm that we made this change correctly, we run the following command in the terminal:
rails routes -E
The command should output a long list of routes, but the very first one is the only one we care about. If we coded our route correctly, it should look like this:
--[ Route 1 ]-----------------------------------------------
Prefix | home
Verb | GET
URI | /home(.:format)
Controller#Action | pages#home
--[ Route 2 ]-----------------------------------------------
…
If we made an error, something different will be outputted. For example, if we made a syntax error, it would instead produce an error message.
Step 2 Create a Controller
In Rails, a controller class is responsible for handling the requests matched by a particular route. In the previous step, we specified in our route that a PagesController
controller class would handle requests for the home page. Since PagesController
does not yet exist, in this step, we will create it.
In general, we use the rails
command to generate new controller classes. To generate our PagesController
controller class, we run the following command:
rails generate controller Pages
The rails generate controller
part of the above command specifies that the command will generate a controller class (along with some supporting files/directories). The Pages
argument specifies that the name of the controller class will be PagesController
. Note that the name given to this command (Pages
) is in UpperCamelCase
(following the convention for class names in Ruby) and the Controller
part of the name is omitted.
This command should output a list of everything it generated:
Running via Spring preloader in process 15430
create app/controllers/pages_controller.rb
invoke erb
create app/views/pages
invoke test_unit
create test/controllers/pages_controller_test.rb
invoke helper
create app/helpers/pages_helper.rb
invoke test_unit
invoke assets
invoke scss
create app/assets/stylesheets/pages.scss
Test It!
Although there’s no good way to test this step per se, we can verify that we generated the code correctly by carefully inspecting the output of the command. In particular, look closely at the first create
line:
create app/controllers/pages_controller.rb
The name of the controller file generated should exactly match pages_controller.rb
. If there is any difference in spelling, capitalization, or punctuation, then an error was made.
If we discover an error in the file name, we can undo the previous rails generate controller
command by running rails destroy controller
; however, we will need to specify the name of the controller exactly as we did before (i.e., using an incorrect name). One way to accomplish this is to click the up-arrow key to get back to our previous rails generate controller
command. Then, we edit the command to replace generate
with destroy
, and run the command.
For example, imagine that we accidentally ran this incorrect rails generate controller
command:
rails generate controller OopsWrongName
We can effectively undo the command by running this command:
rails destroy controller OopsWrongName
Step 3 Create a Controller Action
In Rails, a controller action method defines how requests matched by a particular route are processed. We previously specified in our route that a home
controller action would process requests for the home page, and in this step, we will create that action.
We will add the action method to the PagesController
class defined in the file app/controllers/pages_controller.rb
. Currently, the file looks like this:
class PagesController < ApplicationController
end
Substep
Add an empty action method. We add a home
action (empty for now) to the controller by defining this public method home
in the body of the PagesController
class:
class PagesController < ApplicationController
def home
end
end
Substep
Make the action render the view template. We make the home
action render a view template for the webpage by filling in the body of the home
method with the following render
command:
class PagesController < ApplicationController
def home
render :home
end
end
The render
method uses a view template to create a full response, including HTML code, to send back to the browser. The :home
part is a symbol that tells Rails to render the view template in app/views/pages/home.html.erb
. Rails automatically infers the pages
subdirectory, because the call to render
is being made inside the PagesController
class. Rails automatically infers the home.html.erb
view template from the :home
symbol name. Note that the app/views/pages/home.html.erb
view template does not exist yet, and we will create it in the next step.
Test It!
To test that this step was completed correctly, we run the web app (as per the steps in the running apps demo), and we open the URL http://localhost:3000/home in our web browser.
At the top of the webpage, the error message, “Template is missing” should appear. The next line should begin with “Missing template pages/home…”. These error messages tell us that our controller action is working, and the only problem is that the view template has not yet been created.
If different error messages appear, such as “SyntaxError” or “NoMethodError”, we may have made a mistake in our code. To debug our error, we must carefully inspect our code for any discrepancy with the above code. Note that error messages may also be caused by mistakes in how we run the app, so we may need to revisit those steps if there is no apparent error in our controller action code.
Step 4 Create a View Template
In Rails, view templates are used to define how a webpage will look, and they are commonly used to generate HTML. In the previous step, our home
controller action specified that the view template for the home page would be app/views/pages/home.html.erb
. Thus, we will now create view template.
We first create an empty HTML.ERB view template by making a new file called home.html.erb
in the app/views/pages/
directory. We can create this file using VS Code or using the touch
command (run from the top-level project folder), like this:
touch app/views/pages/home.html.erb
Then, we define what the web page will look like by filling in the file with the following HTML code:
<h1>Welcome to Billy Books!</h1>
<p>
Come visit us at 7107 Juniper Road Fairbend, TN, 37062!
</p>
<p>
Store Hours:
</p>
<ul>
<li>Monday: 10am - 7pm</li>
<li>Tuesday: 10am - 7pm</li>
<li>Wednesday: 10am - 7pm</li>
<li>Thursday: closed</li>
<li>Friday: 10am - 7pm</li>
<li>Saturday: 12pm - 6pm</li>
<li>Sunday: closed</li>
</ul>
If you aren’t familiar with these HTML tags, read the deets on common HTML tags.
Test It!
To test that this step was completed correctly, we run the web app (as per the steps in the running apps demo), and we open the URL http://localhost:3000/home in our web browser. The webpage displayed should look exactly like Figure 1.
If an error message is displayed, then we may have made an error in how we named the view template file or in which directory we saved the view template. We may also have made in an error in how we ran the app.
If the webpage opens, but parts of it do not look right, we likely made an error in our HTML code.
Conclusion and Further Reading
Following the above steps, we have now added a home page to an otherwise empty web app.
Here are some links to additional documentation on the topics covered in this demo:
- Routes in Rails and the path/URL helper methods are covered in this guide.
- Controllers in Rails are covered in this this guide.
- The
render
method and view templates are covered in this guide. - The
rails
command is covered in this guide.