Mối quan hệ đa hình trong Ruby on Rails (Polymorphic relationships)
Polymorphic relationships là một chủ đề bạn sẽ hầu như không đề cập suy nghĩ tới trừ khi bạn thực sự cần chức năng đó. Polymorphic relationship là nơi một mô hình có thể thuộc về nhiều mô hình khác trên một association. Ví dụ điển hình về điều này là bạn có nhiều thứ có thể được comment, ví dụ ...
Polymorphic relationships là một chủ đề bạn sẽ hầu như không đề cập suy nghĩ tới trừ khi bạn thực sự cần chức năng đó.
Polymorphic relationship là nơi một mô hình có thể thuộc về nhiều mô hình khác trên một association.
Ví dụ điển hình về điều này là bạn có nhiều thứ có thể được comment, ví dụ như một dự án, một tác vụ hoặc một tệp đính kèm...
Trong mỗi trường hợp, một comment nó có ý nghĩa chỉ có một model comment duy nhất.
May mắn thay, Rails cho xây dựng Polymorphic chức năng thực sự rất dễ dàng!
Hãy tưởng tượng mình đang xây dựng ứng dụng Quản lý dự án cho phép người dùng quản lý dự án, nhiệm vụ và tệp đính kèm của mình.
Đây là ứng dụng hợp tác nên do đó đồng nghiệp của người dùng có thể nhận xét về dự án, nhiệm vụ và tệp đính kèm. Điều này có nghĩa là chúng ta cần phải có một model Comment, nhưng các dự án, nhiệm vụ và các mô hình Tệp đính kèm đều có khái niệm giống nhau về "comment" vì vậy mình cần liên kết comment với ba kiểu mô hình khác nhau!
Polymorphic relationship là nơi một mô hình có thể thuộc nhiều mô hình trên một liên kết đơn lẻ.
Trong trường hợp này, comment sẽ thuộc về một cái gì đó, nhưng nó không thực sự quan trọng nếu nó là một dự án, một công việc, hoặc một tập tin đính kèm...
Tiếp theo mình sẽ cho một ví dụ: Tạo model và migration Điều đầu tiên chúng ta cần làm là sử dụng máy phát Rails để tạo model và migrate mô hình Comment.
Chạy lệnh sau trong Terminal: bin/rails g model Comment body:text commentable:references{polymorphic} bây giờ sẽ tạo follow migration: null
class CreateComments < ActiveRecord::Migration def change create_table :comments do |t| t.text :body t.references :commentable, polymorphic: true, index: true t.timestamps null: false end end end
Định nghĩa tham chiếu sẽ tự động tạo các cột được gọi là commentable_type và commentable_id. Bạn không cần phải lo lắng về các cột này vì Rails sẽ tự động tạo cho chúng ta. Xác định Associations Bây giờ chúng ta đã di chuyển cho bảng comment tại chỗ, chúng ta có thể bắt đầu kết hợp các model để được "comment" Đầu tiên chúng ta sẽ xem xét lớp Comment đã được tạo ra bởi Rails:
class Comment < ActiveRecord::Base belongs_to :commentable, polymorphic: true end
Như bạn thấy, lớp này có một liên kết đa hình đơn lẻ. Bất cứ khi nào bạn có một ví dụ bình luận cụ thể, bạn không cần phải quan tâm đến người đó thuộc về ai. Để có được parent model, bạn chỉ cần gọi mối quan hệ comment:
comment = Comment.first comment.commentable
Tiếp theo, bạn có thể thêm các association để mỗi mô hình nên được "comment"
class Project < ActiveRecord::Base has_many :comments, as: :commentable end
class Task < ActiveRecord::Base has_many :comments, as: :commentable end
class Attachments < ActiveRecord::Base has_many :comments, as: :commentable end
Bây giờ mỗi model này sẽ có ý kiến kết hợp. Bạn có thể thêm comment như bạn với bất kỳ association Rails thông thường nào
project = Project.find(1) project.comments << Comment.new(body: "Project one")
task = Task.find(2) task.comments << Comment.new(body: "Task one")
attachment = Attachment.find(3) attachment.comments << Comment.new(body: "Attachment one")
Single Table Inheritance(STI) thường được so sánh với Polymorphic Association. Đó cũng là một lựa chọn tương đối tốt so với Polymorphic Association tùy vào từng trường hợp. STI sử dụng cơ chế thừa kế tương tự như ActiveRecord::Base. Ví dụ :
class StaffAssistant < ActiveRecord::Base class Comment < StaffAssistant class Message < StaffAssistant
Trong trường hợp này ta sẽ có một sơ đồ quan hệ khác với Polymorphic Association STI yêu cầu bạn phải tạo ra các class tương ứng để khai báo quan hệ. Bạn phải viết nhiều dòng code hơn và phức tạp hơn sơ với Polymorphic Association
Trên đây là một số kiến thức về Polymorphic. Cảm ơn mọi người đã theo dõi bài viết. Mình cũng chỉ hiểu biết nông cạn, mong mọi người góp ý để bài viết hoàn thiện hơn. Xin cám ơn.