Ruby on Rails

Ruby on Rails may be the next “Killer-App” for web appliction programmers. Here is a basic recipe for creating your first Rails-based application.

Ruby and Rails make creation of these applications easier than ever before. By prefering convention to configuration, you will find its a lot easier to build an application following Rails’ conventions. However, since that is not always possible, there are workarounds for many of these convetions.

Installing Rails on your computer and your Brain

Okay, Intalling Ruby and Rails on your computer can be done by the following links:

  1. Ruby
  2. Gems
  3. Rails

The harder part is installing Rails on your Brain. While it was designed to be easy to use, Rails does still require some prerequisite talents and studying. While you can get by without all these at first, its always worthwhile to bone up on these subjects.

  1. Object-Oriented Programming
  2. Ruby Programming Language
  3. Relational Databases and Data Modeling
  4. MVC, The Model-View-Controller Architecture
  5. HTML, hopefully XHTML, CSS, JavaScript, and “AJAX“.
  6. Some basics of web design and usability are definitely a plus!

Starting your Rails Project

This command creates a Rails application structure at a directory under your current one. This creates a “myapp” named application.

$ rails myapp

This creates a directory structure named “myapp” with a slew of files and configurations. The structure is very intuitive and easy to grasp. Here is a table of the directory and basic files. Most of these files may not be there quite yet, they will be created after you “generate” parts of the application later.

