Introduction to Ruby on Rails — April 4th, 2011

Ruby on Rails is a web application framework that uses Ruby to help build web applications. It was created by David Heinemeier Hansson in 2004 when he extracted the core from an existing web application (called Basecamp) and generalized it so that it could be used to build other applications. It is still actively maintained and is currently at version 3.0.5, which was release near the end of February, 2011. (Version 3.0.6 was released on April 6th. This version is now available in ~donald/pub/rails. The documentation below, however, still refers to version 3.0.5 in some places.)

Some of the more notable aspects of this framework include:

MVC Architecture
This architecture (which is not unique to Rails), divides the application into three main components, the Model, View and Controller. The purpose of this architecture is to separate the primary functionalities of the web application into three major players: The Controller is responsible for the logic and processing, the Model takes care of querying/storing data and the View detemines how the final result is presented to the user.

A typical interaction in the context of a Rails web application is outlined below and illustrated in the figure on the right.

[MVC]
  1. An HTTP request from a user's browser is taken by the router which processes the request.
  2. The router determines which Controller to activate based upon the request (the URL often determines which controller is used).
  3. The Controller performs the actions necessary to satisfy the user's request. (The controllers are represented by different classes; their methods correspond to different actions.) During the course of processing the request, the Controller may query the Model.
  4. The model communicates with the database to retrieve and/or store data, as requested by the Controller.
  5. After the Controller action has completed an appropriate View template is selected. While these View templates may contain programming logic, it is usually kept at a minimum. Most of the logic should be performed in the Controller when possible.
  6. This view template is sent back to the user's web browser for display.

