24
votes

I have a model Post and each time a post is created I want a new instance of Moderation to be created at the same time.

So in post.rb I use the callback after_save :create_moderation Then write a private method :

 ...
 include Reportable
 after_save :create_moderation

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

But when a proposal is created I get this error :

PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "moderations_reportable" DETAIL: Key (reportable_type, reportable_id)=(Post, 25) already exists. : INSERT INTO "moderations" ("blog_id", "reportable_type", "reportable_id", "created_at", "updated_at", "blog_type") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"

In reportable.rb I have :

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

Then few other methods for reportable object.

Note that this issue doesn't happen when I run the create method in console.

EDIT

  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
4
show you migration as well please since this is a Database Error and not an ORM Errorengineersmnky
@engineersmnky I edited my postOrsay
and this t.index ["reportable_type", "reportable_id"], name: "moderations_reportable", unique: true didn't give it away?engineersmnky
Sorry copy paste errorOrsay
No error that line is still part of the database key constraints. I think you want to change the hook to after_create rather than after_save because save will be called on update as wellengineersmnky

4 Answers

7
votes

Looks like you've added a unique index to your database:

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

With a unique index you will only be able to have one record with the same reportable_type and reportable_id. It's likely that you're trying to create a moderation for a reportable that already has a moderation.

69
votes

To fix the issue, we have to tell ActiveRecord to look at the sequence of the table:

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

Now ActiveRecord should have the correct sequence value, and should be able to assign new id's properly.

To resolve error

PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "moderations_reportable" DETAIL: Key (reportable_type, reportable_id)=(Post, 25) already exists. : INSERT INTO "moderations" ("blog_id", "reportable_type", "reportable_id", "created_at", "updated_at", "blog_type") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"

As error occurred on 'moderations' table.

Run the following from rails console fix

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

Thank you

21
votes

Fix pkey sequences for all database:

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

ONLY FOR THOSE WHO ARE SEEING THIS WHILE RUNNING TESTS


One possible reason is, you have some migrations that create new data-records and you ran one of the following recently.

rake db:migrate RAILS_ENV=test

or

rake db:migrate:reset RAILS_ENV=test

Solution

You need to clean/wipeout your test-DB. Run this

rake db:reset RAILS_ENV=test

This will wipeout and generate schema from schema.rb.