首页 > 解决方案 > 如果记录有效,则在签入时停止加载关联模型

问题描述

我有一个名为 message 的对象,它属于运营商、公司、国家

我允许通过 CSV 批量插入用户 - 我之前想做的是在导入之前确保每一行都是有效的(这样我可以在开始导入之前通知用户)

所以我创建了一个循环所有新数据并执行 Message.new(PARAMS_IN_HERE) 然后调用.valid?它的方法,这很好并且达到了预期的结果。

但是,当我查看日志时,我会看到大量这样的查询

  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.3ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Company Load (0.2ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Country Load (0.2ms)  SELECT  "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Carrier Load (0.2ms)  SELECT  "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]

这显然是非常浪费的,因为它多次执行相同的查询。有没有办法让rails在需要查找/或阻止它发生时缓存值/预加载?

这就是我的消息类的样子

class Message < ApplicationRecord
  belongs_to :company
  belongs_to :carrier
  belongs_to :country

  before_validation :set_default_details, on: :create

  private

  def set_default_details
    if self.user.present?
      self.carrier_id = self.user.company.tariff.carrier_id
      self.country_id = self.user.country_id
      self.company_id = self.user.company_id
    end
  end
end  

标签: ruby-on-railsrubyactiverecord

解决方案


您的验证引用self.user,但未在您发布的模型片段中定义。

如果您的验证涉及关联对象,例如self.company,请将这些对象提供给构造函数:Message.new(company: company)而不是Message.new(company_id: company.id). 如有必要,提前查找所有相关对象 - 这可以通过单个查询完成 - 并将 id -> 对象映射存储在哈希中。

同样,您可以使用验证引用字段,company_id但最好在任何地方使用关联对象。


推荐阅读