Friday, January 1, 2010

Ruby and Simple Dynamic Programming III

In my last couple of posts, here and here, I began talking about dynamic programming using Ruby. In this post, I'm going to continue on the same lines and this time we're going to discuss using the eval series of methods, specifically class_eval. Before getting started however, here's a word of warning. Gregory Brown in Ruby Best Practices describes eval (and related methods) as "evil". The truth is that you need to be pretty careful about using these methods as they offer ample opportunity for a user to do some pretty bad things to your system. With that said ...

As you know, Ruby offers three convenience methods for read, write, and read/write access to variables and these are attr_reader, attr_writer, and attr_accessor respectively. Let's take a look at how we could implement these if they hadn't already been thoughtfully provided.

Here's the code:

# Open the class Class and add three new access methods, access_r, access_w, access_rw.
# These are really just reimplementations for attr_reader, attr_writer, attr_accessor.
class Class
# Provide read access only. Take a list of symbols and create a
# method that will all the user to access each symbol.
def access_r(*symbols)
symbols.each { | symbol |
class_eval "def #{symbol}() @#{symbol}; end"
}
end

# Provide write access only. Take a list of symbols and create a
# method that will all the user to write each symbol.
def access_w(*symbols)
symbols.each { | symbol |
class_eval "def #{symbol}=(val) @#{symbol} = val; end"
}
end

# Provide read/write access. Take a list of symbols and create two
# methods that will all the user to read and write each symbol.
def access_rw(*symbols)
symbols.each { | symbol |
class_eval "def #{symbol}() @#{symbol}; end"
class_eval "def #{symbol}=(val) @#{symbol} = val; end"
}
end

end

if __FILE__ == $PROGRAM_NAME

# Using the new attribute accessor methods.
class Foo
access_r :bar
access_w :qux
access_rw :baz, :quux

# Since bar is read only from the outside, we'll just initialize
# it here.
def initialize(bar)
@bar = bar
end

# Since qux is write only, we'll create a method that lets us view
# it.
def show_qux
puts "qux = #{@qux}"
end

end


# Create a new foo and initialize bar (read only) with goodbye.
# Show that we can then access it.
foo = Foo.new ("goodbye")
puts "foo.bar = #{foo.bar}"


# Set and then access the two variables we set to
# read/write.
foo.baz = "hello"
puts "foo.baz = #{foo.baz}"

foo.quux = "world"
puts "foo.quux = #{foo.quux}"

# Set the write only field and then display it using the show_qux
# method.
foo.qux = "test"
foo.show_qux

# Try to access the write only field for reading. This should
# fail with an undefined method.
puts foo.qux

end



We start out opening Class as this is where we're going to add our new methods, access_r, access_w, and access_rw. We're going to take a list of symbols, represented here with "*symbols" and covert each of the symbols into a new method. For access_r, we'll loop through the symbols and then generate a method with the name "symbol" that returns symbol. For example if we have a symbol :x, we'll get a method that looks like def x() @x; end. The access_rw will give us, for the same symbol :x, def x=(val) @x=val; end. Finally, the access_rw will give us both methods (there's probably a clean way to refactor this so we don't have duplicated code, but this is left as an exercise for the reader).

Finally, we create a class Foo, that uses all three access methods and then some code that exercises each one. The final call is a read access to a write only field and should fail with an undefined method.

As always, let me know if you have any questions or comments.

Saturday, December 26, 2009

Ruby and Simple Dynamic Programming II

In my last post, we went over using method_missing in Ruby to do some simple dynamic programming. In this post we'll take a look at using the Singleton Class (not the Singleton pattern) to do a bit more dynamic programming. Most of this is a rehash of a couple of great posts by Ola Bini here and Peter Jones here.

So, what is the Singleton Class? A Singleton Class is where methods for an individual object are stored. What's this mean? Let's just look at some code.

# Create a class, Foo, that has a single method bar. We'll also
# add a method_missing so that we can see what's called that
class Foo
def bar
puts "Called bar"
end

# Put this in so we can see what gets called in foo2 below that's not available.
def method_missing(name, *args, &block)
puts "You tried to call #{name} with #{args.inspect}. There is no method with that name."
end
end


# Create a new Foo
foo = Foo.new

# Call the method that does exist.
foo.bar

