Rails App

时间:2016-06-07 14:40:12

标签: ruby-on-rails postgresql devise foreign-keys

我在rails中构建了一个小型私人购物车,我使用devise进行身份验证,Postgres用于数据库。

现在我正在尝试从我的PG数据库中删除用户,rails会给我这个错误,而且我现在很丢失。

  [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'

我已在用户和订单表中更新了foreignKeys,如下面的迁移文件中所示

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

我试图从order_item表中删除Foreignkey但是控制台给了我这个错误

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)

我还在dependent: :destroyorder.rb模型中添加了user.rb,但我不确定这是否正常。

有人能引导我走向正确的方向吗?我不知道我还能做什么?

下面的

是user.rb,order.rb order_item.rb和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"

1 个答案:

答案 0 :(得分:2)

对此的答案是进行另一次这样的迁移。

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