简体   繁体   中英

ForeignKey Problems/errors in Rails App

I´m build an small private shopping cart in rails, Im using devise for authentication and Postgres for database.

now I´m trying to delete users from my PG database and rails gives me this error and I´m pretty lost at the moment.

  [1] pry(main)> User.destroy_all
User Load (1.7ms)  SELECT "users".* FROM "users"
(0.8ms)  BEGIN
SQL (7.4ms)  DELETE FROM "users" WHERE "users"."id" = $1  [["id", 1]]
(0.3ms)  ROLLBACK
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR:  update or delete on table "orders" violates foreign key constraint "fk_rails_e3cb28f071" on table "order_items"
DETAIL:  Key (id)=(1) is still referenced from table "order_items".
: DELETE FROM "users" WHERE "users"."id" = $1
from  /Users/myname/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:602:in `exec_prepared'

I´ve updated foreignKeys in user and order tables as seen in the migration file below

class UpdateForeignKey < ActiveRecord::Migration
  def change
   # remove the old foreign_key
     remove_foreign_key :orders, :users

   # add the new foreign_key
     add_foreign_key :orders, :users, on_delete: :cascade
   end
end

I tried to remove the Foreignkey from order_item table but then the console gave me this error

Table 'order_items' has no foreign key on column '_id'/Users/myname/Documents/Vefir/stores/brainstore/db/migrate/20160607140507_update_foreign_key_order_item.rb:4:in `change' 
ArgumentError: Table 'order_items' has no foreign key on column '_id'
/Users/myname/Documents/Vefir/stores/brainstore/db/migrate/20160607140507_update_foreign_key_order_item.rb:4:in `change'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

I´ve also added dependent: :destroy to the order.rb and user.rb models but I´m not sure if thats ok.

Can Anyone guide me to the right direction here? I don´t know what more I can do?

below are user.rb, order.rb order_item.rb and schema.rb

user.rb

class User < ActiveRecord::Base
 # Include default devise modules. Others available are:
 # :confirmable, :lockable, :timeoutable and :omniauthable
 devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

  validates_presence_of :name, :address, :city, :country, :postal_code
end

order.rb

class Order < ActiveRecord::Base
 belongs_to :user, dependent: :destroy 
 has_many :order_items, dependent: :destroy 

 def total_price
   order_items.inject(0) { |sum, item| sum + item.total_price }
 end
end

order_item.rb

 class OrderItem < ActiveRecord::Base
  belongs_to :order, dependent: :destroy 
  belongs_to :product, dependent: :destroy 

 def total_price
    self.quantity * self.product.price
 end
end

schema.rb

ActiveRecord::Schema.define(version: 20160607135951) do

 # These are extensions that must be enabled in order to support this database
 enable_extension "plpgsql"

 create_table "categories", force: :cascade do |t|
   t.string   "name"
   t.datetime "created_at", null: false
   t.datetime "updated_at", null: false
 end

 create_table "category_names", force: :cascade do |t|
   t.datetime "created_at", null: false
   t.datetime "updated_at", null: false
 end

 create_table "order_items", force: :cascade do |t|
   t.integer  "order_id"
   t.integer  "product_id"
   t.integer  "quantity"
   t.datetime "created_at", null: false
   t.datetime "updated_at", null: false
 end

 add_index "order_items", ["order_id"], name: "index_order_items_on_order_id", using: :btree
 add_index "order_items", ["product_id"], name: "index_order_items_on_product_id", using: :btree

 create_table "orders", force: :cascade do |t|
   t.integer  "user_id"
   t.datetime "created_at", null: false
   t.datetime "updated_at", null: false
 end

 add_index "orders", ["user_id"], name: "index_orders_on_user_id", using: :btree

 create_table "products", force: :cascade do |t|
   t.string   "name"
   t.string   "description"
   t.float    "price"
   t.string   "image"
   t.datetime "created_at",              null: false
   t.datetime "updated_at",              null: false
   t.integer  "category_id", default: 1
 end

 add_index "products", ["category_id"], name: "index_products_on_category_id", using: :btree

 create_table "users", force: :cascade do |t|
   t.string   "email",                  default: "", null: false
   t.string   "encrypted_password",     default: "", null: false
   t.string   "reset_password_token"
   t.datetime "reset_password_sent_at"
   t.datetime "remember_created_at"
   t.integer  "sign_in_count",          default: 0,  null: false
   t.datetime "current_sign_in_at"
   t.datetime "last_sign_in_at"
   t.inet     "current_sign_in_ip"
   t.inet     "last_sign_in_ip"
   t.string   "name"
   t.string   "address"
   t.string   "phone"
   t.string   "postal_code"
   t.string   "country"
   t.string   "city"
   t.datetime "created_at",                          null: false
   t.datetime "updated_at",                          null: false
 end

 add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
 add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree

 add_foreign_key "order_items", "orders"
 add_foreign_key "order_items", "products"
 add_foreign_key "orders", "users", on_delete: :cascade
 add_foreign_key "products", "categories"

end

The answer to this is to do another migration like this.

class UpdateForeignKeyOrderItem < ActiveRecord::Migration
 def change
    # remove the old foreign_key
    remove_foreign_key :order_items, :orders

    # add the new foreign_key
    add_foreign_key :order_items, :orders, on_delete: :cascade
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM