Associations


Rails supports six types of associations:
  • belongs_to
  • has_one
  • has_many
  • has_many :through
  • has_one :through
  • has_and_belongs_to_many

belongs_to

Sets up a one-to-one connection with another model,
Each instance of the declaring model "belongs to" one instance of the other model.
For example, if your application includes customers and orders, and each order can be assigned to exactly one customer:
 
Migration:
class CreateOrders < ActiveRecord::Migration
  def change
    create_table :customers do |t|
      t.string :name
      t.timestamps
    end
 
    create_table :orders do |t|
      t.belongs_to :customer
      t.datetime :order_date
      t.timestamps
    end
  end
end
 

has_one

sets up a one-to-one connection with another model
each instance of a model contains or possesses one instance of another model.
 
class CreateSuppliers < ActiveRecord::Migration
  def change
    create_table :suppliers do |t|
      t.string :name
      t.timestamps
    end
 
    create_table :accounts do |t|
      t.belongs_to :supplier
      t.string :account_number
      t.timestamps
    end
  end
end
 

has_many

Indicates a one-to-many connection with another model.
Often found on the "other side" of a belongs_to association.
each instance of the model has zero or more instances of another model.
For example, in an application containing customers and orders, the customer model could be declared like this:
 
class CreateCustomers < ActiveRecord::Migration
  def change
    create_table :customers do |t|
      t.string :name
      t.timestamps
    end
 
    create_table :orders do |t|
      t.belongs_to :customer
      t.datetime :order_date
      t.timestamps
    end
  end
end

The name of the other model is pluralized when declaring a has_many association.


has_many :through

Used to set up a many-to-many connection with another model.
The declaring model can be matched with zero or more instances of another model by proceeding through a third model.
For example, consider a medical practice where patients make appointments to see physicians. The relevant association declarations could look like this:
 
class CreateAppointments < ActiveRecord::Migration
  def change
    create_table :physicians do |t|
      t.string :name
      t.timestamps
    end
 
    create_table :patients do |t|
      t.string :name
      t.timestamps
    end
 
    create_table :appointments do |t|
      t.belongs_to :physician
      t.belongs_to :patient
      t.datetime :appointment_date
      t.timestamps
    end
  end
end
 

The collection of join models can be managed via the API. For example, if you assign
physician.patients = patients
new join models are created for newly associated objects, and if some are gone their rows are deleted.

Automatic deletion of join models is direct, no destroy callbacks are triggered.

"shortcuts" through nested has_many associations.
For example, if a document has many sections, and a section has many paragraphs, you may sometimes want to get a simple collection of all paragraphs in the document. You could set that up this way:
class Document < ActiveRecord::Base
  has_many :sections
  has_many :paragraphs, through: :sections
end
 
class Section < ActiveRecord::Base
  belongs_to :document
  has_many :paragraphs
end
 
class Paragraph < ActiveRecord::Base
  belongs_to :section
end

With through: :sections specified, Rails will now understand:
@document.paragraphs

has_one :through

sets up a one-to-one connection with another model.
The declaring model can be matched with one instance of another model by proceeding through a third model.
For example, if each supplier has one account, and each account is associated with one account history, then the supplier model could look like this:
 
class CreateAccountHistories < ActiveRecord::Migration
  def change
    create_table :suppliers do |t|
      t.string :name
      t.timestamps
    end
 
    create_table :accounts do |t|
      t.belongs_to :supplier
      t.string :account_number
      t.timestamps
    end
 
    create_table :account_histories do |t|
      t.belongs_to :account
      t.integer :credit_rating
      t.timestamps
    end
  end
end
 


has_and_belongs_to_many

creates a direct many-to-many connection with another model, with no intervening model.
For example, if your application includes assemblies and parts, with each assembly having many parts and each part appearing in many assemblies, you could declare the models this way:
 
class CreateAssembliesAndParts < ActiveRecord::Migration
  def change
    create_table :assemblies do |t|
      t.string :name
      t.timestamps
    end
 
    create_table :parts do |t|
      t.string :part_number
      t.timestamps
    end
 
    create_table :assemblies_parts do |t|
      t.belongs_to :assembly
      t.belongs_to :part
    end
  end
end
 


















Comments