【问题标题】:ForeignKey Problems/errors in Rails AppRails 应用程序中的外键问题/错误
【发布时间】:2016-06-07 14:40:11
【问题描述】:

我在 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'

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

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 表中删除外键,但是控制台给了我这个错误

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)

我还在order.rbuser.rb 模型中添加了dependent: :destroy,但我不确定是否可以。

任何人都可以在这里指导我正确的方向吗?我不知道我还能做什么?

下面是user.rb、order.rb order_item.rb和schema.rb

用户.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"

结束

【问题讨论】:

  • 您对用户和订单所做的更改还需要对订单和订单项目执行。无法删除订单,因为它们附加了订单商品。
  • 谢谢你,我当然必须这样做,我很傻 :)
  • 不客气,有时只见树木不见林

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


【解决方案1】:

这个问题的答案是像这样进行另一个迁移。

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

【讨论】:

    猜你喜欢
    • 2019-09-05
    • 1970-01-01
    • 2012-12-26
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 2017-01-23
    相关资源
    最近更新 更多