Convention over configuration
Ruby on Rails makes a number of assumptions about the location and names of various files, classes and methods. These assumptions mitigate the need for numerous configuration files related to your web application. Once you are familiar with these conventions, development, deployment and maintenance of your web application can become easier.
Object Relational Mapper
The Model implemented by ActiveRecord provides support for object-relational mapping (ORM). This enables you to treat items in the database as if they were objects. Informally, database tables are represented by classes, database rows are represented by objects and database columns are represented by object attributes. In other framesworks, a number of XML files are necessary to do this mapping. Rails uses convention over configuration and dynamic code generation to make ORM more automatic. Associations between database tables are also handled in the context of the ORM.
Support for AJAX
Rails provides support for more interactive web pages via AJAX without have to actually write any JavaScript or XML. JavaScript is generated from Ruby code in RJS templates. (We won't be talking about that here.)
Testing Frameworks
Rails provides tools that enable comprehensive unit, functional and integration testing of your web application. Preliminary testing code is automatically generated by the code generators, thereby encouraging testing during application development. (Again, due to time constraints, we won't be talking about that here.)
Code Generation
Rails can generate a lot of the foundation code upon which your application is based. These code generators follow the conventions mentioned above and make it easy to build simple applications with rails quickly. Unfortunately, the code generated can be difficult to understand for novices (at least, initially).

Installing Rails

We don't have time to discuss or perform an installation. Refer to the Ruby on Rails Website or Section 1.2 of the Ruby on Rails Tutorial. A private copy of version 3.0.5 of Rails is already installed on the Computer Science machines at MUN and should be accessible with the command (notice the preceding dot):

$ . /users/cs/grad/donald/pub/rails/setpath

This places the directory /users/cs/grad/donald/pub/rails/bin at the front of your PATH environment variable so that all the commands (especially the rails command) can be executed without having to type their full path name. To test whether everything is setup right, try the following commands:

$ which rails
/users/cs/grad/donald/pub/rails/bin/rails
$ rails -v
Rails 3.0.5
$ rails
Usage:
  rails new APP_PATH [options]

Options:
  -r, [--ruby=PATH]           # Path to the Ruby binary of your choice
                              # Default: /users/cs/grad/donald/pub/rails/bin/ruby
  -d, [--database=DATABASE]   # Preconfigure for selected database 
                              #  (options: mysql/oracle/postgresql/sqlite3/frontbase/ibm_db)
                              # Default: sqlite3
  -b, [--builder=BUILDER]     # Path to an application builder (can be a filesystem path or URL)
  -m, [--template=TEMPLATE]   # Path to an application template (can be a filesystem path or URL)
      [--dev]                 # Setup the application with Gemfile pointing to your Rails checkout
      [--edge]                # Setup the application with Gemfile pointing to Rails repository
      [--skip-gemfile]        # Don't create a Gemfile
  -O, [--skip-active-record]  # Skip Active Record files
  -T, [--skip-test-unit]      # Skip Test::Unit files
  -J, [--skip-prototype]      # Skip Prototype files
  -G, [--skip-git]            # Skip Git ignores and keeps

Runtime options:
  -f, [--force]    # Overwrite files that already exist
  -p, [--pretend]  # Run but do not make any changes
  -q, [--quiet]    # Supress status output
  -s, [--skip]     # Skip files that already exist

Rails options:
  -v, [--version]  # Show Rails version number and quit
  -h, [--help]     # Show this help message and quit

Description:
    The 'rails new' command creates a new Rails application with a default
    directory structure and configuration at the path you specify.

Example:
    rails new ~/Code/Ruby/weblog

    This generates a skeletal Rails installation in ~/Code/Ruby/weblog.
    See the README in the newly created application to get going.

NOTE: Conventional IDEs are typically shunned by the Rails developer community in favour of a terminal command line and a good text editor. There are several guides online to help you understand how to use the command line

Creating a new Application

For this introduction, we'll generate a very, very simple Electronic Medical Record (EMR) application. We can use the new subcommand of the rails command to generate the foundation for the application.

$ rails new emr
      create  
      create  README
      create  Rakefile
      create  config.ru
      create  .gitignore
      create  Gemfile
      create  app
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/mailers
      create  app/models
      create  app/views/layouts/application.html.erb
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/secret_token.rb
      create  config/initializers/session_store.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  doc
      create  doc/README_FOR_APP
      create  lib
      create  lib/tasks
      create  lib/tasks/.gitkeep
      create  log
      create  log/server.log
      create  log/production.log
      create  log/development.log
      create  log/test.log
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/favicon.ico
      create  public/index.html
      create  public/robots.txt
      create  public/images
      create  public/images/rails.png
      create  public/stylesheets
      create  public/stylesheets/.gitkeep
      create  public/javascripts
      create  public/javascripts/application.js
      create  public/javascripts/controls.js
      create  public/javascripts/dragdrop.js
      create  public/javascripts/effects.js
      create  public/javascripts/prototype.js
      create  public/javascripts/rails.js
      create  script
      create  script/rails
      create  test
      create  test/fixtures
      create  test/functional
      create  test/integration
      create  test/performance/browsing_test.rb
      create  test/test_helper.rb
      create  test/unit
      create  tmp
      create  tmp/sessions
      create  tmp/sockets
      create  tmp/cache
      create  tmp/pids
      create  vendor/plugins
      create  vendor/plugins/.gitkeep

This command creates an emr directory and creates several more files and subdirectories. We can change to the emr directory and see them:

$ cd emr
$ ls -F
Gemfile  Rakefile  config/    db/   lib/  public/  test/  vendor/
README	 app/	   config.ru  doc/  log/  script/  tmp/

The README file contains many helpful details regarding the files and subdirectories generated as well as some hints on what to do next and how to debug your application. The most important subdirectories we'll be dealing with is the app subdirectory which contains subsubdirectories that contain the files for the models, views and controllers and the db subdirectory which contains the database as well as files related to the creation and modification of the database schema.

Starting the Server

Although we haven't actually created any real application code yet, we can still start a webserver so that we can view a welcome page. This can be done with the server subcommand of the rails command:

$ rails server
[2011-04-01 17:35:56] INFO  WEBrick 1.3.1
[2011-04-01 17:35:56] INFO  ruby 1.9.2 (2011-02-18) [i686-linux]
[2011-04-01 17:35:56] INFO  WEBrick::HTTPServer#start: pid=7428 port=3000

Many log messages will be displayed in this window as you access your application from a web browser. Viewing these log messages can be helpful when diagnosing problems with the web application.

If you get a message about the port already in use, a server is already running on that machine using that port (probably a server you started earlier). Either kill that server or use a different port, for example: rails server -p 3001.

When you are finished, remember to kill the server by pressing Ctrl-C in this terminal window. Or you can find the process ID using the ps and kill it off manually.

When the server has been started we can access it through our web browser by visiting the URL: http://localhost:3000.

Generating a Model/View/Controller

We'll open a new command line window (leaving the window that we used to start the server) and set up our path using the . /users/cs/grad/donald/pub/rails/setpath command again.

Central to any EMR is the patients under a physicians care. We'll use the generate subcommand of the rails command to generate the scaffolding of a model-view-controller that will be used to interact with the Patients in the database. After changing back into the emr directory, we issue the command:

$ rails generate scaffold Patient name:string address:text dob:date mcp_number:string
      invoke  active_record
      create    db/migrate/20110329194309_create_patients.rb
      create    app/models/patient.rb
      invoke    test_unit
      create      test/unit/patient_test.rb
      create      test/fixtures/patients.yml
       route  resources :patients
      invoke  scaffold_controller
      create    app/controllers/patients_controller.rb
      invoke    erb
      create      app/views/patients
      create      app/views/patients/index.html.erb
      create      app/views/patients/edit.html.erb
      create      app/views/patients/show.html.erb
      create      app/views/patients/new.html.erb
      create      app/views/patients/_form.html.erb
      invoke    test_unit
      create      test/functional/patients_controller_test.rb
      invoke    helper
      create      app/helpers/patients_helper.rb
      invoke      test_unit
      create        test/unit/helpers/patients_helper_test.rb
      invoke  stylesheets
      create    public/stylesheets/scaffold.css

The contents of the controller and the corresponding views are shown below, in abbreviated form. Note the following observations:

Controller (edited for brevity)
# app/controllers/patients_controller.rb
class PatientsController < ApplicationController
  # Get a list of all patients
  def index
    @patients = Patient.all
    ...
  end


  # Show details of one patient
  def show
    @patient = Patient.find(params[:id])
    ...
  end


  # Generate a form to create a new patient
  def new
    @patient = Patient.new(params[:patient])
    ...
  end


  # Generate a form to update a patient
  def edit
    @patient = Patient.find(params[:id])
    ...
  end


  # Create a new patient in the database
  def create
    @patient = Patient.new(params[:patient])
    ...
      if @patient.save
    ...
  end


  # Update an existing patient in the database.
  def update
    @patient = Patient.find(params[:id])
    ...
  end


  # Remove a patient from the database.
  def destroy
    @patient = Patient.find(params[:id])
    @patient.destroy
    ...
  end
end
Views (edited for brevity)
<!-- app/views/patient/index.html.erb -->
<h1>Listing patients</h1>

<table>
  <tr>
    <th>Name</th>
    ...
  </tr>

<% @patients.each do |patient| %>
  <tr>
    <td><%= patient.name %></td>
    ...
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Patient', new_patient_path %>
<!-- app/views/patient/show.html.erb -->
<p id="notice"><%= notice %></p>

<p>
  <b>Name:</b>
  <%= @patient.name %>
  ...
</p>

<%= link_to 'Edit', edit_patient_path(@patient) %> |
<%= link_to 'Back', patients_path %>
<!-- app/views/patient/new.html.erb -->
<h1>New patient</h1>

<%= render 'form' %>

<%= link_to 'Back', patients_path %>
<!-- app/views/patient/edit.html.erb -->
<h1>Editing patient</h1>

<%= render 'form' %>

<%= link_to 'Show', @patient %> |
<%= link_to 'Back', patients_path %>

Both the new.html.erb and edit.html.erb views use a common chuck of HTML representing the form to be displayed to the physician. This common code is called a partial in rails and is located in the file _form.html.erb in the app/patient/views subdirectory. It is rendered with the render command in the new.html.erb and edit.html.erb views. (Note that we add a :start_year => 1880 hash parameter to the :dob attribute to allow older patients to be represented in the database.)

<!-- app/views/patient/_form.html.erb -->
<%= form_for(@patient) do |f| %>
  <% if @patient.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@patient.errors.count, "error") %> prohibited this patient from being saved:</h2>

      <ul>
      <% @patient.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :address %><br />
    <%= f.text_area :address, :rows => 4, :cols => 20 %>
  </div>
  <div class="field">
    <%= f.label :dob %><br />
    <%= f.date_select :dob, :start_year => 1900, :end_year => 2011 %>
  </div>
  <div class="field">
    <%= f.label :mcp_number %><br />
    <%= f.text_field :mcp_number %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

The code for the Patient model is pretty simple:

# app/models/patient.rb
class Patient < ActiveRecord::Base
end

Much of the functionality for this class is either inherited or created dynamically during runtime as the database is queried by the controller. We'll be adding validation and associations to this model shortly.

Creating the Database Schema

Another file generated is a database migration file. A migration file is simply a ruby program that describes how the database schema (or the data itself) is to be modified as the database evolves over time. The migration generated for us below creates a table named patients with the specified columns in the database.

# db/migrate/*_create_patients.rb
class CreatePatients < ActiveRecord::Migration
  def self.up
    create_table :patients do |t|
      t.string :name
      t.text :address
      t.date :dob
      t.string :mcp_number

      t.timestamps
    end
  end

  def self.down
    drop_table :patients
  end
end

To actually create the schema in the database, we need to apply the migration by running a task to migrate the database to its new state. In rails tasks are run using a utility program called rake, with the name of the task provided as a command line argument. (A list of all tasks can be generated with $ rake --tasks.) To migrate a database, we specify the task named the db:migrate.

$ rake db:migrate
(in .../emr)
==  CreatePatients: migrating =================================================
-- create_table(:patients)
   -> 0.0060s
==  CreatePatients: migrated (0.0061s) ========================================

By default, the sqlite3 database is used, however other databases are supported as well including MySQL, DB2 and Oracle, to name a few.

Using the application

With everything now in places, we can visit the URL http://localhost:3000/patients/ and create, edit, delete, show or list all the patients in the database. We can change the routing so that the URL http://localhost:3000/ will automatically visit the list of patients:

# config/routes.rb
Emr::Application.routes.draw do
...
  # You can have the root of your site routed with "root"
  # just remember to delete public/index.html.
  # root :to => "welcome#index"
  root :to => "patients#index"
...
end

For this to work, we must also remove the index.html file from the public directory:

$ rm public/index.html

As you are adding patients, note the sequence of events:

  1. When you click on the New Patient link, the new action of the PatientsController is called.
  2. This creates a empty patient object which is stored in the @patient member variable (no database access is done).
  3. The new.html.erb form is then generated. Because this form uses the _form.html.erb partial, this partial will also be rendered.
  4. After the form has been completed and the Create Patient button has been pressed validation occurs (see below) and the create action of the PatientsController is called.
  5. This creates a new patient object (@patient) initialized with the data supplied by the physician in the form. This form data is available in the params hash.
  6. This patient object is then saved to the database and we are redirected back to the show patient view to show the newly created patient.

A similar sequence of events happens when you modify a patient, except that the edit/update actions are called instead of the new/create actions. Also, during the call to edit the model is consulted (@patient = Patient.find(params[:id])) to find the patient in the database whose id matches that selected by the physician in the list. The _form.html.erb partial employed by the edit.html.erb view uses this object to pre-populates form with the patient's details.

Validations

Unfortunately, our application has problems. For example, we can create patients without actually filling in any of the fields. We can create invalid/duplicate MCP numbers. Fortunately, models provides an easy way to validate data before actually storing it in the database.

# app/models/patients.rb
class Patient < ActiveRecord::Base
  validates :name, :address, :dob, :mcp_number, :presence => true

validates :mcp_number, :uniqueness => true,
  			:format => {
			  :with => %r{\A\d{12}\z},
			  :message => 'must have exactly 12 digits'
			}
end

Now, whenever we leave fields blank or try to enter invalid data, we are returned to the form which highlights the problems that were encountered. (Note that the dates are not validated, so an invalid date like April 31 will be stored as May 1. Oddly, Rails 3 does not appear to provide a way to validate dates out of the box.)

Populating the Database

To make the application feel a little more "real-world", we can populate it with some random data. This is known as seeding the database and can be done by modifying the db/seeds.rb file. For example, the script below will add 100 random patients to the database with address, birth dates and MCP numbers.

# db/seeds.rb
Patient.delete_all

FIRST_NAMES	= %w(Alice Bob Charlie Dave Eva Mallory Peggy Victor Trent Walter Arthur)
LAST_NAMES	= %w(Smith Jones Brown Williams Miller Wilson Moore Davis)
STREET_NAMES	= %w(Pine Elm Oak Main)
STREET_TYPES	= %w(Blvd. Cresent Road Street Avenue)

STDOUT.sync = true	# Prevent output from being buffered.

print "Seeding database"
100.times do
  patient = Patient.create(:name => "%s %s" % [FIRST_NAMES.sample, LAST_NAMES.sample],
		 :address => "%d %s %s" %
		 	[rand(1000)+1, STREET_NAMES.sample, STREET_TYPES.sample],
  		 :dob => Date.today - rand(40000),
		 :mcp_number => (rand(900000000000) + 100000000000).to_s)
  print "."
end
puts "done"

We can then run this script as a rake task to seed the database:

$ rake db:seed
(in .../emr)
Seeding database....................................................................................................done

Creating Associations

Each patient has a collection of progress notes associated with it. The views for these progress notes will be handled by the patient views, so we'll just generate a model and a controller for the progress notes.

First we create the model. Observe that each note references a patient (in SQL context, this is the foreign key) and as content field that contains text.

$ rails generate model ProgressNote patient:references contents:text
      create  app/controllers/progress_notes_controller.rb
      invoke  erb
      create    app/views/progress_notes
      invoke  test_unit
      create    test/functional/progress_notes_controller_test.rb
      invoke  helper
      create    app/helpers/progress_notes_helper.rb
      invoke    test_unit
      create      test/unit/helpers/progress_notes_helper_test.rb

We re-migrate to introduce the progress note table into the database.

$ rake db:migrate
(in .../emr)
==  CreateProgressNotes: migrating ============================================
-- create_table(:progress_notes)
   -> 0.0040s
==  CreateProgressNotes: migrated (0.0041s) ===================================

The ProgressNote model generated above is as follows. The belongs_to :patient creates the association between the note and the patient to whom it belongs.

# app/models/progress_note.rb
class ProgressNote < ActiveRecord::Base
  belongs_to :patient
end

We must also create an association in the opposition direction, informing the Patient model that it may have zero or more progress notes.

# app/models/patients.rb
class Patient < ActiveRecord::Base
  validates :name, :address, :dob, :mcp_number, :presence => true

  validates :mcp_number, :uniqueness => true,
  			  :format => {
			    :with => %r{\A\d{12}\z},
			    :message => 'must have exactly 12 digits'
			  }

  has_many :progress_notes
end

A progress note is known as a nested resource. We inform the router of this relationship, as follows:

# config/routes.rb
Emr::Application.routes.draw do
  resources :patients
resources :patients do
  resources :progress_notes
end
  ...
end

Now, if patient is a Patient object we can access its associated progress notes by using the syntax patient.progress_notes. We can create a new progress note for a patient using the syntax patient.progress_notes.create(...). We'll see examples of these later on.

Next, we create the controller class for the ProgressNotes:

$ rails generate controller ProgressNotes

The generated class is very simple with no methods. We'll manaully add a create method. This method will be called when the physician clicks on a Create Progress Note button in a view that shows a patient that we'll see later. The create action queries the database for the patient given the patient id, then creates a progress note for that patient initialized with the contents of the progress note's text field. After the note has been created, we redirect to the view that shows the patient and all of his or here progress notes.

# app/controllers/progress_notes_controller.rb
class ProgressNotesController < ApplicationController
  def create
  @patient = Patient.find(params[:patient_id])
  @patient.progress_notes.create(params[:progress_note])
  redirect_to patient_path(@patient)
end
end

In order to show the progress notes in the patient view, we modify the app/views/patients/show.html.erb template. If there are no progress notes, we'll display some text indicating this. Otherwise, we'll iterate over all the patients progress notes displaying the date the note was created as well as the contents of the note.

The block of code following the conditional display of the progress note is a form that allows the physician to create a new progress note. Because a progress note is a nested resource, the form_for syntax in this case takes a list of objects that illustrate this nesting. When the user clicks the submit button created by the form, the create method of the ProgressNoteController will be invoked.

<!-- app/views/patients/show.html.erb -->
<p id="notice"><%= notice %></p>

<p>
  <b>Name:</b>
  <%= @patient.name %>
</p>

<p>
  <b>Address:</b>
  <%= @patient.address %>
</p>

<p>
  <b>Dob:</b>
  <%= @patient.dob %>
</p>

<p>
  <b>Mcp number:</b>
  <%= @patient.mcp_number %>
</p>

<% if @patient.progress_notes.empty? %>
  <strong>No Progress Notes Available</strong>
<% else %>
  <h2>Notes</h2>
  <% @patient.progress_notes.each do |note| %>
    <p>
      <b>Date:</b>
      <%= note.created_at.localtime %><br/>
      <b>Note:</b>
      <%= note.contents %>
    </p>
  <% end %>
<% end %>

<h2>Add a progress note:</h2>
<%= form_for([@patient, @patient.progress_notes.build]) do |f| %>
  <div class="field">
    <%= f.label :contents %><br />
    <%= f.text_area :contents %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

<%= link_to 'Edit', edit_patient_path(@patient) %> |
<%= link_to 'Back', patients_path %>

Finally, we can modify the view that shows a listing of all the patients (app/views/patients/index.html.erb). The modification will add an extra column that shows how many progress notes the physician created for each patient.

<!-- app/view/patients/index.html.erb -->
<h1>Listing patients</h1>

<table>
  <tr>
    <th>Name</th>
    <th>Address</th>
    <th>Dob</th>
    <th>Mcp number</th>
    <th>Notes</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @patients.each do |patient| %>
  <tr>
    <td><%= patient.name %></td>
    <td><%= patient.address %></td>
    <td><%= patient.dob %></td>
    <td><%= patient.mcp_number %></td>
    <td align="center"><%= patient.progress_notes.size %></td>
    <td><%= link_to 'Show', patient %></td>
    <td><%= link_to 'Edit', edit_patient_path(patient) %></td>
    <td><%= link_to 'Destroy', patient, :confirm => 'Are you sure?', :method => :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Patient', new_patient_path %>

The db/seeds.rb can be modified to create random progress notes for each of the patients. This creates progress notes by grabbing random words from the /usr/share/dict/words file and adding them to the progress note associated with a patient. Note again, the use of the patient.progress_notes.create(...). syntax.

# db/seeds.rb
Patient.delete_all

FIRST_NAMES	= %w(Alice Bob Charlie Dave Eva Mallory Peggy Victor Trent Walter Arthur)
LAST_NAMES	= %w(Smith Jones Brown Williams Miller Wilson Moore Davis)
STREET_NAMES	= %w(Pine Elm Oak Main)
STREET_TYPES	= %w(Blvd. Cresent Road Street Avenue)

WORDS = IO.read('/usr/share/dict/words').split("\n")

STDOUT.sync = true	# Prevent output from being buffered.

print "Seeding database"
100.times do
  patient = Patient.create(:name => "%s %s" % [FIRST_NAMES.sample, LAST_NAMES.sample],
		 :address => "%d %s %s" %
		 	[rand(1000)+1, STREET_NAMES.sample, STREET_TYPES.sample],
  		 :dob => Date.today - rand(40000),
		 :mcp_number => (rand(900000000000) + 100000000000).to_s)
  rand(10).times do 
  # Generate gibberish for the progress notes.
  contents = (1..(rand(30) + 10)).map { WORDS.sample }.join(" ")
  patient.progress_notes.create(:contents => contents)
end
  print "."
end
puts "done"

References


Donald Craig (donald@mun.ca)
Last modified: April 6, 2011 10:38:37 NDT
Valid XHTML 1.0 Strict Valid CSS!