web-dev-qa-db-ja.com

なぜPG :: UniqueViolation:エラー:重複するキー値が一意制約に違反していますか?

モデルPostがあり、投稿が作成されるたびに、Moderationの新しいインスタンスを同時に作成したいと考えています。

したがって、post.rbではコールバックafter_save :create_moderation次に、プライベートメソッドを記述します。

 ...
 include Reportable
 after_save :create_moderation

 private
 def create_moderation
    self.create_moderation!(blog: Blog.first)
 end

しかし、プロポーザルが作成されると、次のエラーが発生します。

PG :: UniqueViolation:エラー:重複するキー値が一意の制約「moderations_reportable」に違反しています詳細:キー(reportable_type、reportable_id)=(Post、25)は既に存在します。 :INSERT INTO "moderations"( "blog_id"、 "reportable_type"、 "reportable_id"、 "created_at"、 "updated_at"、 "blog_type")VALUES($ 1、$ 2、$ 3、$ 4、$ 5、$ 6)RETURNING "id"

Reportable.rbに私は持っています:

  has_one :moderation, as: :reportable, foreign_key: "reportable_id", foreign_type: "reportable_type", class_name: "Moderation"

次に、レポート可能なオブジェクトの他のいくつかのメソッド。

コンソールでcreateメソッドを実行しても、この問題は発生しないことに注意してください。

[〜#〜]編集[〜#〜]

  create_table "moderations", id: :serial, force: :cascade do |t|
    t.string "reportable_type", null: false
    t.string "reportable_id", null: false
    t.integer "blog_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "blog_type", null: false
    t.string "upstream_moderation", default: "unmoderate"
    t.index ["blog_id", "blog_type"], name: "moderations_blog"
    t.index ["reportable_type", "reportable_id"], name: "moderations_reportable", unique: true
  end



create_table "posts", id: :serial, force: :cascade do |t|
    t.text "title", null: false
    t.text "body", null: false
    t.integer "feature_id", null: false
    t.integer "author_id"
    t.integer "scope_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "post_votes_count", default: 0, null: false
    t.index ["body"], name: "post_body_search"
    t.index ["created_at"], name: "index_posts_on_created_at"
    t.index ["author_id"], name: "index_posts_on_author_id"
    t.index ["feature_id"], name: "index_posts_on_feature_id"
    t.index ["proposal_votes_count"], name: "index_posts_on_post_votes_count"
    t.index ["title"], name: "post_title_search"
  end
13
Orsay

データベースに一意のインデックスを追加したようです:

t.index ["reportable_type", "reportable_id"], name: "moderations_reportable", unique: true

一意のインデックスを使用すると、同じreportable_typeおよびreportable_idのレコードを1つだけ持つことができます。すでにモデレートがあるレポータブルのモデレーションを作成しようとしている可能性があります。

4
seancdavis

この問題を修正するには、ActiveRecordにテーブルのシーケンスを確認するように指示する必要があります。

ActiveRecord::Base.connection.reset_pk_sequence!('table_name')

これで、ActiveRecordは正しいシーケンス値を持ち、新しいIDを適切に割り当てることができるはずです。

エラーを解決するには

PG :: UniqueViolation:エラー:重複するキー値が一意の制約「moderations_reportable」に違反しています詳細:キー(reportable_type、reportable_id)=(Post、25)は既に存在します。 :INSERT INTO "moderations"( "blog_id"、 "reportable_type"、 "reportable_id"、 "created_at"、 "updated_at"、 "blog_type")VALUES($ 1、$ 2、$ 3、$ 4、$ 5、$ 6)RETURNING "id"

「管理」テーブルでエラーが発生したため。

Railsコンソール修正から以下を実行します

ActiveRecord::Base.connection.reset_pk_sequence!('moderations')

ありがとうございました

25
aashish

すべてのデータベースのpkeyシーケンスを修正します。

ActiveRecord::Base.connection.tables.each do |table_name| 
  ActiveRecord::Base.connection.reset_pk_sequence!(table_name)
end
6