0

J'ai ce modèle:RoR: intégrité référentielle niveau base de données

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

Et celui-ci:

class Page < ApplicationRecord 
    belongs_to :book 
end 

La migration pour le Book est:

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

Et la migration pour Page est:

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 

De plus j'ai eu quelques graines:

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

rake db:migrate, rake db:seed et tout ce jazz. Je saute dans les rails c:

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

Cool .... maintenant?

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

Donne un sens total. Suivant:

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]] 

Yay! Presque là ... après ensemencement à nouveau je fais ceci:

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 

Je sais delete ne déclenche pas callbacks, de sorte que dependent: :destroy ne me aidera pas ici. Mais la clé étrangère? Bonjour? Je veux l'intégrité référentielle dans mon niveau de base de données !! Qu'est-ce que je fais mal? J'ai essayé d'autres choses, comme le déplacement de la on_delete: :cascade à la définition du champ:

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

Mais ... Nope, même résultat. J'ai recherché et lu la documentation ActiveRecord deux fois, et quelques autres questions dans SO m'ont indiqué mon installation actuelle (qui n'est pas le projet sur lequel je travaille, mais plutôt un nouveau projet avec la même configuration de base pour répliquer le erreur - oui, elle échoue là aussi), mais je ne peux tout simplement pas mettre le doigt sur ce qui ne va pas. Peut-être que c'est trop tard et que je suis trop fatigué. Aidez-moi? Est-ce que Rails supporte même cela? J'utilise v5, loin, loin devant 4.2 où les contraintes au niveau db ont été intégrées. Mon db/schema.rb ressemble à ceci:

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 

Aucune trace de clés étrangères?

+0

Y a-t-il une raison pour laquelle vous utilisez delete au lieu de détruire? Si quelque chose, vous pouvez toujours utiliser Dépendance:: delete_all, qui est essentiellement un nuke de l'orbite. Il ne se souciera de rien concernant les pages et leurs dépendances. – David

+0

Aucune raison particulière en plus d'apprendre et de me sauver des ennuis futurs - Rails réclame l'intégrité référentielle au niveau db est faisable, et j'aimerais l'obtenir. –

+0

https://robots.thoughtbot.com/referential-integrity-with-foreign-keys pourrait vous aider. – David

Répondre

1

Pour vous testez vous utilisez probablement SQLite, ici que MySQL, mysql2 et postgres sont mentionnés donc je pense que les rails ne supportent pas les clés étrangères sur SQLite: http://edgeguides.rubyonrails.org/4_2_release_notes.html#foreign-key-support

Il est également indiqué dans une autre façon après: https://stackoverflow.com/a/28801481/4560144

+0

Je m'assurerai de vérifier cela plus tard. En effet, j'utilise SQLite, et j'ai la suspicion que vous pourriez avoir raison. –

+0

OUI. Que je suis bête. Merci mec. –