# Add a new method to foo. This method, baz, will be added to
# foo's singleton class.
def foo.baz
puts "Called baz"
end

# Call the method we just added.
foo.baz

# Another way to add a new method to foo. This method, baz, will be added to
# foo's singleton class.
class << foo
def qux
puts "Called qux"
end
end

# Call the method we just added.
foo.qux

# Show that we don't have either baz or qux for any other Foo objects.
foo2 = Foo.new
foo2.bar # Should be there
foo2.baz # Should not be there
foo2.qux # Should not be there

# Add two class methods to Foo.
class Foo
class << self
def quux
puts "Called quux"
end
end

def self.quuux
puts "Called quuux"
end
end

foo3 = Foo.new
foo3.quux
foo3.quuux

Foo.quux
Foo.quuux



First we define a class Foo (here we're going to use metasyntactic variables, a phrase I just learned here). Anyway, class Foo has two methods, bar and method_missing (see last post). bar just prints out the fact that it was called and method_missing shows any methods called that aren't available. Nothing too awfully interesting here, we've seen things like this a million times. Next, we'll just create a new Foo called foo and then call the bar method on it. After that, we're going to do something a bit new, we're going to add a new method, baz, to foo (note that we're adding it to the object foo and not the class Foo. We'll call foo.baz to show that it works. Following, we're going to add a method qux using a different syntax, but it will do exactly the same thing as the last addition. Then we're going to call qux on foo to show that it works. Where were these methods added? Well, you can see from the next few statements, that they weren't added to all Foos. The fact is they were added to foo's Singleton Class. The Singleton Class sits between the object foo and its class Foo (see Jones' post to see this represented graphically).

Since a class has a class Class (OK, that may have made very little sense), it makes sense that the class Foo itself might have a Singleton Class and if you guessed that, then you guessed correctly. In the next section, we add a couple of methods using two different techniques to Foo (notice that we just reopen it), as class methods. In the same way as happened above, these methods are added to the Foo Singleton Class. We create a new foo3 variable and show that we can't call these new methods using an instance of foo, then we call them using Foo.

OK, so all of this is very interesting and ... so what? What can we do with this. Well, one use for the Singleton Class is for mocking (once again shown in Jones' post).

# Create a class, User, that has a single method get_buy_power. In
# real life a user would have many, many more methods than this.
class User
def get_buy_power
# Normally, this would be a complex call to
# the database, but here we'll just return
# a random number * 10000.0. This should give
# us a number between 0 and 10000.
rand * 10000.0
end
end

# A "normal" user.
user_normal = User.new
puts "user_normal buy power = #{user_normal.get_buy_power}"


# Create a new User
user_small_bp = User.new

# Change the user_small_bp's get_buy_power method to return a small value. This will be
# added to the user_small_bp's singleton class.
class << user_small_bp
def get_buy_power
20.0
end
end

# Print out the buy power for the user_small_bp
puts "user_small_bp buy power = #{user_small_bp.get_buy_power}"


# Create a new User
user_large_bp = User.new

# Change the user's get_buy_power method to return a large value. This will be
# added to the user's singleton class.
class << user_large_bp
def get_buy_power
200000.0
end
end

# Print out the buy power for the user_large_bp
puts "user_large_bp buy power = #{user_large_bp.get_buy_power}"


# We can now use user_small_bp and user_large_bp to run tests on buying stocks
# without enough buy power or with quite a bit of buy power.


# Create a simple OrderManager that will place orders and send orders. The place_order
# method will check a user's buy power before sending an order through. If the buy power isn't
# large enough, it will simply print a message, otherwise it will send the order and it
# will also print a message.
class OrderManager
def place_order(user, shares, stock, price)
if user.get_buy_power > price*shares
send_order(stock, price, shares)
else
puts "Not engough buy power for #{shares} of #{stock} at #{price}"
end
end

private

def send_order(stock, price, shares)
puts "Order sent for #{shares} of #{stock} at #{price}"
end
end

# Create a simple order manager.
order_manager = OrderManager.new

# Place an order for 200 shares of apple at $210.0 with user_small_bp. This should fail.
order_manager.place_order(user_small_bp, 200, "AAPL", 210.0)

# Place an order for 200 shares of apple at $210.0 with user_large_bp. This should succeed.
order_manager.place_order(user_large_bp, 200, "AAPL", 210.0)



Take a look at the code above. In the world that I live in (stock trading software), users have a certain amount of buy power that they can use to purchase stocks. Normally, this value would come out of the database and would be incremented (selling a stock) and decremented I(buying a stock) with each trade (OK, this sentence is incredibly simplistic, but will do for now). We're going to use Singleton Class to change our get_buy_power method (rather than adding as we did earlier). In one case, we'll give the user very little buy power and in the other, quite a bit more. After that, we'll create simple order manager that will allow us to place an order for a user that will check their buy power before sending it.

So there you have it, the Singleton Class and its usage. As always, let me know if you have any questions or comments.

Wednesday, December 16, 2009

Ruby and Simple Dynamic Programming

I've been reading"Ruby Best Practices" by Gregory T. Brown and it's well worth checking out for anyone interested in Ruby. I'm in the middle of Chapter 3, "Mastering the Dynamic Toolkit" and thought I'd share a some simple bits of code that actually use dynamic programming.

We actually make use of the fact that with Ruby you can add a method_missing method to any class that allows you to capture calls to any method that are ... well missing. Here's a simple example that shows how it works.

# Create a class with the method_missing method. If a method 
# is called on this class and it's not found, then this method
# will be called. We'll then print whatever was passed in along
# with the fact that it's not there.
class MM
def x
puts "Called x"
end

def y
puts "Called y"
end

def method_missing(name, *args, &block)
puts "You tried to call #{name} with #{args.inspect}. There is no method with that name."
end
end

if __FILE__ == $PROGRAM_NAME

# Create a new MM
mm = MM.new

# Call the two mehtods that do exist.
mm.x
mm.y

# Call z (which doesn't exist) both with and without
# paramaters.
mm.z
mm.z 1, 2, 3
end



This code creates a simple class called MM with three methods, x, y, and method_missing. The first two only print out the fact that they were called and the third will print out any other method that gets called, say z 1,2, 3 and will print out the name and parameters that get passed in to it. The main code just creates a new MM and calls a few methods (existing and not) on it.

Admittedly, this isn't too awfully interesting, but in our next example, we'll actually use method_missing to save ourselves some work. Here's the second bit of code:

# Create a class MM1. The x and y methods require calling
# setup before and teardown after. This means that everytime
# we have to add a new method (say z()), we end up having to
# duplicate this code.
class MM1

def setup
puts "Setup"
end

def teardown
puts "Tear down"
end

def x
setup
puts "Called x"
teardown
end

def y
setup
puts "Called y"
teardown
end
end

# Create a class with the method_missing method. Here we
# still require x and y to have setup and teardown called, but
# we wrap it in method_missing as setup_x_teardown or setup_y_teardown.
# This allows us to also add z without having to worry about remembering
# the setup/teardown.
class MM2

def setup
puts "Setup"
end

def teardown
puts "Tear down"
end

# The method_missing() does all of the work here. We check if the
# name is setup_something_teardown and if it is, we call setup,
# call something with the parameters passed in, and then call teardown.
# If the method isn't of this form, we just pass it along.
def method_missing(name, *args, &block)
case (name)
when /^setup_(.*)_teardown/
setup
send($1, *args, & block)
teardown
else
super
end
end

def x
puts "Called x"
end

def y
puts "Called y"
end
end

if __FILE__ == $PROGRAM_NAME

# Create a new MM1
mm1 = MM1.new

# Call the two mehtods that do exist.
mm1.x
mm1.y

# Create a new MM2
mm2 = MM2.new
mm2.setup_x_teardown
mm2.setup_y_teardown
end



There's two classes here that both "do" the same thing. The first class MM1 has two methods, x and y that require a setup before they are called and a teardown after they are called.

The second class, MM2, has the same requirements, but we're going to handle them a bit differently. We have the same setup and teardown, but we don't have x and y call them directly. Instead we use method_missing to handle the setup and teardown. What we're going to do is use method_missing and then check the name parameter. If it matches something that looks like setup_X_teardown, then we'll call setup, call the method using send, and finally, call teardown. If we don't match the pattern, then we just pass the call up the chain. The main code here creates both an MM1 and an MM2 and shows a bit of how to use them.

Here, in this simple example, you probably wouldn't bother with this. In the book Brown gives a much better use case, but this should give you some ideas at least.

Let me know if you have questions or comments.

Saturday, November 28, 2009

Ramaze - Forgot Password II

Edit 2009-11-30

This in from Jeremy Evans
------------------------------
Looks better, but I recommend a few more changes:

1) You need to salt your password hashes. Unsalted hashes are better
than storing the password in plaintext, but most common hash
algorithms probably already have large rainbow tables that will allow
an easy lookup of most passwords given an unsalted hash.

2) I would recommend at least including random data when generating
the random key for password resets. Your use of the username and
Time.now makes it guessable if you know roughly when the user
requested/will request a password change. encrypt_password is a
poorly named method, since you are hashing, not encrypting (encrypting
implies the possibility of decrypting, while hashing is one way).

3) I generally put a time limit on password resets. That way if
someone requests one, but then remembers their password and doesn't
change it, they are not vulnerable to someone else changing it next
year.
------------------------------------------------

So, add the salt for the password, modify the generate_rand_key() to add a random component (possibly just add a #{rand(1000000)} to the end of the string to add in a 6 digit random component, rename encrypt_password to say hash_password, and finally add a time limit. Here, you'll need to add a date to the user table, add a date when you generate_rand_key(), and check this in change_password() when you also test the existence of a user with the key.

Thanks for the improvements Jeremy.

------------------------------------------------

After my last post, I received, as I noted, some rather stern comments on a) saving passwords in plaintext in the database and b) sending them in plaintext via email. So, I decided to fix the example up to make it a bit better. We'll be saving the password as a hash in the database and also when the user forgets their password, we'll send a link to let them change it. One other suggestion was to add a salt for the password hash which is easy enough to do, but I've left it as an exercise for the reader. I should note that some of the ideas in this post were stolen (and I mean that in the good sense) from JustKez. This post is definitely worth reading over as are others on the site.

