Search code examples
ruby-on-railspostgresqlcapistranospree

Ruby on Rails: PostgreSQL/Capistrano override migration when deploying


I've updated Rails, Spree (e-commerce framework) and added some new gems. These all needed to be migrated after update and installation. On the development app, I ran into a problem. Whenever I tried to migrate I would get the error

Problem

ActiveRecord::StatementInvalid: PG::DuplicateTable: ERROR: relation "index_products_promotion_rules_on_product_id" already exists : CREATE INDEX "index_products_promotion_rules_on_product_id" ON "spree_products_promotion_rules" ("product_id")

I solved this by dropping my database (DB) and making a new one. Since it's development mode It's not a problem losing some data kept on the DB.

Now I'm using postgreSQL as my DB and Capistrano to deploy my app.

When I try to deploy my website to the live server the error/problem returns, but on the live server I've actually got customer data stored and orders coming in. So I can't drop the DB.

I've tried to remove the line from the migration file and schema.rb, but it hasn't helped.

Questions:

Now I was wondering can I override the current tables on the live server?

Is it save to remove the lines from the migration file and schema.rb ?

Or is there another way to solve this?

schema.rb

  create_table "spree_product_promotion_rules", force: :cascade do |t|
    t.integer "product_id"
    t.integer "promotion_rule_id"
    t.index ["product_id"], name: "index_products_promotion_rules_on_product_id"
    t.index ["promotion_rule_id", "product_id"], name: "index_products_promotion_rules_on_promotion_rule_and_product"

Migration File

# This migration comes from spree (originally 20120831092359)
class SpreePromoOneTwo < ActiveRecord::Migration[4.2]
  def up

    # This migration is just a compressed migration for all previous versions of spree_promo
    return if table_exists?(:spree_products_promotion_rules)

    create_table :spree_products_promotion_rules, :id => false, :force => true do |t|
      t.references :product
      t.references :promotion_rule
    end

    add_index :spree_products_promotion_rules, [:product_id], :name => 'index_products_promotion_rules_on_product_id'
    add_index :spree_products_promotion_rules, [:promotion_rule_id], :name => 'index_products_promotion_rules_on_promotion_rule_id'

    create_table :spree_promotion_actions, force: true do |t|
      t.references :activator
      t.integer    :position
      t.string     :type
    end

    create_table :spree_promotion_rules, force: true do |t|
      t.references :activator
      t.references :user
      t.references :product_group
      t.string     :type
      t.timestamps null: false
    end

    add_index :spree_promotion_rules, [:product_group_id], name: 'index_promotion_rules_on_product_group_id'
    add_index :spree_promotion_rules, [:user_id], name: 'index_promotion_rules_on_user_id'

    create_table :spree_promotion_rules_users, id: false, force: true do |t|
      t.references :user
      t.references :promotion_rule
    end

    add_index :spree_promotion_rules_users, [:promotion_rule_id], name: 'index_promotion_rules_users_on_promotion_rule_id'
    add_index :spree_promotion_rules_users, [:user_id], name: 'index_promotion_rules_users_on_user_id'
  end
end

Solution

  • Ultimately I downloaded the database, so I could try to migrate locally. I changed the files removing the already existing lines and executing the rails db:migrate until I no longer got the error message.