STI and Polymorphic Associations
Bài đăng này đã không được cập nhật trong 7 năm
STI và Polymorphic Associations là những cách thông thường áp dụng để kết nối giữa hai bảng dựa trên một điều kiện nào đó. Giả sử chúng ta có một bảng trong database được gọi là comment
, và chúng ta có thể có comment cho nhiều loại ví dụ như comments cho một video, hay một status hay một bức ảnh đại diện,.. Vì vậy khi tuân thủ theo DRY khi thiết kế database, chúng ta có thể nghĩ đến quan hệ giữa bảng comment với các video, status, hay ảnh đại diện ở trên.
Ở phiến diện database, chúng ta nên có hai trường trong bảng comment
, một trường định nghĩa kiểu của comment(type) để phân biệt comment cho video hay comment status, một trường sẽ lưu id của video hay status mà nó trỏ tới.
Còn đối với trong rails, có 2 cách để định nghĩa kiểu quan hệ trên giữa các model trên:
STI - Single Table Inheritance
Đối với STI, bạn sẽ tạo một bảng comment
với model tương ứng là class Comment
. Sẽ có 2 class thêm vào tương ứng là VideoComment
và StatusComment
được thừa kế từ class Comment
.
Nếu chúng ta nhìn vào bảng comment, chúng ta sẽ thấy rằng mỗi một class sẽ tự động lưu lại thông tin trường type
là "video"
và "status"
. Còn một trường source_id
sẽ lưu id của video
hoặc status
tương ứng với nó.
Định nghĩa của các class sẽ như sau:
class Comment < ActiveRecord::Base
end
class VideoComment < Comment
belongs_to :video, :foreign_key => "source_id"
end
class StatusComment < Comment
belongs_to :status, :foreign_key => "source_id"
end
Polymorphic Association
Kể từ rails 1.1, chúng ta có thể tạo kiểu quan hệ trên theo polymorphic association định nghĩa. Với polymorphic association, trong bảng comment
chúng ta sẽ có 2 trường là commentable_type
và commentable_id
thay vì type
vào source_id
như STI ở trên. Trường commentable_type
sẽ lưu tên class mà comment đó quan hệ tới là "Video"
hay "Status"
, còn commentable_id
sẽ lưu id của video/status tương ứng với nó.
Định nghĩa của các class sẽ như sau:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Video < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Status < ActiveRecord::Base
has_many :comments, :as => :commentable
end
REFS
All rights reserved