Active Record Association: Relation (PART 1)
Bài đăng này đã không được cập nhật trong 6 năm
Mở đầu
- Trong rails, một association giúp kết nối giữa 2 hoặc nhiều model
- Nó giúp việc truy vấn cơ sở dữ liệu đơn giản và dễ dàng hơn, code ngăn gọn hơn.
this is example for use or not active record
The Types of Associations
Rails hỗ trợ 6 loại assocications:
- belongs_to
- has_one
- has_many
- has_many :through
- has_one :through
- has_and_belongs_to_many
Ở bài viết này mình sẽ giới thiệu qua về các associations: has_many :through, has_one :through, has_and_belongs_to_many và các options.
The has_many :through Association
Ví dụ ta có ba bảng như sau:
1 company có nhiều job, và 1 job thì có nhiều apply, vậy nghĩa là 1 company sẽ có nhiều apply, ta sẽ khai báo như sau trong model company:
class Company < ApplicationRecord
has_many :jobs
has_many :applies, through: :jobs
end
- Khi muốn lấy các applies của company, ta chỉ cần viết
@company.applies
- Chúng ta có thể dễ dàng nhận thấy nó sử dụng option through, vì bản chất của through như toán tử join trong sql.
The has_and_belongs_to_many Association
Để nói về association này mình sẽ đưa ra 1 ví dụ khác như sau:
Đối với quan hệ nhiều nhiều, chúng ta có hai cách thể hiện thông qua active record:
- Cách 1: Sử dụng has_and_belongs_to_many, không cần model trung gian (lưu ý: chỉ không cần model, db vẫn phải lưu table trung gian)
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
- Cách 2: Sử dụng model trung gian như chúng ta vẫn hay sử dụng:
class Assembly < ActiveRecord::Base
has_many :assemblies_parts
has_many :parts, through: :assemblies_parts
end
class Part < ActiveRecord::Base
has_many :assemblies_parts
has_many :assemblies, through: :assemblies_parts
end
class AssembliesParts < ActiveRecord::Base
has_many :assembly
has_many :part
end
Nhận xét:
- Đối với cách 1 làm code ngắn gọn, đơn giản hơn.
- Đối với cách 2 vì có model trung gian nên có thể thêm attributes và sử dụng validation, callback.
Self Joins
Là khi model có relation với chính nó, để hiểu rõ self joins mình sẽ giới thiệu nó qua 2 ví dụ, trong trường hợp quan hệ 1-n và n-n
- Trường hợp quan hệ 1-n: một nhân viên có nhiều người quản lí, và 1 người quản lí cũng sẽ có nhiều nhân viên, nhân viên và quản lí đều nằm trong 1 bảng user
class User < ApplicationRecord
has_many :subordinates, class_name: User.name, foreign_key: :manager_id
belongs_to :manager, class_name: User.name
end
- Lấy các nhân viên của 1 quản lý:
@user.subordinates
- Lấy người quản lý của 1 nhân viên:
@user.manager
Nhận xét:
- Ở đây xuất hiện option class_name và foreign_key, vậy tác dụng của nó là gì?
- class_name sẽ nói cho rails biết bạn belongs_to đến model nào
- foreign_key sẽ belongs_to đến model theo key nào.
- Trường hợp quan hệ n-n: trong trường hợp add friends, thì một user sẽ có nhiều người gửi kết bạn đến, đồng thời nó cũng đang gửi kết bạn cho nhiều người, trường hợp này ta cần 1 table trung gian, chứa sender_id và accepter_id.
class User < ApplicationRecord
has_many :active_friends, class_name: Friend.name, foreign_key: :sender_id
has_many :sending, through: :active_friends, source: :accepter
has_many :passive_friends, class_name: Friend.name, foreign_key: :accepter_id
has_many :accepting, through: :passive_friends, source: :sender
end
class Friend < ApplicationRecord
belongs_to :sender, class_name: User.name
belongs_to :accepter, class_name: User.name
end
- Lấy danh sách người user đang gửi kết bạn đến:
@user.accepting
- Lấy danh sách người mà user đang gửi kết bạn:
@user.sending
- Ở đây xuất hiện thêm 1 option đó là source, source nó sẽ xác định tên source cho quan hệ has_many:through.
Polymorphic Associations
polymorphic nghĩa là đa hình, nó được sử dụng để 1 model có thể belongs_to đến nhiều model khác thông qua 1 association. Ví dụ ta có model notifications làm nhiệm vụ lưu thông báo cho cả model apply và model job
class Notification < ApplicationRecord
belongs_to :event, polymorphic: true
end
class Apply < ApplicationRecord
has_many :notifications, as: :event
end
class Job < ApplicationRecord
has_many :notifications, as: :event
end
Trường hợp này table notification sẽ có 2 field event_type và event_id.
- lấy các thông báo của apply:
@apply.notifications
- lấy các thông báo của job:
@job.notifications
- Ở đây xuất hiện thêm option as, trong trường hợp này nó giúp xác định điều kiện where trong câu lệnh sql sinh ra
SELECT `notifications`.* FROM `notifications` WHERE `notifications`.`deleted_at` IS NULL AND `notifications`.`event_id` = 2 AND `notifications`.`event_type` = 'Apply'
Kết luận
Trong bài viết này mình đã giới thiêu một số association cũng như các options liên quan, mong nó sẽ có ích với các bạn
Tài liệu tham khảo
http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
(TO BE CONTINUES)
All rights reserved