OK, let's get started. We'll start out with the database migration.


# dbMigration/001_ForgotPassword.rb
#
# This is the "new" way to do migrations by using the Class.new form.
# It means that a new class name is not required and so there is no chance
# of creating a second class in the migration files that is the same as the
# first causing problems.
Class.new(Sequel::Migration) do
def up
# Create the users table.
create_table(:users) do
primary_key :id
String :user_name
String :password
String :email
String :rand_key
end

end

def down
# Remove the two tables.
drop_table(:users)
end
end



This is a bit simpler than in the previous example. We're only going to have a users table with the user_name, password (which will be encrypted), an email address, and a random key (used for sending the user their password). The down method will just drop the users table. To generate the password, simply type sequel -M dbMigration/ sqlite://forgot.db. This will create the database we'll use for the project.

The model for this is pretty simple too.

# models/models.rb
#
# Create the User model. Each user can have a single challenge question.
require 'digest/sha1'
class User < Sequel::Model

# Return an encrypted password based on the one passed in.
def self.encrypt_password(password)
Digest::SHA1.hexdigest(password)
end

# Generate a random key based on the username and the current time in
# rand_key and save the model back to the database. We'll use this to email
# the user so that they can changer their password.
def generate_rand_key
self.rand_key = Digest::SHA1.hexdigest("#{@username} -- #{Time.now}")
save
end
end



