gpt4 book ai didi

ruby-on-rails - 防止 Rails 5 中重复的 has_many 记录

转载 作者:行者123 更新时间:2023-11-29 13:17:25 25 4
gpt4 key购买 nike

给定以下模型:

class Client < ApplicationRecord
has_many :preferences
validates_associated :preferences
accepts_nested_attributes_for :preferences
end

class Preference < ApplicationRecord
belongs_to :client
validates_uniqueness_of :block, scope: [:day, :client_id]
end

在创建客户端期间创建一批首选项时,我仍然能够创建具有重复日期*的首选项。这(似乎)是因为在运行 validates_uniqueness_of 验证时 client_id 外键不可用。 (*我有一个索引可以防止重复项被保存,但我想捕获错误,并在它到达数据库之前返回一个用户友好的错误消息。)

有什么方法可以通过 ActiveRecord 验证来防止这种情况发生吗?

编辑:This appears to be a known issue .

最佳答案

当您批量插入时,没有一种非常干净的方法可以通过 AR 验证来执行此操作,但您可以通过以下步骤手动执行此操作。

  1. 使用 Postgresql VALUES 列表对数据库进行单个查询以加载任何可能重复的记录。
  2. 比较您将要批量创建的记录并剔除任何重复项
  3. 手动生成并返回错误信息

第一步看起来有点像这样

# Build array of uniq attribute pairs we want to check for
uniq_attrs = new_collection.map do |record|
[
record.day,
record.client_id,
]
end

# santize the values and create a tuple like ('Monday', 5)
values = uniq_attrs.map do |attrs|
safe = attrs.map {|v| ActiveRecord::Base.connection.quote(v)}
"( #{safe.join(",")} )"
end

existing = Preference.where(%{
(day, client_id) in
(#{values.join(",")})
})

# SQL Looks like
# select * from preferences where (day, client_id) in (('Monday',5), ('Tuesday', 3) ....)

然后您可以获取集合 existing 并在步骤 2 和 3 中使用它来提取重复项并生成错误消息。

当我需要这个功能时,我通常会把它作为我类(class)之外的一个 self 方法,比如

class Preference < ApplicationRecord

def self.filter_duplicates(collection)
# blah blah blah from above

non_duplicates = collection.reject do |record|
existing.find do |exist|
exist.duplicate?(record)
end
end

[non_duplicates, existing]

end

def duplicate?(record)
record.day == self.day &&
record.client_id = self.client_id
end
end

关于ruby-on-rails - 防止 Rails 5 中重复的 has_many 记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47034353/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com