Ruby on rails 引发ActiveRecord::回滚并因此失去嵌套的属性值

Ruby on rails 引发ActiveRecord::回滚并因此失去嵌套的属性值,ruby-on-rails,ruby,activerecord,Ruby On Rails,Ruby,Activerecord,一般来说,我试图批量验证一组对象,我需要保存它们以执行唯一性验证。然后我回滚需要保存以进行唯一性验证的对象 这是批量导入UI所必需的,在批量导入UI中,我希望在用户选择持久化数据之前通知用户数据中的问题 这种方法似乎失败了,因为对象在第二次保存时正在丢失其嵌套属性。因此,在第二次保存对象时,MySQL/SQlite会正确地告诉我列为null 以下是一个例子: ActiveRecord::Schema.define do create_table :posts, force: true do

一般来说,我试图批量验证一组对象,我需要保存它们以执行唯一性验证。然后我回滚需要保存以进行唯一性验证的对象

这是批量导入UI所必需的,在批量导入UI中,我希望在用户选择持久化数据之前通知用户数据中的问题

这种方法似乎失败了,因为对象在第二次保存时正在丢失其嵌套属性。因此,在第二次保存对象时,MySQL/SQlite会正确地告诉我列为null

以下是一个例子:

ActiveRecord::Schema.define do
  create_table :posts, force: true do |t|
    t.string :title
  end

  create_table :comments, force: true do |t|
    t.text :body, null: false
    t.integer :post_id
  end
end

class Post < ActiveRecord::Base
  has_many :comments
  validates :title, uniqueness: true
  accepts_nested_attributes_for :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

posts = [Post.new(title: "Title", comments_attributes: [{ body: "Comment" }])]

ActiveRecord::Base.transaction do
  posts.each do |p|
    p.save # This saves fine
    # Collecting validation errors here for presentation purposes
  end
  raise ActiveRecord::Rollback
end

# Now the comment attributes seem to be gone and
# Mysql is raising an error because the 'body' column is null
posts.each { |p| p.save }
ActiveRecord::Schema.define do
创建|表:posts,force:true do | t|
t、 字符串:标题
结束
创建表格:注释,强制:真do | t|
t、 text:body,null:false
t、 整数:post_id
结束
结束
类Post
我在这里有一个完全可运行的测试用例:


有办法解决这个问题吗?我想我的问题可以归结为,在用户决定继续并真正保留更改之前,必须执行唯一性验证来告诉用户重复项。

您不需要保存并回滚Post记录来验证唯一性。您可以直接调用
post.valid?
,所有验证(包括唯一性验证)都将运行

而不是

ActiveRecord::Base.transaction do
  posts.each do |p|
    p.save # This saves fine
    # Collecting validation errors here for presentation purposes
  end
  raise ActiveRecord::Rollback
end
照办

posts.each(&:valid?)

我刚刚对它进行了测试,看起来嵌套记录不受此方法的影响。

不幸的是,唯一性验证只会将新记录与已持久化的记录进行比较。看见所以,当我有一系列两篇标题相同的未保存帖子时,它不会告诉我,因为它们都没有被保存。啊,我现在明白了。单个验证取决于集合的其余部分。这使得这有点困难。:/AR仅支持单行插入。。。我看到的唯一好的选择是在AR之外编写一些自定义检查来检查整个posts数组。这里唯一需要检查的是,在运行post之前,所有标题都是唯一的。每个(&:valid?)。在任何情况下,我都不鼓励通过AR事务进行验证。如果你喜欢冒险,你也可以查看一些批量导入的gem,比如activerecord导入,看看它们是否支持这样的东西。