The only model we have is for the User. We have a couple of methods. The first is a Class level method for encrypting the password. We create a hash of the password using SHA1 and return the value (it will be used for creation of the user and changing the password). The second method is for generating a random key which will be passed as part of a link to the user in case they forget or lose their password.

Here's our start code

# start.rb
#
# This is the main program for the example. It loads the Sequel database,
# loads the controllers and models, and then starts up Ramaze.
#
# The database should have been set up using the database migrations in
# the dbMigration directory.
require 'rubygems'
require 'ramaze'
require 'sequel'

# Required for mailing.
require 'net/smtp'
require 'mailit'

# Create the mailer.
MAILER = Mailit::Mailer.new(:server => 'MailServer.MyCompany.COM', :port => 25, :username => 'ApplicationName',
:password => 'ApplicationPassword')


# Open the forgot password database. This must be done before we access the
# models that use it.
DB = Sequel.sqlite("forgot.db")

# Load the controllers and models.
require 'models/models'
require 'controllers/main_controller'

# Start Ramaze.
Ramaze.start



This is pretty much the same as most of our start files. We add in the code for mailit, open the database, and then require our models and controllers. Finally, we start ramaze.

Next up our only controller.

# controllers/main_controller.rb
#
# The mainController has a single method index. First map to / for
# the view. Next, set the layout to page so that we use the layout/page.xhtml for our
# layout.
class MainController < Ramaze::Controller

