52

Rails có liên kết has_one :through giúp thiết lập liên kết một-một với mô hình thứ ba bằng cách thực hiện mô hình thứ hai. Việc sử dụng thực sự điều đó ngoài việc tạo ra một liên kết phím tắt là gì, nếu không sẽ là một bước phụ.Rails has_one: thông qua liên kết

Lấy ví dụ này từ Rails guide:

class Supplier < ActiveRecord::Base 
    has_one :account 
    has_one :account_history, :through => :account 
end 

class Account < ActiveRecord::Base 
    belongs_to :supplier 
    has_one :account_history 
end 

class AccountHistory < ActiveRecord::Base 
    belongs_to :account 
end 

có thể cho phép chúng ta làm điều gì đó như:

supplier.account_history 

mà nếu không sẽ đạt được như:

supplier.account.history 

Nếu đó là chỉ để truy cập đơn giản sau đó về mặt kỹ thuật có thể có một hiệp hội một-một t kết nối một mô hình với một số mô hình thứ n thông qua các mô hình n-1 để truy cập dễ dàng hơn. Có bất cứ điều gì khác với nó mà tôi đang thiếu bên cạnh các phím tắt?

Trả lời

47
  1. logic, OK nó có vẻ một chút yếu cho điều này nhưng nó sẽ là hợp lý để nói rằng "Tôi có một nhà cung cấp có một tài khoản với tôi, tôi muốn nhìn thấy toàn bộ lịch sử tài khoản này nhà cung cấp ", do đó, nó có ý nghĩa đối với tôi để có thể truy cập lịch sử tài khoản từ nhà cung cấp trực tiếp.

  2. Hiệu quả, điều này đối với tôi là lý do chính tôi sẽ sử dụng :through, đơn giản chỉ vì này đưa ra một tuyên bố tham gia thay vì gọi nhà cung cấp, và sau đó tài khoản, và sau đó account_history. nhận thấy số lượng cuộc gọi cơ sở dữ liệu?

    • sử dụng :through, 1 cuộc gọi để có được nhà cung cấp, 1 cuộc gọi để có được account_history (đường ray tự động sử dụng :join để lấy thông qua tài khoản)

    • sử dụng sự kết hợp thông thường, 1 cuộc gọi để có được nhà cung cấp, 1 cuộc gọi để nhận được tài khoản, và 1 cuộc gọi để có được account_history

đó là những gì tôi nghĩ =) hy vọng nó sẽ giúp!

+2

Tôi nghĩ đối số lôgic là khá hợp lệ. Nghe có vẻ tự nhiên hơn, hãy cho tôi biết lịch sử tài khoản của nhà cung cấp này và không phải là lịch sử tài khoản của nhà cung cấp. Rất tinh tế nhưng vẫn dễ nhớ hơn khi xem xét triết lý của Ruby/Rails về các câu thay vì mã. Tôi biết chúng ta có thể thấy các truy vấn DB thực tế đang được ban hành nhưng Rails có chỉ định cách thức các cuộc gọi phương thức này sẽ dịch sang SQL không? – Anurag

+10

Điều này cũng tránh vi phạm Luật Demeter. –

+2

@TomCrayford, tôi thực sự không thấy nó như thế nào. Điều này không làm cho mối quan hệ ít trực tiếp hơn? –

6
  • Inverse hiệp hội: xem xét tình hình kinh điển do người dùng thành viên nhóm. Nếu người dùng có thể là thành viên trong nhiều nhóm, thì một nhóm có nhiều thành viên hoặc người dùng và người dùng có nhiều nhóm. Nhưng nếu người dùng chỉ có thể là thành viên trong một nhóm, nhóm vẫn có nhiều thành viên: class User has_one :group, :through => :membership nhưng class Group has_many :members, :through => memberships. Mô hình trung gian membership hữu ích để theo dõi mối quan hệ nghịch đảo.

  • Khả năng mở rộng: một mối quan hệ has_one :through dễ dàng có thể được mở rộng và kéo dài đến một mối quan hệ has_many :through

7

Tôi ngạc nhiên không ai đề cập đến Hiệp hội Objects.

Một mối quan hệ has_many (hoặc has_one) :through tạo điều kiện cho việc sử dụng các association object pattern đó là khi bạn có hai thứ liên quan đến nhau, và đó là mối quan hệ riêng của mình có thuộc tính (ví dụ một ngày khi hiệp hội đã được thực hiện hoặc khi nó hết hạn).

Đây là considered by some là giải pháp thay thế tốt cho trình trợ giúp has_and_belongs_to_many ActiveRecord. Lý do đằng sau điều này là rất có thể bạn sẽ cần phải thay đổi bản chất của hiệp hội hoặc thêm vào nó, và khi bạn là một vài tháng vào một dự án, điều này có thể rất đau đớn nếu mối quan hệ ban đầu được thiết lập a has_and_belongs_to_many (liên kết thứ hai đi vào một số chi tiết). Nếu nó được thiết lập ban đầu bằng cách sử dụng mối quan hệ has_many :through thì một vài tháng trong dự án sẽ dễ dàng đổi tên mô hình tham gia hoặc thêm thuộc tính vào mô hình, giúp các nhà phát triển dễ dàng hơn trong việc đáp ứng các yêu cầu thay đổi. Lập kế hoạch thay đổi.

Các vấn đề liên quan