web-dev-qa-db-fra.com

pourquoi PG :: UniqueViolation: ERREUR: la valeur de clé en double viole la contrainte unique?

J'ai un modèle Post et chaque fois qu'une publication est créée, je veux qu'une nouvelle instance de Moderation soit créée en même temps.

Donc, dans post.rb, j'utilise le rappel after_save :create_moderation Puis écrivez une méthode privée:

 ...
 include Reportable
 after_save :create_moderation

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

Mais lorsqu'une proposition est créée, j'obtiens cette erreur:

PG :: UniqueViolation: ERREUR: la valeur de clé en double viole la contrainte unique "moderations_reportable" DÉTAIL: La clé (reportable_type, reportable_id) = (Post, 25) existe déjà. : INSERT INTO "moderations" ("blog_id", "reportable_type", "reportable_id", "created_at", "updated_at", "blog_type") VALUES ($ 1, $ 2, $ 3, $ 4, $ 5, $ 6) RETURNING "id"

Dans reportable.rb j'ai:

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

Puis quelques autres méthodes pour l'objet à signaler.

Notez que ce problème ne se produit pas lorsque j'exécute la méthode create dans la console.

MODIFIER

  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
10
Orsay

Il semble que vous ayez ajouté un index unique à votre base de données:

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

Avec un index unique, vous ne pourrez avoir qu'un seul enregistrement avec le même reportable_type et reportable_id. Il est probable que vous essayiez de créer une modération pour un rapportable qui a déjà une modération.

4
seancdavis

Pour résoudre le problème, nous devons dire à ActiveRecord de regarder la séquence de la table:

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

Maintenant, ActiveRecord devrait avoir la valeur de séquence correcte et devrait être en mesure d'attribuer correctement les nouveaux identifiants.

Pour résoudre l'erreur

PG :: UniqueViolation: ERREUR: la valeur de clé en double viole la contrainte unique "moderations_reportable" DÉTAIL: La clé (reportable_type, reportable_id) = (Post, 25) existe déjà. : INSERT INTO "moderations" ("blog_id", "reportable_type", "reportable_id", "created_at", "updated_at", "blog_type") VALUES ($ 1, $ 2, $ 3, $ 4, $ 5, $ 6) RETURNING "id"

Comme une erreur s'est produite sur la table des "modérations".

Exécutez ce qui suit depuis console Rails correction

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

Je vous remercie

25
aashish

Correction des séquences pkey pour toutes les bases de données:

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