# The Main controller will be accessed using "main" as in:
# http://localhost:7000/main.
map '/'

# Use page.xhtml in the layout directory for layout except
# for when we're doing AJAX.
layout(:page) { !request.xhr? }

# 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.
helper :aspect
before(:account_settings, :main) {
unless logged_in?
# 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."
redirect rs(:index)
end
}

# You can access it now with http://localhost:7000/
def index
@title = "SteamCode - User"
end

# Placeholder for real content.
def main
"<h2>Main</h2>"
end

# Placeholder for real content.
def about
"<h2>About</h2>"
end

# Placeholder for real content.
def help
"<h2>User Help</h2>"
end

# Register a new user with SteamCode. We will get here from the
# views/register.xhtml page where the user will put in their (requested)
# login, password, and email address. First find if the user already
# exists, if it does, then we'll set a message to tell the user so and
# redirect them back to the register screen. If not, we'll go ahead and add
# them to the database with the appropriate login, password, and email
# address. We'll then send them to the login screen to let them log in to
# SteamCode.
def register
@title = "Register with SteamCode"
# Make sure we're getting here from a post request.
if request.post?
# 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.
unless User.find(:user_name => request[:user_name])
# This account does not exist. Grab the user_name, the password,
# and the email and create a new Account with them.
user_name = request[:user_name]
password = request[:password]
email = request[:email]

# Create the account with the user_name, password, and email given.
user = User.create(:user_name => user_name, :password => User.encrypt_password(password), :email => email)
Ramaze::Log.debug "New User Added: user_name = #{user.user_name} password = #{user.password} email = #{user.email}"

# Redirect to the login page.
redirect rs(:login)

else
# This user already exists. Set the flash message for them to
# try again.
flash[:message] = "Login #{request[:user_name]} already used. Please select another."

# Stay on the register page.
redirect rs(:register)
end
end
end

# Login to Steamcode. If the request is a post, then we'll try to find the
# user. If we succeed then we'll set some session variables and redirect to
# the main page (which the user can only access if they're logged in). If they
# can't be logged in, we'll set a flash message, reset the session, and redirect
# back to the login page.
def login
@title = "Login to SteamCode"
if request.post?
if user = User.find(:user_name => request[:user_name], :password => User.encrypt_password(request[:password]))
# 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[:user_id] = user.id
session[:user_name] = user.user_name

# Redirect to the main screen.
redirect rs(:main)
else
# 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 user name or password, please try again!!!"
session[:user_id] = nil
session[:user_name] = nil

# Stay on the login page.
redirect rs(:login)
end
end
end

# Let the user change account settings. For now this is
# just the email and password.
def account_settings
@title = "Account Settings for SteamCode"
user = User[session[:user_id]]
if request.post?
user = User[session[:user_id]]
user.email = request[:email]
user.password = User.encrypt_password(request[:password])
user.save
flash[:message] = "New email and/or password saved."
redirect rs(:main)
end
@current_email = user.email
end

# Logout of the system. Set the flash message and then
# set the session values to nil. Finally, redirect back to the
# index page.
def logout
@title = "Logout from SteamCode"
flash[:message] = "#{session[:user_name]} Logged out"
session[:user_id] = nil
session[:user_name] = nil
redirect rs(:index)
end

# The user has requested that we email their password back to them. Generate
# a random key and email it to them to allow them to change their password.
def forgot_password
if request.post?
# Final submit.
if user = User.find(:user_name => request[:user_name])

# Generate a key and associate it with the user_name.
user.generate_rand_key

# Create the mail message and fill it in with the appropriate
# information (to/from/subject/text). Then send it off.
mail = Mailit::Mail.new
mail.to = user.email
mail.from = "Steamcode@MyCompany.com"
mail.subject = "Steamcode Password"
mail.text = "To change your password: http://localhost:7000/change_password/#{user.rand_key}"

# Send the mail message via the MAILER (created in start.rb).
MAILER.send(mail)

# Just go back to the login page.
redirect rs(:login)
else
flash[:message] = "Could not find user: #{request[:user_name]}"