LocationPurpose
.app/controllers/application.rb Application Controller Helper
.app/controllers/ccc_controller.rb Application Controller File
.app/helpers/application_helper.rb View Helper for all views
.app/helpers/ccc_helper.rb View Helpers for controller ccc
.app/models/ttt.rb Model definitions for table ttt (singluar)
.config/database.yml Database Connection Settings
./config/environment.rb Application Level Settings
./config/environments/eee_rb Development/Test/Production Settings
./config/routes.rb Route (URL Naming) Rules
./log/development.log Framework actions running under development
./test/fixtures/ttt.yml Testing Records for table ttt
./test/functional/ccc_test.rb Controller Tests for ccc
./test/mocks/eee/* Mock-tests for environemtn eee
./test/test_helper.rb Application test helper module
./test/unit/ttt_test.rb Unit Tests for module ttt
./vendor/ 3rd Party logic
./script/console Interactive (irb) console with app libraries
./script/generate Generates Ruby code into this framework
./script/server Runs the webrick web server for development

Your Database

Rails applications are primarily database-driven applications, so you will need a database with schema (tables, etc.) to use. While I can not determine your schema, you will need to follow a few convections as part of the Rails way of doing things. Note that these can be worked around, but it will save you work from the onset if you can abide by these rules.

  1. Database tables should be named as a plural form of a noun, like “pages”
  2. Tables are named like word_word. etc.
  3. Set a single primary key named “id” (lower case!) for the table.
  4. Sequence names (for advanced db’s) are named “pages_id_seq”
  5. There are special column names wich Rails will update automatically for you
    • created_on - Date the record was inserted
    • created_at - Timestamp (date and time) the record was inserted.
    • updated_at - Timestamp (date and time) the record was inserted or updated
  6. Do not name tables with reserved or library names for Ruby or Rails like “Thread/s”
  7. Do not name columns with reserved Ruby symbols or standard names like “method”
  8. Keep a single column as a primary key.
  9. Foreign keys are named as “table_name_id”

Now, create your database and tables. Rails has a scheme to use 3 databases for an application. You should create at least 2 of them now! The popular databases like MySQL, PostgreSQL, Oracle, and DB2 are suppored. Rails was written to work primarily with MySQL, but feel free to choose a better database. I prefer Postgres for data integrity and licensing issues among other reasons.

  • Development database (myapp_development)
  • Test database (myapp_text)
  • Production database (myapp_production). You can create this later, of course.
$ createdb myapp_development
CREATE DATABASE
$ createdb myapp_test
CREATE DATABASE
$ psql myapp_development < myapp/db/myapp.ddl.sql

Connecting the Application to the Database

Now you need to tell rails what the databases are. You can find that in the ./config/database.yml file in your Rails application. It lists database records for development, test, and production. Fill in your database adapter (mysql, postgresql, oracle, db2 or whatever) and connection infomation.

What if you need to connect to a second (or more) databases from your application? Add additional records into your database.yml file for each database. For a “security” database, create this entry for development, test, and production environments.

security_development:
  adapter: postgresql
  database: security
  host: localhost
  username: allen
  password: xxxxx

Next, edit the ./config/environment.rb file, just under the ActiveRecord::Base.establish_connection line add a line to connect from your model class to the name you used above. The RAILS_ENV variable contains either development, test, or production, so we can use that to differentiate depending on the environment. Say we have a model “Authorization” that needs to access a table in the security database, so we add:

Authorization.establish_connection "security_#{RAILS_ENV}”

Unknown: Do we have to do this for every table we need to access in non-application databases? Would it create multiple connections or cache the connection by its name? Does the security_test database get deleted and reconstructed during tests?

ActiveRecord

The ActiveRecord component of Rails is used to model the database in a Ruby Data Framework. This is an essential part of Ruby, but ActiveRecord is not essential to Rails. ActiveRecord utilizes what Ruby does best, integrating Object-Oriented abstact base classes with metaprogramming work.

For each table you wish to add to the model, run the generate command. change the table name into the model name by

  • Make the Model Name singular (table name is plural)
  • Make the Model Name CamelCase (table account_users becomes AccountUser)
$ .script/generate model AccountUser

This adds a file called ./app/models/account_user.rb to the application, containing:

class AccountUser < ActiveRecord::Base
end

Do this for every table you wish to add to the application. (Of course, you can share a data model repository between application!) This basic definition gives you full access to a conventions-bases access to the table. At runtime, the dtabase catalogs are queries to yield the table columns and definitions to build upon.

Not every data model conforms to the Rails ways of doing things. So Rails provides the class decorator methods to dynamically change the model class If you don’t follow that gibberish, just watch... its easy to understand.

Each ActiveRecord Class assumes the following:

  1. Table Name is plural and “_” form of class name, “AccountUser” becomes “account_users”
  2. Primary key is “id” (lower case), usually an integer, and a single column

You can use decorators to override these rules:

class AccountUser < ActiveRecord::Base
  set_table_name "user_account"
  set_primary_key "employee_id"
end

Overriding Implied Keys

If your database schema does not match the Rails way of doing things, that’s okay! Sure, it will require a couple lines of work, but even in the end you will still be ahead using Rails.

class Project < ActiveRecord::Base
  set_table_name "my_table"
  set_primary_key "project id"
end

See? That wasn’t hard!

Associations

You can add foreign keys, and inter-table relationships into the records to preserve the integrity and give you easy access to these relationships in your code. You specify the table name in symbol form as the association

class Project < ActiveRecord::Base
    belongs_to              :portfolio
    has_one                 :project_manager
    has_many                :milestones
    has_and_belongs_to_many :categories
end

Defining these associations defines methods in your ActiveRecord class to access these related tables. Substitute your table or association name for assoc and the plural name for assocs in the list. They will be available for the expected singular or multiple association.

  1. assoc() fetches associated record(s) from the database
  2. assoc=(record) to assign a a record to that association
  3. assoc.nil? check if the association has a linked record
  4. assocs.empty? check if the association has any linked record.
  5. assocs.size How many records exist in the association
  6. assocs«(record) Adds a record in the association
  7. assocs.delete(record) Deletes a record from the association
  8. assocs.find(id) Returns the matching record from the association
  9. assocs.find_all(conditions) Returns the matching records from the association
  10. assocs.build(attributes) Forms an association record object
  11. assocs.create(attributes) Builds and saves the association record

When defining the association, the following optional parameters may be given when appropriate.

  1. :association_name, names the association, usually the table_name.
  2. :order ⇒ “col, cols desc”, sets the order of returned records
  3. :conditions ⇒ [”where clause”], Any where-clause additions required
  4. :class_name ⇒ RecordClass, to override the implied association class name
  5. :foreign_key ⇒ foreign_key_name, override the implied foreign key name
  6. :dependent ⇒ parm, what happens to dependent records in the association
    1. :destroy or true, destroys (cascade deletes) dependent records
    2. :nullify, sets the values to null in the dependent records
  7. :exclusively_dependent ⇒true, deletes all dependent records at once from your class
  8. :finder_sql⇒“statement”, a complete statement to select rows for the association
  9. :counter_sql⇒“statement”, a complete statement to select rows counts for the association
  10. :extend ⇒ ModuleName, extends class with external module methods shared between classes
  11. :include ⇒ :association, loads a secondary association along with current data

Association records from the database are cached. Subsequent accesses do not hit the database again unless you spefify the force_relead parameter: record.assoc_record(true).

Returning Rows

Business Rules: Validation

Business Rules: Implementing Rules

Callbacks

Transactions

ActionController

ActionView

Tests

Prototype Javascript Library

ActionMailer

ActionWebService

 
programming/rails.txt · Last modified: 2005/11/21 23:10 by allen