Khám phá option “:inverse_of” trong Rails associations

Tram Ho

Bạn đã bao giờ nhìn thấy tùy chọn :inverse_of trên một liên kết và tự hỏi nó đã làm gì và tại sao nó lại ở đó?

Lần đầu tiên tôi nhìn thấy một thứ như vậy, nó có vẻ như là một tùy chọn không cần thiết. Vậy :inverse_of có tác dụng gì ?

Tối ưu hóa bộ nhớ khi tìm nạp các bản ghi được liên kết

Theo mặc định, các đối tượng được liên kết không trỏ đến cùng các đối tượng trong bộ nhớ. Ví dụ

Khi chúng ta gọi criminal.prison mà không có option :inverse_of, nó sẽ truy xuất vào cơ sở dữ liệu. Với :inverse_of, nếu chúng ta đã có prison đó trong bộ nhớ thì crime.prison sẽ chỉ đến cùng một prison.
Điều này giúp bạn tiết kiệm 1 lần tra cứu cơ sở dữ liệu khi đi từ Criminal đến Prison (từ 1 đến n trong quan hệ 1-n). Ví dụ nếu đi từ hướng khác

Liên kết trong model, liên quan đế bộ nhớ là các ràng buộc một chiều. :inverse_of về cơ bản cung cấp cho chúng ta các ràng buộc bộ nhớ hai chiều khi một trong các liên kết là :belong_to. Tối ưu hóa bộ nhớ không phải là điều duy nhất mà :inverse_of giúp bạn.
Tiếp theo, chúng ta sẽ xem xét hai trường hợp sử dụng liên quan đến việc tạo các bản ghi liên quan.

Tạo đối tượng và đối tượng con của nó thông qua accept_nested_attributes_for trong liên kết :has_many

Giả sử chúng ta có một quan hệ như hình dưới và, ta muốn tạo Prison và thêm nhiều Criminal

Nếu không có :inverse_of, đây là những gì xảy a khi chúng ta gửi form

Khi Rails lưu criminal, prison chưa được tạo vào cơ sở dữ liệu và do đó thiếu id. Đó là lý do khiến validates :prison, presence: true
trả về fail
Để điều này hoạt động, chúng ta cần có :inverse_of và kết quả là:

Tạo các đối tượng được liên kết has_many :through

Trường hợp bạn gặp sự cố khi bạn đang tạo một đối tượng được liên kết ở phía bên kia của has_many :through. Giả sử chúng ta có quan hệ n-n được khai báo như sau:

Nếu chúng ta muốn làm gì đó như:

Nếu không có inverse_of, ta nhận được:

criminal của chúng ta sẽ không có bất kỳ prisons nào vì sentence cần thiết không được tạo tự động.
Còn với inverse_of

Tuyệt vời, kết quả đã như chúng ta mong muốn

Tin tốt

Kể từ phiên bản 4.1, Rail sẽ tự động đặt option :inverse_of cho chúng ta. Trong ví dụ trên của chúng ta, với Criminal có liên kết :belongs_to với Prison, nó sẽ cố gắng suy ra nghịch đảo từ tên class – trong trường hợp này là :criminals dựa trên class Criminal. Chắc chắn điều này sẽ sai khi tên class không trùng khớp. Ví dụ, khi chúng ta sử dụng tùy chọn :class_name hoặc :foreign_key chúng ta phải đặt :inverse_of một cách chính xác, vì vậy bạn vẫn nên biết cách hoạt động của :inverse_of.

Tài liệu tham khảo

https://www.viget.com/articles/exploring-the-inverse-of-option-on-rails-model-associations/

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo