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
rders, :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
rders, :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
rder
end
One-to-one
Use has_one in the base, and belongs_to in the associated model.
class Employee < ActiveRecord::Base
has_one
ffice
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.
rder – 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}’