# sequel -m dbMigration -M 1 sqlite://accounts.db
# from the top level directory to create the :accounts table with login and
# password columns.
class CreateAccountsTable < Sequel::Migration
# For the up we want to create the three tables.
# Create the accounts table with a primary key and a title.
String :login, :unique=>true
# For the down we want to remove the accounts tables.
To create simply run:
sequel -m dbMigration -M 1 sqlite://accounts.db
which should create a database accounts.db in the main directory with a table accounts with columns for a login and password. Here we're going to cheat just a bit (OK, quite a bit) to keep things simpler. Normally, in an application like this one, we'd have a registration page that would allow us to create new accounts (and we'll probably add that in a future post), but here we're just going to put a new account in using some code. Here's the dbload.rb file that puts in a single account with loginid "hello" and password "world":
# Run this file after the running the database migration
# to create a login/password. This is a quick hack since we
# don't have a page to add them with.
DB = Sequel.sqlite("accounts.db") # Open the accounts database
Account.create(:login => 'hello', :password => 'world')
Now let's look at start.rb which starts things off. In this version of our code, I've moved the controller into its own directory in the same way that the models and views have their own directories. Here's the code:
# This is the main program for the example. It loads the Sequel database,
# loads the controller and model, and then starts up Ramaze.
# The database should have been set up using the database migrations in
# the dbMigration directory. Since there's currently no way to add login/password
# pairs, we're going to cheat and run the dbload.rb file which will create a
# login "hello" with a password "world". Normally, this would be handled with a
# registration page.
# Open the accounts database. This must be done before we access the models
# that use it.
DB = Sequel.sqlite("accounts.db")
# Load the controllers and models (one of each in this case).
This is all pretty straight forward. The only mildly tricky part is that we need to open the database before we bring in the model. The database we open is the one we created with the database migration and loaded with the dbload. Finally, as is normal, we start Ramaze.
Our model is very simple. It only contains the Account which is derived from the Sequel::Model. Here's the code:
# This is the model for the Account and is backed by the :accounts table in the
# database. For this simple example we don't need anything but the definition.
# Create the Account model.
class Account < Sequel::Model
The controller class in this example is where all of the real work is done. We still have our two methods
logged_infrom before. The
indexlogs a user into the system and the
logged_inhappens after the user is authorized. Before either of these though is some new code that is used to protect our pages from users that are not logged in. In our earlier examples, you could actually go to the logged_in page without having been authorized. What the new code, helper aspect / before, does is prevent that. We check the session variable for a loginID not equal to nil and redirect to the index (login) page if it is nil. If it's not, we'll just continue on with normal processing. This code happens before the logged_in page is called. If we add additional pages, they can be protected by simply adding them in the before() list. There is also an equivalent after call that can be used in a similar way as well as before_all and after_all that can be used without a list of methods. Here's the controller:
# This example is based on the previous "Using Models" example. It has two
# methods (index and logged_in). The index method will take data from a form
# and call the Account.find method. If the Account.find method returns
# something (we aren't actually going to use what's returned), we will set the
# session variable, and redirect to the logged_in method. If it returns false
# we will set the flash variable and stay on the index page.
class MainController < Ramaze::Controller
# Use page.xhtml in the view directory for layout
# Set up a helper to check if we're logged in and only allow access
# to the :logged_in page if we are. This is probably the hard way to
# do this for only the single page but will make much more sense if
# we add more pages as we'd do in a real application.
# Set the flash message which will only be available in the next
# screen. In this case that will be the logged_in screen.
flash[:message] = "You must log in before accessing the requested page."
# You can access it now with http://localhost:7000/
# This should display a form with a login and a password as
# well as a "Login" button in your browser.
# Make sure we're getting here from a post request.
# Check the login and password.
# if we find the Account based on the login and password. If we find it
# we'll save the login ID in the session variable and we can use that
# to show if the Account is currently logged in or not. If we can't
# find the Account, we'll set the flash message, set the session to nil
# and just stay on this page.
if Account.find(:login => request[:loginID], :password => request[:pw2])
# Use the name= portion of the input form to grab the data
# from the request variable and save it in the session
# hash table.
session[:loginID] = request[:loginID]
# Redirect to the logged_in screen.
# The login could not be authorized. Set the flash message
# and stay on this page (index/login). Set the session loginID
# to nil also. This will effectively log the user out. This would
# be reasonable if they are logged in and then try to log in with
# a new login/password.
flash[:message] = "Incorrect password, please try again!!!"
session[:loginID] = nil
# Stay on the login page.
# Set the login ID variable so we can issue a
# welcome message on the logged_in page.
@loginID = session[:loginID]
The only other interesting thing in the controller is the use of the model Account to determine if an account exists for a given login/password. We use the find method and pass in the values from the form, as we've done in previous posts, to check if this is a valid account. If it is, we set the session variable with the loginID and redirect to the logged_in page. This will trigger the before check that we discussed earlier. If we could not find this user (and in this case there will only be one), we set the flash variable and redirect back to the index page to let the user try again. We also set the session/loginID value to nil here to clear it out.
Here's the view pages starting with view/page.xhtml:
<head> <title>Using Sequel and Ramaze Together</title> </head>
<h5> Powered by Ramaze </h5>
Here's the view/index.xhtml which contains our login form:
<form id="login" method="post">
<!-- for= goes with id=, the name= is placed in the request variable. -->
<input id="nick" name="loginID" type="text" />
<input id="pw1" name="pw2" type="password" />
<input type="submit" value="Login" />
Finally, view/logged_in.xhtml which shows a welcome message based on the loginID set in the logged_in method of the main controller:
Welcome to Our Site: #@loginID
As always, please post your questions and comments.