Postgres / ActiveRecord错误?

时间:2018-04-02 18:24:26

标签: ruby-on-rails postgresql activerecord

我在ActiveRecord中有以下方法,还有一些简化的类/关联:

class LineItem < ApplicationRecord
  has_many :line_item_parts

  def media
    best = line_item_parts.detect do |part|
      part.part.medias.any?
    end
    best_media = best && best.part.medias.first
    best_media || product.medias.first
  end
end

class LineItemPart < ApplicationRecord
  belongs_to :line_item
  belongs_to :part
end

class Part < ApplicationRecord
  belongs_to :product
  has_many :medias
end

class Media < ApplicationRecord
  belongs_to :product
  belongs_to :part, optional: true
end

在binding.pry中的服务器上运行时,我会执行以下操作:

> line_item.media #=> nil
> line_item.media #=> <Media: ...>

它有时会在第一次返回nil,但是当我再次运行它时它总是返回正确的对象。我在第一次运行的日志中看到以下行:

  Products::Media Exists (1.0ms)  SELECT  1 AS one FROM "products_medias" WHERE "products_medias"."part_id" = $1 LIMIT $2  [["part_id", 472], ["LIMIT", 1]]

手动执行查询会按预期返回Media结果。在第二次运行中,它是相同的查询,但使用AR CACHE,但在第二次运行时,它返回正确的结果(非零媒体对象)。

这怎么可能?这是一个ActiveRecord错误吗?我甚至不知道从哪里开始用谷歌搜索这样的东西。

宝石:

  • Rails(5.1.5)
  • pg(0.21.0)

Postgres版本:psql (PostgreSQL) 10.2 (Debian 10.2-1.pgdg90+1)

在Docker for Mac中运行。

1 个答案:

答案 0 :(得分:1)

我没有看到错误,但看起来无论如何都会导致多次查询。我可以建议一个替代方案吗?

 def media
   best_media = Media
      .joins(parts: [line_item_parts: :line_items])
      .where('line_items.id = ?', id)
      .first
   best_media || product.medias.first
 end

如果您希望直接使用关联,可以尝试在枚举器方法之前添加.to_a,以便明确地对结果进行操作。

def media
  best = line_item_parts.to_a.detect do |lip|
    lip.part.medias.any?
  end
  best_media = best && best.part.medias.first
  best_media || product.medias.first
end