h1. Dr Nic's Magic Models h2. News alert Assocations now generated using "Foreign Keys":foreignkeys.html too! Now... on with the magic show!

*conjure* 1. To create events that appear to be magical
- "David Copperfield":http://www.dcopperfield.com/ website
If you've used Ruby on Rails you'll have written at least one model class like this:
class Person < ActiveRecord::Base
  has_many :memberships
  has_many :groups, :through => :memberships
  belongs_to :family
  validates_presence_of :firstname, :lastname, :email
end
A few minutes later you'll have wondered to yourself,
Why do I have write my own has_many, belongs_to, and validates_presence_of commands if all the data is in the database schema?
Now, for the very first time, your classes can look like this:
class Person < ActiveRecord::Base
end
or, if you are lazy...
class Person < ActiveRecord::Base; end
or, if you read right to the end of this page, this...

Magic and mystery abound. All for you. Impress your friends, amaze your mother. NOTE: The gratuitous use of *Dr Nic's* in the name should only enhance the mystical magicery, for magic needs a magician; and I love magic. I always wanted to create my own magic trick. So I shall be the magician for the sake of magic itself. I look a bit like Harry Potter if Harry were 31 and better dressed. h2. Installation To install the Dr Nic's Magic Models gem you can run the following command to fetch the gem remotely from RubyForge:
gem install dr_nic_magic_models
or "download the gem manually":http://rubyforge.org/projects/magicmodels and run the above command in the download directory. Now you need to require the gem into your Ruby/Rails app. Insert the following line into your script (use config/environment.rb for your Rails apps):
require 'dr_nic_magic_models'
Your application is now blessed with magical mystery. h2. David Copperfield eat your Ruby-crusted heart out Let's demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app:
rails magic_show
cd magic_show
ruby script/generate model Person
ruby script/generate model Group
ruby script/generate model Membership
Update the migration 001_create_people.rb with:
class CreatePeople < ActiveRecord::Migration
  def self.up
    create_table :people do |t|
      t.column :firstname, :string, :null => false
      t.column :lastname, :string, :null => false
      t.column :email, :string, :null => false
    end
  end

  def self.down
    drop_table :people
  end
end
Similarly, update the def self.up method of 002_create_groups.rb with:
    create_table :groups do |t|
      t.column :name, :string, :null => false
      t.column :description, :string
    end
and 003_create_memberships.rb with:
    create_table :memberships do |t|
      t.column :person_id, :integer, :null => false
      t.column :group_id, :integer, :null => false
    end
Now create your database. For MySql:
mysqladmin -u root create magic_show_development
mysqladmin -u root create magic_show_test
And run your migrations to create the three tables:
rake migrate
h2. And now for some "woofle dust":http://en.wikipedia.org/wiki/List_of_conjuring_terms ... At the end of config/environment.rb add the following line:
require 'dr_nic_magic_models'
Now, let's do a magic trick. First, let's check our model classes (app/models/person.rb etc):
class Person < ActiveRecord::Base
end
class Group < ActiveRecord::Base
end
class Membership < ActiveRecord::Base
end
Nothing suspicious here. We have no validations and no associations. Just some plain old model classes. For this trick, we'll need an ordinary console session. Any old one lying around the house will do.
ruby script/console
Now a normal model class is valid until you explicitly add validates_xxx commands. With Dr Nic's Magic Models:
>> person = Person.new
=> #"", "firstname"=>"", "email"=>""}, @new_record=true>
>> person.valid?
=> false
>> person.errors
=> ["can't be blank"], 
"lastname"=>["can't be blank"], "email"=>["can't be blank"]}, 
@base=, 
@attributes={"lastname"=>"", "firstname"=>"", "email"=>""}, @new_record=true>>
*Kapoow!* Instant validation! Because you specified the three columns as :null => false, your ActiveRecord models will now automatically generated validates_presence_of for each non-null field. Ok, we're just warming up. Your models normally require association commands (has_many, belongs_to, etc, as demonstrated above) to have the brilliantly simple support that Rails/ActiveRecords are known for. Let's just watch what Dr Nic's Magic Models can do without any effort at all...
>> person = Person.create(:firstname => "Nic", :lastname => "Williams", :email => "drnicwilliams@gmail.com")
>> group = Group.create(:name => "Magic Models Forum", :description => "http://groups.google.com/magicmodels")
>> membership = Membership.create(:person_id => person, :group_id => group)
>> person.memberships.length
=> 1
>> membership.person
=> "Williams", "firstname"=>"Nic", 
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
>> group.memberships
=> ["1", "id"=>"1", "person_id"=>"1"}>]
The final association trick is a ripper. Automatic generation of has_many :through associations...
>> person.groups
=> ["Magic Models Forum", "id"=>"1", "description"=>nil}>]
>> group.people
=> ["Williams", "firstname"=>"Nic", 
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>]
h2. Drum roll... Ladies and gentlemen. For my final feat of magical mastery, I'll ask you to do something you've never done before. This illusion is akin to the "floating lady":http://www.toytent.com/Posters/985.html illusion that has been passed down through generations of magicians. Exit your console session. DELETE your three model classes: person.rb, group.rb, and membership.rb from the app/models folder. (You can always get them back via the model generator... be fearless!) Re-launch your console. *drums are still rolling...* Be prepared to applaud loudly...
>> Person
=> Person
You applaud loudly, but watch for more...
>> person = Person.find(1)
=> "Williams", "firstname"=>"Nic", 
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
>> person.memberships
=> ["1", "id"=>"1", "person_id"=>"1"}>]
>> person.groups
=> ["Magic Models Forum", "id"=>"1", "description"=>nil}>]
h2. Tada! The end. h2. Dr Nic's Blog "http://www.drnicwilliams.com":http://www.drnicwilliams.com - for future announcements and other stories and things. h2. Articles about Magic Models * "Announcement":http://drnicwilliams.com/2006/08/07/ann-dr-nics-magic-models/ * "BTS - Class creation":http://drnicwilliams.com/2006/08/10/bts-magic-models-class-creation/ h2. Forum "http://groups.google.com/group/magicmodels":http://groups.google.com/group/magicmodels h2. Licence This code is free to use under the terms of the MIT licence. h2. Contact Comments are welcome. Send an email to "Dr Nic Williams":mailto:drnicwilliams@gmail.com or via his blog at "http://www.drnicwilliams.com":http://www.drnicwilliams.com