【问题标题】:Rails Active Record: How to join three tables?Rails Active Record:如何连接三个表?
【发布时间】:2018-01-31 11:50:47
【问题描述】:

我有如下三张表:

广告商模型:

class Advertiser < ActiveRecord::Base
 has_many :advertisers_account_groups

AdvertisersAccountGroup 模型

class AdvertisersAccountGroup < ActiveRecord::Base
 belongs_to :advertiser
 belongs_to :v2_account_account_group, class_name: 'V2Account::AccountGroup', foreign_key: 'account_group_id'

我想知道v2_account_account_groups属于哪个广告商 想得到v2_account_account_groups.name

期望的输出:

我尝试了什么;

Advertiser.where(media_type: "line").joins(advertisers_account_groups,v2_account_account_groups)

但它不起作用

【问题讨论】:

  • 输入是什么?是V2Account::AccountGroup 还是AdvertisersAccountGroup

标签: mysql ruby-on-rails activerecord


【解决方案1】:

在我看来,您当前的设置使用AdvertisersAccountGroup 作为连接表;因此,我建议使用has_many :through 关联。

为此,您只需按如下方式切换模型:

class Advertiser < ActiveRecord::Base
  has_many :v2_account_account_groups, through: :advertisers_account_groups
  has_many :advertisers_account_groups
  ...
end

class V2Account::AccountGroup < ActiveRecord::Base
  has_many :advertisers, through: :advertisers_account_groups
  has_many :advertisers_account_groups
  ...
end

class AdvertisersAccountGroup < ActiveRecord::Base
  belongs_to :advertiser
  belongs_to :v2_account_account_group, class_name: 'V2Account::AccountGroup', foreign_key: 'account_group_id'
  ...
end

这将允许您根据需要查询advertiser,即advertiser.v2_account_account_groups

但是,这种关联在广告商和 v2 帐户组之间是多对多的,因此,您将无法调用 advertiser.v2_account_account_groups.name,因为 advertiser.v2_account_account_groups 返回的是集合而不是单个记录。

您可以使用advertiser.v2_account_account_groups.map(&amp;:name)(获取所有组名称的数组)或advertiser.v2_account_account_groups.first&amp;.name,但如果广告客户应该只有一个 v2 帐户组,您可能需要重新构建数据。

这是否有意义并且听起来像您正在寻找的东西?如果您有任何问题,请告诉我。


编辑:

根据您的评论,我认为您应该能够构造如下查询:

Advertiser.includes(advertiser_account_groups: : v2_account_account_group)
          .where(advertiser_account_groups: { v2_account_groups: { name: "something" } })

这听起来像您正在寻找的吗?

有几点需要注意:

  • 在引用includes 中的关联时,您希望使用关联名称
  • 然而,将这些插入where 子句时,您需要使用完整的表名,因为它们在数据库中(可通过Model.table_name 搜索)

另外,在您的评论中,您提到了添加media_type: "line",下面还包括:

Advertiser.includes(advertiser_account_groups: : v2_account_account_group)
          .where(media_type: "line", advertiser_account_groups: { v2_account_account_groups: { name: "something" } })

在您的代码中构建它的最佳方式可能是作为广告商模型中的一个范围,例如:

scope :by_v2_group_name, -> (name) { includes(advertiser_account_groups: :v2_account_account_group)
                               .where(media_type: "line", advertiser_account_groups: { v2_account_account_groups: { name: "something" } }) }

scope :by_v2_group_name, (lambda do |name| 
  includes(advertiser_account_groups: :v2_account_account_group)
  .where(media_type: "line", advertiser_account_groups: { v2_account_account_groups: { name: "something" } })
end)

这样您就可以保持代码干净并调用Advertiser.by_v2_group_name("something")

让我知道您的进展情况,我们会根据需要进行处理 :)

【讨论】:

  • 谢谢,但我不想更改代码。我只想编写一个主动重新编码查询来查找哪个广告商属于哪个 v2_account_groups。一个广告客户可以属于多个v2_account_groups。例如,我想写 Advertiser.where(media_type: "line").joins(:v2_account_account_groups).where("something")
  • 感谢@RajSharma - 我已经扩展了我的答案以反映这一点。希望它有所帮助 - 如果您有任何问题或它在任何地方都不起作用(我无法测试它),请大声告诉我,我们会看看我们能解决什么问题。
  • 感谢您的回答。这对我很有帮助。
【解决方案2】:

仅当您不需要连接表的 模型 时,此答案才有意义 ads_account_gourps (如果您在该连接表上没有除 advertiser_idaccount_gourp_id 之外的任何额外属性 - 您通常不需要它)

虽然@SRack 的答案是使用has_many :through 关联,但我认为您可以使用简单的多对多关联(has_and_belongs_to_many),因为在您的图像中我可以看到连接表只有ids关联表(除非您确实需要 id 列 -> 在这种情况下,请使用 @SRack 的解决方案!)

class Advertiser < ActiveRecord::Base
  has_and_belongs_to_many :advertisers_account_groups

class AccountGroup < ActiveRecord::Base
  has_and_belongs_to_many :advertisers

然后你可以使用:

advertiser = Advertiser.first
advertiser.account_groups #to get account groups of that advertiser

反之亦然:

account_group = AccountGroup.first
account_group.advertisers # to get advertisers of that account group
  • @SRack 的评论是正确的!我把它改成了HABTM协会!

在这种情况下,您需要创建一个迁移来制作连接表:

rails g migration CreateJoinTableAdvertiserAccountGroup advertiser account_group

此表将仅包含关联的advertiser_idaccount_group_id

您无需创建模型并处理该表上的内容,rails 会为您填充该表。

【讨论】:

  • 我去了has_many :through,因为他在advertisers_account_group 上有一个id 列,他需要核对那个列才能使用多对多。我总是更喜欢has_many :through 协会,就像我读过的关于该主题/与我共事过的人的几乎所有内容(尽管很高兴在这里听到其他人的意见!)。另外,您不需要成为has_and_belongs_to_many 吗?没有提到 v2 组?
  • @SRack:在这种情况下你是对的。在这种情况下,habtm 需要建立多对多关系。
  • @SRack 是的,您对habtm 的看法是正确的。我刚刚发布了另一种方法来做他想做的事,我猜他的advertiser_account_group 中的id 并不是真的需要....
  • 但是 habtm 不适用于连接表上的 id 列...当您可以使用 has_many :through 时,IMO 似乎比杀死该列更值得:) 另外,您已经然后让 flex 根据需要使用连接表。
  • 我知道它没有那个id 专栏...。我编辑了我的答案并指定如果他需要那个id 专栏,他应该使用您的答案...跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多