2011-01-08 26 views
138

Xin hãy giúp tôi trong việc tìm hiểu :source tùy chọn has_one/has_many :through hiệp hội. Lời giải thích về Rails API có ý nghĩa rất ít đối với tôi.Hiểu: Tùy chọn nguồn has_one/has_many qua của Rails

"Chỉ định tên gắn nguồn được sử dụng bởi has_many:through => :queries. Chỉ sử dụng nó nếu tên không thể được suy ra từ các hiệp hội . has_many :subscribers, :through => :subscriptions sẽ nhìn cho một trong hai :subscribers hoặc :subscriber trên Subscription, trừ một :source được đưa ra. "

Trả lời

178

Đôi khi, bạn muốn sử dụng các tên khác nhau cho các liên kết khác nhau. Nếu tên bạn muốn sử dụng cho liên kết trên mô hình không giống với xác nhận trên mô hình :through, bạn có thể sử dụng :source để chỉ định.

Tôi không nghĩ đoạn trên là nhiều hơn rõ ràng hơn so với đoạn trong tài liệu, vì vậy đây là một ví dụ. Giả sử chúng tôi có ba mô hình, Pet, DogDog::Breed.

class Pet < ActiveRecord::Base 
    has_many :dogs 
end 

class Dog < ActiveRecord::Base 
    belongs_to :pet 
    has_many :breeds 
end 

class Dog::Breed < ActiveRecord::Base 
    belongs_to :dog 
end 

Trong trường hợp này, chúng tôi đã chọn không gian tên các Dog::Breed, bởi vì chúng tôi muốn truy cập Dog.find(123).breeds như một hiệp hội tốt đẹp và thuận tiện.

Bây giờ, nếu bây giờ chúng tôi muốn tạo liên kết has_many :dog_breeds, :through => :dogs trên Pet, chúng tôi đột nhiên gặp sự cố. Rails sẽ không thể tìm thấy một hiệp hội :dog_breeds trên Dog, vì vậy Rails không thể nào biết Dog sự liên kết bạn muốn sử dụng. Nhập :source: Rails

class Pet < ActiveRecord::Base 
    has_many :dogs 
    has_many :dog_breeds, :through => :dogs, :source => :breeds 
end 

Với :source, chúng ta đang nói đến nhìn cho một hiệp hội gọi là :breeds trên Dog mô hình (như đó là mô hình sử dụng cho :dogs), và sử dụng.

+2

Tôi nghĩ rằng bạn có nghĩa là cho lớp học cuối cùng của bạn Động vật được gọi là lớp Pet, chỉ là một lỗi đánh máy tôi tin. – Kamilski81

+0

Cảm ơn, hãy bắt! – vonconrad

+2

Trong ví dụ trên, nên liên kết trong 'Dog' là' has_many: breed' thay vì ': breeds' và sau đó là': source' là ': breed' singular, để đại diện cho tên model, thay vì': giống 'đại diện cho tên bảng? Ví dụ. 'has_many: dog_breeds,: through =>: chó,: source =>: breed' (không có' s' suffixing ': breed')? – LazerSharks

152

Hãy để tôi mở rộng ví dụ:

class User 
    has_many :subscriptions 
    has_many :newsletters, :through => :subscriptions 
end 

class Newsletter 
    has_many :subscriptions 
    has_many :users, :through => :subscriptions 
end 

class Subscription 
    belongs_to :newsletter 
    belongs_to :user 
end 

Với mã này, bạn có thể làm điều gì đó như Newsletter.find(id).users để có được một danh sách các thuê bao của bản tin. Nhưng nếu bạn muốn trở thành rõ ràng hơn và có khả năng gõ Newsletter.find(id).subscribers thay vào đó, bạn phải thay đổi lớp Bản tin này:

class Newsletter 
    has_many :subscriptions 
    has_many :subscribers, :through => :subscriptions, :source => :user 
end 

Bạn đang đổi tên Hiệp hội users-subscribers. Nếu bạn không cung cấp :source, Rails sẽ tìm kiếm một liên kết được gọi là subscriber trong lớp Đăng ký. Bạn phải nói điều đó để sử dụng liên kết user trong lớp Đăng ký để tạo danh sách người đăng ký.

+1

Cảm ơn.Rõ ràng hơn nhiều, – Anwar

+2

lưu ý rằng, nên sử dụng tên mẫu số ít trong ': source =>', không phải số nhiều. Vì vậy, ': người dùng' là sai,': người dùng' là chính xác – Anwar

+0

Đây là câu trả lời hay nhất !, hãy để tôi nhấn mạnh phần này: "Bạn đang đổi tên người dùng thành người đăng ký. Nếu bạn không cung cấp: nguồn, Rails sẽ tìm kiếm một liên kết được gọi là người đăng ký trong lớp Đăng ký. " –

5

Câu trả lời đơn giản nhất:

Là tên của mối quan hệ trong bảng ở giữa.

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