首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何重写这一行以避免"#<ActiveRecord::Associations::CollectionProxy []“错误?

如何重写这一行以避免"#<ActiveRecord::Associations::CollectionProxy []“错误?
EN

Stack Overflow用户
提问于 2019-11-19 21:50:22
回答 2查看 295关注 0票数 0

我有这些模特..。

代码语言:javascript
复制
class Administrator < ApplicationRecord
    ...
    has_many :locations


class Location < ApplicationRecord
    ...
    has_many :displays, :dependent => :destroy

我有这样的代码,它的目的是检索所有的显示,但必须符合某些标准.

代码语言:javascript
复制
  @displays = []
  current_user.locations.each do |location|
    @displays = (@displays + location.displays.where(:user => user).includes(:administrator)).uniq
  end

我想找一种巧妙的铁轨方法把上面的东西简化成一个班轮,所以我试了一下。

代码语言:javascript
复制
  @displays = current_user.locations.displays.where(:user => user).includes(:administrator).flatten.uniq

但这会导致一个错误

代码语言:javascript
复制
undefined method `displays' for #<ActiveRecord::Associations::CollectionProxy []>

有没有一种方法可以用一行重写我的独立块呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-19 23:53:44

您可以向Location模型中添加一个类方法,以实现您想要的结果。

代码语言:javascript
复制
class Location < ApplicationRecord
  has_many :displays, dependent: :destroy

  def self.displays
    Display.where(location_id: select(:id))
  end
end

它应该允许您使用:

代码语言:javascript
复制
@displays = current_user.locations.displays.where(user: user).includes(:administrator)

如果不想向模型中添加助手,则可以更改记录获取技术。

代码语言:javascript
复制
location_ids = current_user.locations.pluck(:id)
@displays = Display.where(location_id: location_ids, user: user).includes(:administrator)

对于一行,您可以简单地将上面的行合并在一起。然而,我会选择多行解决方案,因为这一行将变得相当长。

代码语言:javascript
复制
@displays = Display.where(location_id: current_user.locations.pluck(:id), user: user).includes(:administrator)

在这两个场景中,不需要对结果进行flatten或调用uniq

您可能希望将select(:id)替换为pluck(:id),反之亦然。区别在于select将创建一个子查询。虽然pluck首先只执行查询,但只获取位置ids,然后使用它们创建新的查询。这确实会产生一个额外的查询,但可能会更快,因为查询不那么复杂。

您还可以使用以下作用域而不是类方法:

代码语言:javascript
复制
scope :displays, -> { Display.where(location_id: select(:id)) }

我之所以使用类方法是因为定义/一致性的原因。让我引用GNU版的“国际英语合作词典”中的“范围”的定义

名词,目的;目的是达到或完成的目的;因此,最终的设计、目标或目的;意图;漂泊;目标。

从上面我们可以得出结论,作用域应该增加对当前作用域的限制,以缩小结果的目标。因此,作用域只应返回当前作用域的受限版本。由于displays返回了一个全新的作用域,并且产生了不同的记录( Display而不是Location的实例),所以我选择了一个类方法。(尽管用法相同。)

票数 1
EN

Stack Overflow用户

发布于 2019-11-19 21:52:22

你是在locations上给locations打电话,而不是打location

你可能在找这样的东西:

current_user.locations.joins(:displays).where(displays: { user: user }) ...

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58943353

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档