# Could not find user with this user_name.
redirect rs(:forgot_password)
end
end
end

# The key will be the key that we created above when the user asked
# for the password change. It will be passed as a parameter when the user
# clicks on the link that was emailed to them.
def change_password(key)
# Check to make sure that there's a user with this key.
user = User.find(:rand_key => key)
if user
if request.post?
# We got here from a post and there's a user with the key. Go ahead
# and a) change the password, b) reset the random key, and c) save
# the new user information. Then set the flash message and put them
# on the login screen.
user.password = User.encrypt_password(request[:password])
user.rand_key = nil
user.save
flash[:message] = "Your new password saved."
redirect rs(:login)
end
else
# There wasn't a user with this random key. Just flash a message
# and then redirect to the login screen.
flash[:message] = "This does not appear to be a valid request."
redirect rs(:login)
end
end

private

# If the user is logged in, the session will
# contain a non nil user id.
def logged_in?
session[:user_id] != nil
end
end



This is very similar to many of our other controllers from our past posts. We map to '/', Add the layout (which won't be used for AJAX calls (not used here anyway)), and then the aspect which will prevent the user from going to certain pages unless they're logged in to the system. The next four methods, index, main, about, and help are really just place holders. Index is where the user will end up initially and main is where they will end up after logging in. Then we have the register page. This will check if it's a post and if it is, try to find the user. If it can't find the user (note the use of "unless" here. To a certain extend, I'm trying to decide if it helps or hinder readability. Let me know what you think) it will create a new one with the parameters from the request hash. If the user already exists, we'll just flash a message back and redirect them back to the register page. Next we have the login method. We check to make sure this is from a post, then check to see if we can find the user based on their user name and password (using the model's encrypt_password method). If we find them, we go ahead and log them in (set the session variables) and redirect them to the main page. If not, we flash a message, reset the session variables, and redirect them back to the login page. The account_settings page let's the user reset their email and password. The logout page resets the session variables and then redirects back to the index page. Looking at it now, I'd recommend refactoring the session resets here and in login to their own private method (once again we'll leave that as an exercise). The forgot_password method is the reason for all of this. We check that it's a post and contains a valid user. If so, we generate a random key for the user (using the model method) and then create an email with the link containing this key. If we can't find the user, we'll flash a message and redirect back to the same page. Finally (for the pages anyway), we have the change_password page. This checks to see if we have user with this rand_key (from the link generated above) and if we do, we check if this is a post and change their password appropriately, reset the random key (so it's used only once), flash a message and redirect them back to the login page. If there wasn't a user with that random key, we simply flash a message and redirect them back to the login page. Finally, we have the private method that's used to check if a user is logged in to the system.

Here's our layout page.xhtml

<!-- view/page.xhtml -->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- Use the page.css in the public directory and set title based on
what's set in the associated method.
-->

<link rel="stylesheet" type="text/css" href="/page.css"/>

<title>#@title</title>
</head>
<body>
<div id="whole_page">
<div id="header">
<h1>SteamCode</h1>
</div>

<div id="nav">
<!-- Main/User controller -->
<!-- Move this next section over to the right side of the screen. It
will contain the Login/Register if we're not logged in and the Logout
if we are. -->

<span style="float: right">
<!-- We're going to use the private method logged_in? here to test if
we want to show the Login/Register links or the Logout link -->

<?r if !logged_in? ?>
<a href="#{r(:login)}">Login</a>
<a href="#{r(:register)}">Register</a>
<?r else ?>
<a href="#{r(:account_settings)}">Account</a>
<a href="#{r(:logout)}">Logout</a>
<?r end ?>
</span>

<!-- These next three will be on the left side and always there -->
<a href="#{r(:index)}">Home</a> |
<a href="#{r(:about)}">About Us</a> |
<a href="#{r(:help)}">Help</a>
</div>

<div id="content">
<!-- Display the actual content. This will come from the method or the
associated view/*.xhtml file
-->

#@content
</div>

<!-- Set the footer in the center of the screen. -->
<div id="footer" style="text-align: center;">
<h5> Powered by Ramaze </h5>
</div>
</div>
</body>
</html>



It's stripped down a bit from the last post and has all of the administration stuff removed. Since you've seen this in past posts, I won't go through it. It's mostly just code for the navigation with some content and a header and footer tossed in for good measure.

Let's take a look at the views for the project. They're really simple this time. No JavaScript and no AJAX. Here's the index.

#{flashbox}
<h2>Welcome</h2>



Here's the login page

#{flashbox}
<a href="#{r(:forgot_password)}">Forgot your password?</a>
<br/>

<form id="login" method="post">
<fieldset>
<legend> Login </legend>
<div>
<!-- for= goes with id=, the name= is placed in the request variable. -->

<!-- Input for the user_name. -->
<label for="user_name">User Name:</label>
<input id="user_name" name="user_name" type="text" />
<br/>

<!-- Input for the user_name. -->
<label for="password">Password:</label>
<input id="password" name="password" type="password" />
<br/>

<!-- Submit the login request. -->
<input type="submit" value="Login" />
</div>
</fieldset>
</form>



There's just input boxes for the user name and password and a button for submitting.

Here's the registration page.

<!-- view/register.xhtml -->
<form id="register" method="post">
<div>
<!-- for= goes with id=, the name= is placed in the request variable. -->

<!-- Input for the user_name. -->
<label for="user_name">Login:</label>
<input id="user_name" name="user_name" type="text" />
<br/>

<!-- Input for the password. -->
<label for="password">Password:</label>
<input id="password" name="password" type="password" />
<br/>

<!-- Input for the email. -->
<label for="email">Email:</label>
<input id="email" name="email" type="text" />
<br/>

<!-- Submit the new User -->
<input type="submit" value="Register" />
</div>
</form>



As above boxes for user name, password, and email plus the submit button.

Here's the page for changing the account settings.

<!-- Let's the user change their email and/or password -->
<form id="change_password" method="post">
<fieldset>
<legend> Change Settings </legend>
<div>
<!-- Input for the email address. -->
<label for="email">Email:</label>
<input id="email" name="email" type="text" value=#{@current_email} />
<br/>

<!-- Input for the password. -->
<label for="password">Password:</label>
<input id="password" name="password" type="password"/>
<br/>

<!-- Submit the new email and/or password -->
<input type="submit" value="Submit" />
</div>
</fieldset>
</form>



This contains boxes for password and email (the user can't change their user_name) and the submit button.

Next is the forgot_password.xhtml.

<h2>Forgot Password</h2>
#{flashbox}

<form id="forgot_screen" method="post">
<fieldset>
<legend> Forgot Password </legend>
<div id='forgot_password'>

<!-- for= goes with id=, the name= is placed in the request variable. -->
<!-- Input for the user_name. -->
<label for="user_name">User Name:</label>
<input id="user_name" name="user_name" type="text" value="User Name" />
<br/>

</div>

<!-- Once they've put in the challenge answer, they will select -->
<!-- this and the system will send their password via email. -->
<input type="submit" value="Send Password" />
</fieldset>
</form>
<br/>



This has a box for the user_name and the submit button. When the user puts in their user_name and submits, an email is generated (see above) that provides a link to change their password. This page is the change_password.xhtml.

<!-- view/register.xhtml -->
<form id="change_password" method="post">
<div>
<!-- for= goes with id=, the name= is placed in the request variable. -->

<!-- Input for the password. -->
<label for="password">Password:</label>
<input id="password" name="password" type="password" />
<br/>

<!-- Submit the new User -->
<input type="submit" value="Change Password." />
</div>
</form>



Once again, dead simple with the password box and a submit (you'd probably want a confirmation password that would be checked using JavaScript, but we'll just assume that the user won't make any mistakes.

That's pretty much everything except for the CSS which is in public/page.css


#whole_page {
width: 50em;
margin: auto;
padding: 0;
text-align: left;
border-width: 0 1px 1px 1px;
border-color: black;
border-style: solid;
}

#content {
height: 100%;
background: white;
padding: 1em 1em 1em 1em;
}


/* Header CSS */
#header {
background:#9DA9EE;
color: white;
margin-bottom: 0;
padding: 0.25em;
}

#nav {
background:#9DA9EE;
color: black;
padding: 0.5em;
}


/* Footer CSS */
#footer {
background:#9DA9EE;
color: black;
}


So, I hope this works out for everyone a bit better than the last version and gets at least a bit closer to what you might use in a "real" project. Let me know if you have questions or comments.