2017-01-10 8 views
1

一般的に、オブジェクトの束を一括して検証しようとしており、一意性検証を実行するためにそれらを保存する必要があります。次に、一意性検証のために保存する必要のあるオブジェクトをロールバックします。ActiveRecord :: Rollbackを生成し、結果としてネストされた属性値を破棄します。

これは、データを永続化するオプションを使用する前に、データの問題についてユーザーに通知したいバッチインポートUIに必要です。

2回目の保存時にオブジェクトのネストされた属性が失われているため、アプローチが失敗したようです。だから、オブジェクトを2度保存すると、MySQL/SQliteはカラムがヌルであると正当に伝えます。ここで

は一例です:

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 } 

私はここで完全に実行可能なテストケースを持っている:https://gist.github.com/phansch/ab172e4b8cadf24f1e6508a0555e465c

はこの周りのいくつかの方法はありますか?私の問題は、ユーザーが前進して実際に変更を維持することを決定する前に、重複の検証を実行して重複についてユーザーに伝えなければならないことになります。

答えて

0

一意性を検証するためにポストレコードを保存してからロールバックする必要はありません。 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?) 

を行い、私はちょうどそれをテストして、ネストされたレコードは、このアプローチに影響されないように見えます。

+0

残念ながら、一意性検証では、新しいレコードと、すでに永続化されているものとのみ比較されます。 http://guides.rubyonrails.org/active_record_validations.html#uniquenessを参照してください。だから私は同じタイトルを持っている2つの未保存の投稿の配列を持っているとき、それは永続化されていないので、私には言いません。 –

+0

ああ、私は今理解しています。個々のバリデーションは、コレクションの残りの部分を条件にしています。これは少し難しくなります。 :/ ARは単一行の挿入だけをサポートしています...私が見る唯一の良いオプションは、ARの外にいくつかのカスタムチェックを書いて、ポスト配列全体をチェックすることです。ここでチェックするのは、posts.each(&:valid?)を実行する前にすべてのタイトルが一意であることだけです。いずれにしても、私はARトランザクションを通した検証を妨げるでしょう。あなたが冒険を感じているなら、activerecord-importのような大量インポートの宝石をチェックして、そういうものをサポートしているかどうか確認することもできます。 – Glyoko

関連する問題