Links

Tuesday, October 30, 2012

Basics of Rails Part 4

In this portion of the series, we will create the foundation for a login page and deal a little bit more with the Model portion of MVC.

We need to be able to assign the following information to a user.

First Name

Last Name

Email Address

Password

Admin (true/false)

This is where the Model comes in. Before we jump into that, let's create a Users controller similar to the way we create a Home controller in the last post.

Note that the "new" following Users simply states that a "new" action (method) will be automatically defined in the controller for you.

Also, we should briefly cover how you connect to a database with Rails. In this tutorial, we will stick with the default configuration/database, SQLite. Navigate to config/database.yml:

If you remember Part 2 of the series, we covered the 3 default modes of Rails. This is the reason there are 3 different database configurations in this file. It is useful as your local development environment database will differ from Production (ex: database username, password, and host would/should be different).

When we are running in development mode, the database we will be using will be db/development.sqlite3 as specified on line 8. The naming convention refers to it's location and filename.

So nothing really to change there, let's go ahead and create the model.

Command(s) Breakdown:

rails - Invoking a Rails command

g - Short for generate, used to generate Rails items

model - specifies that we are generating a model

Users - the name of the model which, actually refers to both the model (app/models/users.rb) and a table in the database

first_name:string (etc.) - The first portion is the name of the column in the table and the second part (string) identifies the variable type to be stored in the database.

Now, upon generation, the model is created but the db table/columns do not yet exist. To make this happen, let's run rake db:migrate.

To give you a visual of what was just created...

Note the table "users" has been created along with the columns we identified during model creation.

This is great and later if you'd like to add an additional column to your local db, you can. What if you'd like to add a column so that the next person to download your code and run rake db:migrate also has the new column? Navigate to db/migrate/ and you'll see a file that ends in _create_users.rb. This is where you would make that change. Do NOT edit the db/schema.rb file for that purpose (this is overwritten by the migrate files).

Next, create a sessions controller:

Time to add code to the session controller (app/controllers/sessions_controller.rb).

Notice the new and create actions. The gist of this, AFAIK, is that Rails uses new to instantiate a new instance of the Model object and create will actually save data and perform some of the more permanent actions. For our purposes, the "GET" request to the sessions#new and the new.html.erb file will show a login form. Once 'POST'-ing from that login form, the create method will receive the email and password parameters.

Code Breakdown:

Line 6 - Calls a method in the User model (authenticate).
Line 8 - Extract a user ID from the user's session
Line 9 - redirects to a home path once authenticated
Line 11 - A user did not authenticate correctly and we want to send them back to the login page.

The next thing we need to discuss are the changes to your routes.rb file:

Lines 3 - The first portion (ex: logout) identifies a request for that resources, goes to sessions#destroy.
Line 8 - Our root has changed to the login page (app/views/sessions/new.html.erb)
Line 10-12 - We've identified resources (controllers) and instantiated some default routes. 7 to be exact:

Note that 7 routes were not manually defined by you, in your routes file but rather, Rails created them for you. This is because you specified `resources :<controller name>` in your routes.rb file. You can create views and controller actions whose names match the names of those 7 defined routes (index, create, etc.). They automagically have routes!

Code breakdown:

Line 5 - form_tag is a Rails method, notice how we encapsulate it in <%= %>. This is how we separate Rails code from regular HTML. You may also see <% %>.
Line 7, 8, 11, 12 - Rails methods that are converted by Rails to define labels and input fields.
Line 14 - submit_tag, again, a Rails method. Note the {:class => "btn btn-primary"}. This is a Twitter-Boostrap definition you can find here.

Now fire up your instance, you should see the following:

Note: You can't necessarily use this yet but it looks nice :-)

This was a lot of information (read: lengthy post) and while the login does not yet work, we will wrap all of this up in Part 5 of the series. While part 5 of this series will walk you through the details of the code, you can always skip ahead and grab it from this Railscast (if you'd like to finish up).