+3

Mối quan hệ đa hình trong Ruby on Rails (Polymorphic relationships)

Giới thiệu

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!

Nội dung

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")

So sánh STIPolymorphic Association

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

Kết luận:

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.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí