Oomoo

March 11, 2008

“Model” Relationships

Filed under: model, rails — oomoo @ 1:47 pm

Notes about how Relationships work in Rails Models.  I created the examples and pulled some of the notes from the API doc.
 

http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html 
 
 

“belongs_to” – Means “this class is a child of the class that is named in the belongs_to statement”. 

“parent class”  –  Use the mixed case singular form. 

“foreign key field”  –  Use the signular form of the parent class name with _id appended. 
 
 

Example: 

class Order < ActiveRecord::Base

  set_table_name “orders”

  set_primary_key “ordPK” 

  #tblOrders belong to customers, use the orders.ordcustpk field.

  belongs_to :customer, :foreign_key => “ordCustPK” 

  #Orders belong to CustomerContact,

  #but only when the field CustomerContact.custconPrimary = 1

  belongs_to :customercontact,  :conditions => “custconPrimary=1” 

  #Customer

  belongs_to :shipment, :foreign_key => “ordShipPK”

end 
 

class Customer < ActiveRecord::Base

  set_table_name “customers”

  set_primary_key “CustPK” 

  has_many :orders, :foreign_key => “ordCustPK”

  has_many :customercontacts, :foreign_key => “custconCustPK”

end 
 

class Customercontact < ActiveRecord::Base

  set_table_name “customercontacts”

  set_primary_key “custconPK” 

  #orders belong to customers, use the orders.ordcustpk field.

  belongs_to :customer, :foreign_key => “custconCustPK” 

  #CustomerContacts has many Orders,

  #  related through Customer, using the key index Orders.ordCustPK.

  #To link Orders to Customer.  (the link from

  #  CustomerContacts to Customers is already specified above)

  has_many :orders, :through => :customer, :foreign_key => “ordCustPK”

end 
 

class Shipment < ActiveRecord::Base

  set_table_name “shipments”

  set_primary_key “shipPK” 

  #Each Shipment only has one Order (one-to-one relationship)

  has_one :order

end 
 
 

One-to-one

Use has_one in the base, and belongs_to in the associated model.

  class Employee < ActiveRecord::Base

    has_one :office

  end

  class Office < ActiveRecord::Base

    belongs_to :employee    # foreign key – employee_id

  end 

One-to-many

Use has_many in the base, and belongs_to in the associated model.

  class Manager < ActiveRecord::Base

    has_many :employees

  end

  class Employee < ActiveRecord::Base

    belongs_to :manager     # foreign key – manager_id

  end 

Many-to-many

There are two ways to build a many-to-many relationship.

The first way uses a has_many association with the :through option and a join model, so there are two stages of associations.

  class Assignment < ActiveRecord::Base

    belongs_to :programmer  # foreign key – programmer_id

    belongs_to :project     # foreign key – project_id

  end 

  class Programmer < ActiveRecord::Base

    has_many :assignments

    has_many :projects, :through => :assignments

  end 

  class Project < ActiveRecord::Base

    has_many :assignments

    has_many :programmers, :through => :assignments

  end 

For the second way, use has_and_belongs_to_many in both models. This requires a join table that has no corresponding model or primary key.

  class Programmer < ActiveRecord::Base

    has_and_belongs_to_many :projects       # foreign keys in the join table

  end 

  class Project < ActiveRecord::Base

    has_and_belongs_to_many :programmers    # foreign keys in the join table

  end 

Choosing which way to build a many-to-many relationship is not always simple. If you need to work with the relationship model as its own entity, use has_many :through. Use has_and_belongs_to_many when working with legacy schemas or when you never work directly with the relationship itself.  

Is it a belongs_to or has_one association?

Both express a 1-1 relationship. The difference is mostly where to place the foreign key, which goes on the table for the class declaring the belongs_to relationship. Example:

  class User < ActiveRecord::Base

    # I reference an account.

    belongs_to :account

  end 

  class Account < ActiveRecord::Base

    # One user references me.

    has_one :user

  end 

The tables for these classes could look something like:

  CREATE TABLE users (

    id int(11) NOT NULL auto_increment,

    account_id int(11) default NULL,

    name varchar default NULL,

    PRIMARY KEY  (id)

  ) 

  CREATE TABLE accounts (

    id int(11) NOT NULL auto_increment,

    name varchar default NULL,

    PRIMARY KEY  (id)

  ) 
 
 
 

Partial List of Options:

:class_name – specify the class name of the association. Use it only if that name can’t be inferred from the association name. So has_one :author will by default be linked to the Author class, but if the real class name is Person, you’ll have to specify it with this option.

:conditions – specify the conditions that the associated object must meet in order to be included as a WHERE SQL fragment, such as authorized = 1.

:order – specify the order in which the associated objects are returned as an ORDER BY SQL fragment, such as last_name, first_name DESC

:foreign_key – specify the foreign key used for the association. By default this is guessed to be the name of the associated class in lower-case and _id suffixed. So a Person class that makes a belongs_to association to a Boss class will use boss_id as the default foreign_key.  
 
 

Examples:

belongs_to :firm, :foreign_key => “client_of”

belongs_to :author, :class_name => “Person”, :foreign_key => “author_id”

belongs_to :valid_coupon, :class_name => “Coupon”, :foreign_key => “coupon_id”, :conditions => ‘discounts > #{payments_count}’

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: