Review active record query
Types of association?
There are 6 types of association: belongs_to
, has_one
, has_many
, has_many :through
, has_one :through
, has_and_belongs_to_many
.
belongs_to
must use in singular term, it describe one-to-one association. Example: 1 Order
belongs to 1 Customer
in Order’s model has field name customer_id
(int), and customer_id
referer with id of Customer’s model.
has_one
built for one-to-one association, it set-up connection between 2 models, but it has somewhat different semantics.
Example each Supplier has one Account, in Account’s model has field name supplier_id
(int).
belongs_to
and has_one
is same when we write migrations, we need to indexing the column connection (customer_id
, supplier_id
)
has_many
is indicates one-to-many associations. Example: 1 Customers
has many n orders
. Instance of Customer’s model has many instance of orders’s model.
Example: Customer has many orders. in Order’s model has field customer_id
(int)
Example migration:
class CreateOrders < ActiveRecord::Migration
def change
create_table :customers do |t|
t.string :name
t.timestamps null: false
end
create_table :orders do |t|
t.belongs_to :customer, index: true
t.datetime :order_date
t.timestamps null: false
end
end
end
The has_many :through
association. it often use to set up many-to-many connection. It indicates One model can be matched with many instance other model through
the third model.
Example: consider context about medical practice, where patients make appointments to see physicians. 1 Physician can has many patients through appointments. Physician has many patients and has many appointments. Then, appointments belongs to physician, and belongs to appointment. Like physicians, 1 Patient can has many physicians through appointments. Patient has many physicians, has many appointments.
Appointments model has 2 field bo describe the connection is physician_id
and patient_id
.
Example:
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
end
Sometime The has_many :through
use like shortcuts
, example we have Document, the document has many sections, one session has many paragraphs. So we can get paragraphs of ducuments by Document.paragraphs by this association.
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
The has_one :through
association. Like has_many :through
, it indicates connection through the third model, but it has one connection.
The has_and_belongs_to_many
association, indicates many-to-many connection, with no intervaling model.
Example: create model Assembly and model Part, each assembly has many parts, and each part has many assemblies. But we don’t need create model interval such as assembly_part.
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
class CreateAssembliesAndParts < ActiveRecord::Migration
def change
create_table :assemblies do |t|
t.string :name
t.timestamps null: false
end
create_table :parts do |t|
t.string :part_number
t.timestamps null: false
end
create_table :assemblies_parts, id: false do |t|
t.belongs_to :assembly, index: true
t.belongs_to :part, index: true
end
end
end
Polymorphic Associations
With polymorphic assocation, one model can belongs to more then one model, on a single association. You can think a polymorphic belongs_to
declare as setting up interface
that any other model can use.
Example: you have picture model, that belongs to either an employee model or a product model.
class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
end
class Employee < ActiveRecord::Base
has_many :pictures, as: :imageable
end
class Product < ActiveRecord::Base
has_many :pictures, as: :imageable
end
You can retrive pictures by @employee.pictures
and @product.pictures
.
You can get parent of picture by @picture.imageable
, you may declare both a foreign key column and type column in the model the declare the polymorphic interface.
class CreatePictures < ActiveRecord::Migration
def change
create_table :pictures do |t|
t.string :name
t.integer :imageable_id
t.string :imageable_type
t.timestamps null: false
end
add_index :pictures, :imageable_id
end
end
// this migration can be simplified by t.references from
class CreatePictures < ActiveRecord::Migration
def change
create_table :pictures do |t|
t.string :name
t.references :imageable, polymorphic: true, index: true
t.timestamps null: false
end
end
end
Self Joins
Sometime, you will find a model that should have a relation itself. Example, you want to store all employees
in single model, but you want to know who is manager or who is subordinates. It mean you can trace relationship between manager and subordinates.
class Employee < ActiveRecord::Base
has_many :subordinates, class_name: "Employee", foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
end
// With this set-up you can retrive, @employee.manager and @employee.subordinates
// In migration
class CreateEmployees < ActiveRecord::Migration
def change
create_table :employees do |t|
t.references :manager, index: true
t.timestamps null: false
end
end
end