Sunday, February 15, 2009

Using a Simple Model

Models are the "M" in the MVC pattern along with "View" and "Controller". We've used both views and controllers so far, but we haven't seen any models yet. For this post, we'll take our last post, Accessing Data From Forms and add a very simple model for "authorizing" the login ID and password. Here's our main ruby code usingmodels.rb:

require 'rubygems'
require 'ramaze'

require 'models/authorize'

# This example is based on the previous "Accessing Data From Forms" example.
# It has two methods (index and logged_in). The index method will take data
# from a form and call the authorize method. If the authorize method returns
# true we will set the session and flash variables, and then finally redirect
# to the logged_in screen where it will display the flash message and the
# login/password values. 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
layout :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.
# For anything that is entered, we will save the values
# in the session, set the session variable, set the flash
# variable, and redirect to the logged_in screen.
def index

# Make sure we're getting here from a post request.
# 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]
session[:pw] = request[:pw2]

# Check the login and password.
if Authorize.authorize(session[:loginID], session[:pw])
# 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] = "Successfully logged in!!!"

# Redirect to the logged_in screen.
redirect Rs(:logged_in)
# The login could not be authorized. Set the flash message
# and stay on this page (index/login).
flash[:message] = "Incorrect password, please try again!!!"

# Show the message in the flash variable and print out the
# login ID and password. Typically, you wouldn't want to do
# this in a real environment.
def logged_in
"#{flash[:message]} #{session[:loginID]} : #{session[:pw]}"


As you can see it is pretty much the same as the previous example except we make a call to the Authorize.authorize() method which is brought in with the require 'models/authorize' in line 4. It this returns true, we move on (are redirected) to our logged_in action/view as before and display the success message and the login/password pair (still not a good idea). If the Authorize.authorize() returns false, we set a flash message that says it was an incorrect password and we don't redirect anywhere but stay on the same page (no redirect).

Here's the Authorize.authorize()

# This class is a very simple authorize class that
# contains a single class method that checks a
# login/password pair and if they are hello/world
# returns authorized as true and otherwise false.
class Authorize
def self.authorize(login, password)
if ((login == 'hello') && (password == 'world'))
authorized = true
authorized = false

If you haven't done much ruby programming, you may be wondering about a couple of things. First, there's the def self.authorize(login, password). This is the way you declare a class as opposed to an instance method in Ruby. In this case, we want to be independent of any particular instance of Authorize, so we use this form. The other interesting thing here is that there's no return statement. Ruby (like Perl) returns the last thing that's "mentioned" which in this case is the authorized variable. This code should be placed in a models directory underneath your main directory.

Here's our new view/index.xhtml:

<form id="login" method="post">
<!-- for= goes with id=, the name= is placed in the request variable. -->
<label for="nick">Login:</label>
<input id="nick" name="loginID" type="text"
<label for="pw1">Password:</label>
<input id="pw1" name="pw2" type="password"
<input type="submit" value="Login" />

This is exactly the same as in our previous example with the exception of the #{flashbox}. This will display our flash message in the view. Remember that the flash message is only available on the next redirect so this will only appear when we go to the page and it has just been set as in an authorization failure. The first time we hit the page, nothing should be displayed. Try it with both the single correct login/password and some other pairs and watch what happens.

Our page.xhtml hasn't changed so I won't repost it here, you can grab it out of one of the previous posts.

As always, let me know in the comments of any questions.


  1. Thanks for this great example. Two questions:
    1) What is the default HTML output of flashbox if you've never set it?
    2) Has this been tested to work with Ramaze 2009/04 (i.e. Innate/Ramaze)

  2. The default output is simply text wherever the flashbox is. I just tested and this does work with the 2009-04 Ramaze.

  3. when I enter in the index page form invalid data, so that I will not be authorized, then the content of the flashbox is not shown in the browser after pressing login. It works fine, if I am redirected authorized to the logged_in page.
    Is this a browser or a ramaze challenge?

    My environment is:
    Ubuntu 9.04
    ruby 1.9.1p129
    ramaze 2009.7
    firefox 3.0.13

  4. kittekat, I have pretty much the same environment. My ruby is 1.9.1p0, but I don't think that's it. I just retested and everything looks OK. So you don't see "Incorrect password, please try again!!!". When you type in "abc" for the login and "xyz" for the password. It should appear above the Login text box. The only thing I had to do different and I assume you've already made this change is to modify "Rs" to "rs" for the new Ramaze.

  5. found it, just a typo - sorry for bothering you with that old blog
    thanks for the check

  6. kittekat, No problem. I'm glad you're finding these posts useful. I know there are a few things that don't work with the new Ramaze, so if you find anything, let me know, and I'll try to correct it.

  7. For nearly two years I am using mainly MAC OS X on a mini as development environment, which runs ruby1.8.6 and still ramaze 2009.01. As I have learned, that the new ramaze requires ruby 1.9, I did not want to fiddle around on the mini. So I created a VMWare Fusion guest system of Ubuntu 9.04, did there a source download of ruby 1.9.1, builded it and had since then a lot of "fun". Regarding Ramaze and Sequel I started to redo your examples to sort out the "unexpected" changes -like the new dataset.filter{} syntax. So it is very likely that you hear more from me. Thanks for the offer.