2016-08-23 103 views
0

我有一種感覺,這是一個非常基本的問題,但由於某種原因,我被它困住了(Rails新手),似乎無法找到答案(這可能是我沒有正確搜索)。迭代has_many時通過關聯訪問關聯模型:通過關聯

所以我有一個基本的has_many:通過這樣的關係:

class User < ApplicationRecord 
    has_many :contacts, through :user_contacts 

class Contact < ApplicationRecord 
    has_many :users, through :user_contacts 

在用戶/ show.html.erb我通過一個單一用戶的聯繫人迭代,如:

<% @user.contacts.each do |c| %> 
    <%= c.name %> 
<% end %> 

現在,在每個循環內部,我想訪問與給定用戶和聯繫人關聯的user_contact連接模型,以顯示created_at時間戳,該時間戳指示用戶何時建立了聯繫關係。

我知道我可以做一個UserContact.find調用,通過user_id和contact_id在數據庫中查找模型,但不知何故,這感覺是多餘的。如果我正確理解這是如何工作的(完全可能我不這樣做),當我從數據庫中加載給定用戶及其聯繫人時,user_contact模型應該已經加載。我只是不知道如何正確訪問正確的模型。有人可以幫助正確的語法?

回答

1

其實加盟模式不會被加載尚未:ActiveRecord的取through規範來構建它的SQL語句JOIN查詢正確Contact記錄,但有效只會實例化的。

假設你有一個UserContact模型,你可以做某事像這樣:

@user.user_contacts.includes(:contact).find_each do |uc| 
    # now you can access both join model and contact without additional queries to the DB 
end 

如果你想保留的東西可讀,而不與uc.contact.something弄亂你的代碼,你可以設置委託UserContact模型內部代表團一些屬性分別爲contactuser。例如,這

class UserContact < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :contact 
    delegate :name, to: :contact, prefix: true 
end 

將允許你寫

uc.contact_name 
1

首先,在has_many :things, through: :other_things條款是要去找other_things關係找到:things

把它看作是一種內置魔法的方法調用,使其在SQL查詢中具有高性能。因此,通過使用一個through條款你或多或少做這樣的事情:

def contacts 
    user_contacts.map { |user_contact| user_contact.contacts }.flatten 
end 

user_contacts的背景是完全喪失。

由於它看起來像user_contacts是一對一的連接。因爲你是新來的Rails值得一提的是加載這些記錄沒有N + 1查詢,你可以做這樣的事情在你的控制器

<% @user.user_contacts.each do |user_contact| %> 
    <%= user_contact.contact.name %> 
<% end %> 

另外::這將是更容易做這樣的事情

@user = User.includes(user_contacts: [:contacts]).find(params[:id]) 
+0

謝謝,得到了這個工作。對於任何在將來遇到此問題的人來說,包含的正確語法是在.find之前:@user = User.includes(user_contacts:[:contact])。find(params [:id]) – Katie

+0

Ahh,你是對的。 'find'不會返回'ActiveRecord :: Relation'。謝謝,我會解決它。 – Azolo

0

使用.joins.select這樣:

@contacts = current_user.contacts.joins(user_contacts: :users).select('contacts.*, user_contacts.user_contact_attribute_name as user_contact_attribute_name')

現在,裏面@contacts.each do |contact|循環,您可以撥打contact.user_contact_attribute_name

它看起來奇怪,因爲contact不具有user_contact_attribute_name,只有UserContact做,但查詢的.select部分將奇蹟般地提供給您的每個contact實例。

contacts.*部分告訴查詢使所有contact的屬性都可用。