迭代has_many时通过关联访问关联模型:通过关联
我有一种感觉,这是一个非常基本的问题,但由于某种原因,我被它困住了(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模型应该已经加载。我只是不知道如何正确访问正确的模型。有人可以帮助正确的语法?
其实加盟模式不会被加载尚未: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
模型内部代表团一些属性分别为contact
或user
。例如,这
class UserContact < ActiveRecord::Base
belongs_to :user
belongs_to :contact
delegate :name, to: :contact, prefix: true
end
将允许你写
uc.contact_name
首先,在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])
使用.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
的属性都可用。
谢谢,得到了这个工作。对于任何在将来遇到此问题的人来说,包含的正确语法是在.find之前:@user = User.includes(user_contacts:[:contact])。find(params [:id]) – Katie
Ahh,你是对的。 'find'不会返回'ActiveRecord :: Relation'。谢谢,我会解决它。 – Azolo