如何通过“has_many”关联获取数据?

Posted

技术标签:

【中文标题】如何通过“has_many”关联获取数据?【英文标题】:How to fetch data through "has_many" associations? 【发布时间】:2014-09-18 09:12:37 【问题描述】:

我有以下模型结构:

class User < ActiveRecord::Base
  has_many :favorites
end
class Favorite < ActiveRecord::Base
  belongs_to :user
  belongs_to :company
end
class Color < ActiveRecord::Base
  belongs_to :company
end
class Company < ActiveRecord::Base
  has_many :colors
  has_many :favorities
end

这意味着一家公司有多种颜色。每个用户都可以收藏一家公司(然后我可以打印出相应公司提供的每种颜色)。

但我正在尝试显示我收藏的公司提供的所有颜色。

我试过这样:

favorited_colors = current_user.favorites.colors

undefined method `colors' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Favorite:0x007fe037da01f0>

favorited_colors = current_user.favorites.companies.colors

undefined method `companies' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Favorite:0x007fe038ce8db0>

除了通过 each 循环遍历所有收藏的公司并将所有颜色保存到数组中之外,还有其他方法可以从收藏的公司获取所有颜色的列表吗?

谢谢

【问题讨论】:

你没有用户和公司之间的联系,也没有用户和颜色之间的联系。因此,不,没有办法得到你正在尝试的东西 【参考方案1】:

这应该可以从 rails 3.1 开始:

class User
  has_many :favorites
  has_many :companies, :through => :favorites
  has_many :favorit_colors, :through => :companies
end

然后

favorited_colors = current_user.favorit_colors

不过,这未经测试。

【讨论】:

【参考方案2】:

收藏

您遇到的问题是您在集合对象上调用 companies 方法

这里的问题是您只能在对象的单个实例上调用方法。您看到的错误很好地证明了这一点:

undefined method `companies' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Favorite:0x007fe038ce8db0>

应该尝试使其工作的方式是调用以下内容:

current_user.favorites.each do |favourite|
    = favourite.colors
end

我了解您想要实现的目标,所以让我给您一些想法:


关联扩展

Rails 有一个名为ActiveRecord Association Extensions 的功能,它可以让您提供所需的功能:

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :favorites do
      def colors
         # Business logic for colours here
      end
   end
end

现在这是完全未经测试的。但是,我对 Rails 的这一深层部分有经验,因此我知道您将使用以下数据集:

proxy_association.owner 返回关联所属的对象。 proxy_association.reflection 返回描述关联的反射对象。 proxy_association.target 返回 belongs_to 或 has_one 的关联对象,或关联对象的集合 has_many 或 has_and_belongs_to_many。

由此,您将能够根据您希望显示的colors 构造一个数组/对象:

has_many :favorites do
  def colors #totally untested
    colors = 
    favorites = proxy_association.target 

    favorites.each do |favorite|
       favorite.company.colors.each do |color|
         colors << color
       end
    end

    return colors
  end
end

【讨论】:

以上是关于如何通过“has_many”关联获取数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在has_many中获取模型的属性:通过Rails 5中的关联

has_many 与非传统数据模型的关联

如何通过关联在 has_many 中使用回调?

使用 has_many 时如何创建关联模型的实例:通过关联

如何通过 has_many 关联在 FactoryBot 中设置工厂

在 has_many 关联中添加数据