Help us understand the problem. What is going on with this article?

railsモデルを削除して新しくmodelを追加したらIDが飛ばされることなく削除したモデルのIDが設定されてしまった。

More than 5 years have passed since last update.

Category has_many goodsのような関連のデータでCategoryモデルを削除し、新規に作成した場合、削除したIDの次の数値がIDとなるのが期待される挙動です。(例 ID=23のモデルを削除したら次に作成されるモデルのIDは24)

しかし特定の状況下ではそうならずに削除したIDが新規に作成したモデルに割り振られる事があるようです。(例 ID=23のモデルを削除したら次に作成されるモデルのIDに23が割り振られる)

こうなると思わぬ関連付けされてしまうので困ります。

> Category.find(23).destroy
  Category Load (0.7ms)  SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 23 LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.3ms)  DELETE FROM `categories` WHERE `categories`.`id` = 23

下に自分が起きたとき原因だろうと思われるところを上げてみます。

  1. railsはmysqlを使う際InnoDBをデフォルトで使う
    Ruby on Rails : migration 機能リファレンス

    なお、バックエンドデータベースとして MySQL を使用している場合、:options を指定しないと "ENGINE=InnoDB" がデフォルトで指定されます。

  2. mysqlのInnoDBは外部key制約で参照されているtableのデータを削除するときはTRUNCATEが使用される。
    12.2.9. TRUNCATE 構文

もしテーブルを参照する外部キー制約があれば、InnoDB テーブルに対しては、TRUNCATE TABLE が DELETE にマップされ、そうでなければ、高速切断(テーブルのドロップと再作成)が利用されます。外部キー制約の有無に関わらず、AUTO_INCREMENT カウンタが TRUNCATE TABLE によってリセットされます。

  1. テーブルでTRUNCATEを使用するとauto incrementがリセットされる。

メッチャ役に立つauto_incrementの話のスライド21~23ページ目を参考にした。

21. テーブルをTRUNCATEするとどうなる?(シーケンスが12まで振られてる状態で)TRUNCATE TABLE tbl;INSERT INTOtbl(user_name)VALUES(‘userXX’);
22. シーケンスが巻き戻った
23. DELETEでは巻き戻らないが、 TRUNCATEだと巻き戻る

上記の3つの条件が同時に起こっているとオートインクリメントの挙動が期待されていないものになるようです。

対策としてはrailsのhas_manyにはdependent オプションがあるのでそれを設定しとくべきだと思います。
設定すると親モデルを削除した際に子モデルも同時に削除されるというものです。

http://guides.rubyonrails.org/association_basics.html#options-for-belongs-to-dependent

railsでhas_manyで関連したモデルのデータを一気に消すとき

prinum
uniba
ユニバ株式会社は、"さわれるインターネット(Embodied Virtuality)"の会社です。
http://uniba.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした