RoR:数据库级参照完整性

时间:2016-02-18 23:53:56

标签: ruby-on-rails activerecord rails-migrations ruby-on-rails-4.2 ruby-on-rails-5

我有这个型号:

class Book < ApplicationRecord
  has_many :pages, dependent: :destroy
end

这一个:

class Page < ApplicationRecord
  belongs_to :book
end

Book的迁移是:

class CreateBooks < ActiveRecord::Migration[5.0]
  def change
    create_table :books do |t|
    end
  end
end

Page的迁移是:

class CreatePages < ActiveRecord::Migration[5.0]
  def change
    create_table :pages do |t|
      t.references :book, index: true, null: false
    end
  end
  add_foreign_key :pages, :books, on_delete: :cascade
end

此外我还有一些种子:

Book.create!(
  pages: [
    Page.new,
    Page.new,
    Page.new
  ]
)

rake db:migraterake db:seed以及所有爵士乐。我跳进了导轨c:

Book.first
Book Load (0.1ms)  SELECT  "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<Book id: 1>

酷....现在?

Page.count
(0.3ms)  SELECT COUNT(*) FROM "pages"
=> 3

完全有道理。下一个:

Book.first.destroy
Book Load (0.2ms)  SELECT  "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT ?  [["LIMIT", 1]]
(0.1ms)  begin transaction
Page Load (0.1ms)  SELECT "pages".* FROM "pages" WHERE "pages"."book_id" = ?  [["book_id", 1]]
SQL (0.1ms)  DELETE FROM "pages" WHERE "pages"."id" = ?  [["id", 1]]
SQL (0.0ms)  DELETE FROM "pages" WHERE "pages"."id" = ?  [["id", 2]]
SQL (0.0ms)  DELETE FROM "pages" WHERE "pages"."id" = ?  [["id", 3]]
SQL (0.1ms)  DELETE FROM "books" WHERE "books"."id" = ?  [["id", 1]]

耶!差不多......再次播种后我就这样做了:

Book.first.delete
Book Load (0.1ms)  SELECT  "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT ?  [["LIMIT", 1]]
SQL (144.0ms)  DELETE FROM "books" WHERE "books"."id" = ?  [["id", 2]]

WTF?

Page.count
(0.1ms)  SELECT COUNT(*) FROM "pages"
=> 3

我知道delete不会触发回调,因此dependent: :destroy无法帮助我。但外键呢?你好?我希望数据库级别的参照完整性!!我究竟做错了什么?我尝试了更多的东西,比如将on_delete: :cascade移到字段定义中:

def change
  create_table :pages do |t|
    t.references :book, index: true, null: false
  end
end

但是......不,同样的结果。我已经搜索并阅读了两次ActiveRecord文档,SO中的其他一些问题指出了我当前的设置(这不是我正在处理的项目,而是一个新生成的具有相同基本配置的项目来复制错误 - 是的,它也在那里失败了),但我无法指责错误。也许现在已经太晚了,我太累了。救命? Rails甚至支持这个吗?我正在使用v5,远远超过4.2,其中集成了db级别的约束。我的db/schema.rb看起来像这样:

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

  create_table "books", force: :cascade do |t|
  end

  create_table "pages", force: :cascade do |t|
    t.integer "book_id", null: false
    t.index ["book_id"], name: "index_pages_on_book_id"
  end

end

没有外键痕迹?

1 个答案:

答案 0 :(得分:1)

你正在测试你可能正在使用SQLite,这里只提到了mysql,mysql2和postgres因此我认为rails不支持SQLite上的外键:http://edgeguides.rubyonrails.org/4_2_release_notes.html#foreign-key-support

在另一篇帖子中也有说明:https://stackoverflow.com/a/28801481/4560144