Ruby on Rails(以降、Rails)で「何か」を削除するシーンはとても多いと思います。
データはもちろんですが、Model、Controller、scaffoldで作成した枠組みなど、いったん作成したものはすべて削除できます。
そこでこの記事では、主にデータの削除方法を説明し、最後にModelやControllerなどを削除する方法を説明します。
データの削除方法では、論理削除と呼ばれる方法も説明します。
それでは、行ってみましょう!
動作を理解するためのWebアプリを作成する
Railsのデータの削除を理解するために、RailsをインストールしてWebアプリを作りましょう。
(1)Railsをインストールします。
私は、以下の記事を参考に、VirtualBoxで作成した仮想パソコンにインストールしたLinux Mintに、Railsの開発環境を作成しました。
基本的には記事の手順に従って操作しますが、app/samurai/sample1ディレクトリを作成する代わりに、app/samurai/delete-demoディレクトリを作成しました。
また、Railsを起動して、ブラウザで画面が表示されることを確認したら、いったんRailsを終了してから次に進みます。
Linux Mintのインストールについては、以下の記事で詳しく説明しています。
(2)「端末」で以下のコマンドを1行ずつ順番に入力します。
bin/rails generate scaffold User name:string bin/rails generate scaffold Post user_id:integer title:string month:integer bin/rails db:migrate bin/rails console
(3)以下のコードを入力します。
User.create(id:1, name:"山田太郎") User.create(id:2, name:"長瀬来") User.create(id:3, name:"立川裕美") User.create(id:4, name:"前田達郎") User.create(id:5, name:"細川修二") User.create(id:6, name:"木村拓磨") Post.create(id:1, user_id:5,title:"楽しい休日の過ごし方" ,month:3) Post.create(id:2, user_id:1,title:"先日の旅行での話" ,month:2) Post.create(id:3, user_id:3,title:"昨日の出来事" ,month:12) Post.create(id:4, user_id:3,title:"山登りに行きました" ,month:8) Post.create(id:5, user_id:4,title:"友人が結婚しました" ,month:4) Post.create(id:6, user_id:2,title:"最近少し気になったこと" ,month:1) Post.create(id:7, user_id:4,title:"ランニングのコツ" ,month:9) Post.create(id:8, user_id:3,title:"Ruby on Railsの日" ,month:9) exit
UserテーブルとPostテーブルにデータが入力され、Railsコンソールが終了します。
次にUserテーブルとPostテーブルを関連付け、Userのデータが削除されたときに、関連するPostのデータを削除するように設定します。
(5)app/models/user.rbを以下のように編集します。
変更前:
class User < ApplicationRecord end
変更後:
class User < ApplicationRecord has_many :posts, dependent: :destroy end
最後にRailsサーバーを起動して、準備完了です。
(6)以下のコマンドを入力します。
bin/rails server
データベース(テーブル)からデータを削除する
データベース(テーブル)からデータを削除する方法は主に4つあります。
メソッド | 説明 | 関連データの削除 |
---|---|---|
destroy | データを1件削除する | 対象データだけでなく、関連するデータも削除する |
destroy_all | where()とあわせて使用し、複数のデータを削除する | 対象データだけでなく、関連するデータも削除する |
delete | データを1件削除する | 関連するデータは削除しない |
delete_all | where()とあわせて使用し、複数のデータを削除する | 関連するデータは削除しない |
destroy
destroyメソッドは、データを1件削除するメソッドです。
対象データだけでなく、モデルクラスでdependent: :destroyを指定して関連付けたデータも自動的に削除されます。
早速、「id:3, name:”立川裕美”」を削除してみましょう。
関連するPostデータも削除されるでしょうか。
(1)新しい「端末」を起動し、以下のコマンドを1行ずつ順番に入力します。
cd app/samurai/delete-demo bin/rails console
(2)以下のコードを入力します。
User.find(3).destroy
実行結果:
User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] (0.1ms) begin transaction Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? [["user_id", 3]] SQL (0.7ms) DELETE FROM "posts" WHERE "posts"."id" = ? [["id", 3]] SQL (0.1ms) DELETE FROM "posts" WHERE "posts"."id" = ? [["id", 4]] SQL (0.1ms) DELETE FROM "posts" WHERE "posts"."id" = ? [["id", 8]] SQL (0.1ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 3]] (10.8ms) commit transaction => #
(3)ブラウザで「http://localhost:3000/users」にアクセスします。
「id:3, name:”立川裕美”」が削除されていますね。
(4)ブラウザで「http://localhost:3000/posts」にアクセスします。
「id:3, name:”立川裕美”」に関連する(user_id:3が設定されている)、以下の3つのPostデータも削除されていることがわかります。
- 「id:3, user_id:3,title:”昨日の出来事” ,month:12」
- 「id:4, user_id:3,title:”山登りに行きました” ,month:8」
- 「id:8, user_id:3,title:”Ruby on Railsの日” ,month:9」
destroy_all
destroy_allメソッドは、複数のデータを削除するときに、whereメソッドとあわせて使うメソッドです。
対象データだけでなく、モデルクラスでdependent: :destroyを指定して関連付けたデータも自動的に削除されるのは、destroyメソッドと同じです。
(1)新しい「端末」を起動し、以下のコマンドを1行ずつ順番に入力します。
cd app/samurai/delete-demo bin/rails console
(2)以下のコードを入力します。
User.where(id: 5..6).destroy_all
実行結果:
User Load (0.2ms) SELECT "users".* FROM "users" WHERE ("users"."id" BETWEEN ? AND ?) [["id", 5], ["id", 6]] (0.1ms) begin transaction Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? [["user_id", 5]] SQL (19.7ms) DELETE FROM "posts" WHERE "posts"."id" = ? [["id", 1]] SQL (0.2ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 5]] (5.8ms) commit transaction (0.1ms) begin transaction Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? [["user_id", 6]] SQL (0.4ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 6]] (4.7ms) commit transaction => [#, #]
トランザクションを利用して、データをまとめて削除しているようです。
トランザクションについては、以下の記事で説明していますので、あわせてご覧ください。
(3)ブラウザで「http://localhost:3000/users」にアクセスします。
where(id: 5..6)と指定したとおり、以下の2つのデータが削除されています。
- 「id:5, name:”細川修二”」
- 「id:6, name:”木村拓磨”」
(4)ブラウザで「http://localhost:3000/posts」にアクセスします。
「id:5, name:”細川修二”」に関連する(user_id:5が設定されている)、以下のデータが削除されていることがわかります。
「id:1, user_id:5,title:”楽しい休日の過ごし方” ,month:3」
※id:6の「木村琢磨」に関連するデータは存在しません。
delete
deleteメソッドも、データを1件削除するメソッドです。
ただし、destroyメソッドとは異なり、関連するデータは削除されません。
(1)新しい「端末」を起動し、以下のコマンドを1行ずつ順番に入力します。
cd app/samurai/delete-demo bin/rails console
(2)以下のコードを入力します。
User.find(4).delete
実行結果:
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 4], ["LIMIT", 1]] SQL (8.7ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 4]] => #
(3)ブラウザで「http://localhost:3000/users」にアクセスします。
「id:4, name:”前田達郎”」が削除されていますね。
(4)ブラウザで「http://localhost:3000/posts」にアクセスします。
こちらは何も変化していません。
destroyメソッドを使うと、「id:4, name:”前田達郎”」に関連する(user_id:4が設定されている)、以下の2つのPostデータも削除されるハズです。
- id:5, user_id:4,title:”友人が結婚しました” ,month:4
- id:7, user_id:4,title:”ランニングのコツ” ,month:9
delete_all
delete_allメソッドは、複数のデータを削除するときに、whereメソッドとあわせて使うメソッドです。
ただし、destroy_allメソッドとは異なり、関連するデータは削除されません。
(1)新しい「端末」を起動し、以下のコマンドを1行ずつ順番に入力します。
cd app/samurai/delete-demo bin/rails console
(2)以下のコードを入力します。
User.where(id: 1..2).delete_all
実行結果:
SQL (8.6ms) DELETE FROM "users" WHERE ("users"."id" BETWEEN ? AND ?) [["id", 1], ["id", 2]] => 2
(3)ブラウザで「http://localhost:3000/users」にアクセスします。
以下の2つのデータも削除され、とうとうすべて無くなってしまいました。
- id:1, name:”山田太郎”
- id:2, name:”長瀬来”
(4)ブラウザで「http://localhost:3000/posts」にアクセスします。
やはり何も変化していませんね。
データベース(テーブル)からデータを論理削除する
論理削除は、実際にはデータを削除せずに、削除したことを記録することで、削除されたようにみえる削除方法です。
Railsでは、paranoia gemをインストールし、Modelを作成する際に「deleted_at: date」を指定することで、論理削除が可能なテーブルが作成されます。
論理削除を試してみる前に、ここまでにscaffoldで作成した枠組みをすべて削除しておきましょう。
(1)Railsサーバーを終了します。
(2)新しい「端末」を起動し、以下のコマンドを1行ずつ順番に入力します。
cd app/samurai/delete-demo bin/rails destroy scaffold user bin/rails destroy scaffold post bin/rails db:drop DISABLE_DATABASE_ENVIRONMENT_CHECK=1
(3)Gemfileの最終行に以下の内容を追加します。
gem "paranoia", "~> 2.2"
(4)以下のコマンドを1行ずつ順番に入力します。
bundle install bin/rails generate scaffold User name:string deleted_at:datetime bin/rails generate scaffold Post user_id:integer title:string month:integer deleted_at:datetime bin/rails db:create bin/rails db:migrate bin/rails console
(5)以下のコードを入力します。
User.create(id:1, name:"山田太郎") User.create(id:2, name:"長瀬来") User.create(id:3, name:"立川裕美") User.create(id:4, name:"前田達郎") User.create(id:5, name:"細川修二") User.create(id:6, name:"木村拓磨") Post.create(id:1, user_id:5,title:"楽しい休日の過ごし方" ,month:3) Post.create(id:2, user_id:1,title:"先日の旅行での話" ,month:2) Post.create(id:3, user_id:3,title:"昨日の出来事" ,month:12) Post.create(id:4, user_id:3,title:"山登りに行きました" ,month:8) Post.create(id:5, user_id:4,title:"友人が結婚しました" ,month:4) Post.create(id:6, user_id:2,title:"最近少し気になったこと" ,month:1) Post.create(id:7, user_id:4,title:"ランニングのコツ" ,month:9) Post.create(id:8, user_id:3,title:"Ruby on Railsの日" ,month:9) exit
先ほど作成した状態とまったく同じ状態を作ろうとしている部分の説明は省きます。
(6)app/models/user.rbを以下のように編集します。
変更前:
class User < ApplicationRecord end
変更後:
class User < ApplicationRecord acts_as_paranoid has_many :posts, dependent: :destroy end
acts_as_paranoidを追加することで、論理削除に対応します。
(7)app/models/post.rbを以下のように編集します。
変更前:
class Post < ApplicationRecord end
変更後:
class Post < ApplicationRecord acts_as_paranoid end
(8)以下のコマンドを入力します。
bin/rails console
(9)以下のコードを入力します。
User.find(3).destroy
実行結果:
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] (0.1ms) begin transaction Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."deleted_at" IS NULL AND "posts"."user_id" = ? [["user_id", 3]] SQL (0.3ms) UPDATE "posts" SET "deleted_at" = '2018-07-12 02:29:47.355911', "updated_at" = '2018-07-12 02:29:47.355939' WHERE "posts"."id" = ? [["id", 3]] SQL (0.1ms) UPDATE "posts" SET "deleted_at" = '2018-07-12 02:29:47.357530', "updated_at" = '2018-07-12 02:29:47.357546' WHERE "posts"."id" = ? [["id", 4]] SQL (0.1ms) UPDATE "posts" SET "deleted_at" = '2018-07-12 02:29:47.358251', "updated_at" = '2018-07-12 02:29:47.358262' WHERE "posts"."id" = ? [["id", 8]] SQL (0.4ms) UPDATE "users" SET "deleted_at" = '2018-07-12 02:29:47.367083', "updated_at" = '2018-07-12 02:29:47.367138' WHERE "users"."id" = ? [["id", 3]] (6.8ms) commit transaction => #
(9)以下のコードを入力します。
User.all
実行結果:
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL LIMIT ? [["LIMIT", 11]] => #, #, #, #, #]>
「id:3, name:”立川裕美”」は削除されていますね。
(10)以下のコードを入力します。
User.only_deleted
実行結果:
User Load (0.2ms) SELECT "users".* FROM "users" WHERE ("users"."deleted_at" IS NOT NULL) LIMIT ? [["LIMIT", 11]] => #]>
削除したデータを確認できました。つまり、データとしての実体は残したまま削除というステータスが付与されているわけです。
続けて、Postの方も確認しておきましょう。
(10)以下のコードを入力します。
Post.all
実行結果:
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."deleted_at" IS NULL LIMIT ? [["LIMIT", 11]] => #, #, #, #, #]>
「id:3, name:”立川裕美”」に関連する(user_id:3が設定されている)、以下の3つのPostデータも削除されていることがわかります。
- 「id:3, user_id:3,title:”昨日の出来事” ,month:12」
- 「id:4, user_id:3,title:”山登りに行きました” ,month:8」
- 「id:8, user_id:3,title:”Ruby on Railsの日” ,month:9」
(11)以下のコードを入力します。
Post.only_deleted
実行結果:
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE ("posts"."deleted_at" IS NOT NULL) LIMIT ? [["LIMIT", 11]] => #, #, #]>
Postのほうも削除したデータを確認できました。こちらも同様にデータそのものは残っていますが、削除された、という状態になっているわけです。
bin/rails generateしたデータを削除する
少し方向性を変えましょう。
Railsでは、bin/rails generateコマンドで枠組み(scaffold)やController、Modelを簡単に作成できます。
ここでは、それらを安全に削除する方法をまとめました。
scaffoldで作成した枠組みを削除する
「bin/rails generate scaffold User name:string」コマンドと「bin/rails generate scaffold Post user_id:integer title:string month:integer」コマンドで作成した枠組みを削除する操作を説明します。
(1)新しい「端末」を起動して、以下のコマンドを1行ずつ順番に入力します。
cd app/samurai/delete-demo bin/rails destroy scaffold User bin/rails destroy scaffold Post bin/rails db:drop DISABLE_DATABASE_ENVIRONMENT_CHECK=1
以上で、削除が完了します。
Controllerを削除する
Controllerの削除については、以下のページで説明していますので、ぜひご覧ください。
Model(モデルクラス、テーブル)を削除する
Model(モデルクラス、テーブル)の削除については、以下のページで説明していますので、ぜひご覧ください。
Railsを独学で頑張っているけど先が見えない方のために
そんな方、実はいらっしゃるのではないでしょうか?
そんな方であれば、これから先の話は必要ないでしょう。そっとページの閉じるボタンを押しましょう。
しかし、「先が見えない」と心の底では勘付いているそこの奥さん。この先を読み進めて、一緒に課題を深堀りしていきましょう。
なぜ「先が見えない」という不安や悩みを抱えてしまうのか
さて、「一寸先は闇だ・・・」とお悩みを抱えている方に、なぜ独学でRailsを勉強しているにもかかわらず、そのような現状を抱えてしまうのか、一緒に考えていきましょう。
先が見えない現状を踏まえ、課題として考えられるものは以下のどれかに該当するでしょう。
- プログラミングの上達が見えない
- プログラミングを継続できない気がする
- プログラミングスキルを習得した姿がイメージできない
- プログラミングスキルを活かした仕事を獲得するイメージができない
これらのどれかに該当することによって、「なんとなくプログラミング学習をしている」という状態になってしまいます。
これらの要因は、三日坊主になる理論と同じなんですが、「プログラミング学習をしなきゃ」とプログラミング学習を頑張ってしまっている状態になってしまっています。
受験勉強をやった経験のある方なら頭がもげるほどに首を縦に振ってしまう方も多いのですが、「今日も5時間勉強するぞ」や「今日はこの章を終わらすぞ」というように、学習を進めることに意識が行き過ぎてしまうと、ある程度学習を継続した後に「先が見えない・・・」となってしまいます。
未来に光を当て、プログラミング学習を「成果が出るもの」にするために
先ほど、「なぜ先が見えないという悩みや不安を抱えてしまうのか」という疑問に対しての答えを示していきました。
これらの課題というのは、独学をしていれば9割の方がぶつかってしまう壁だそうで、いわば、あるあるの現象なのです。
独学をしていて、「なんか前に進めていないぞ」と感じるのはこのせいなんですね。甘く見がちですが、非常にやっかい。
これがさらにやっかいさを極めているのは、上記に挙げた課題のほとんどが、1人で解決できないものばかりだからです。
実は、これらのほとんどが経験者に助けてもらいながら解決しないと、すぐに違う方向へと流れてしまいます。
そう言い切れるのは、以前の私もそうだったからです。
エンジニアやプログラマー関連のキャリアに詳しい方や現役のエンジニアに相談しながら修正を加え、学習を実践して今があります。
という方もいるでしょう。そういう時にこそ、プログラミングスクールの無料カウンセリングを利用するのです。
という考えに辿りついてしまいますよね。結論から言うと弊社では、そういった強引な営業等を行うことはありませんので、安心して受講できます。
「プログラミング学習の先ある未来」を光で明るく照らすには、弊社の無料カウンセリングがぴったりだと断言できます。それくらい無料カウンセリングに自信を持っているのです。
さらに、無料カウンセリングには以下の3大特典もついてきます!
- 「最短1ヶ月で開発ができる学習方法」電子書籍(非売品)
- 効率的なオリジナル学習カリキュラム
- 未経験の転職(フリーランス)を可能にするキャリアサポート
上記の特典だけでも他のスクールにはないポイントだと自信を持っている無料カウンセリング特典です。
ただプログラミング学習をする毎日から、ワクワクしながらプログラミング学習できる毎日に変える体験を一度でいいのでしてみませんか?
まとめ
この記事では、Railsで作成したいろいろなものを削除する方法を説明しました。
データの削除では、destroy、destroy_all、delete、delete_allの4つのメソッドの動作の違いを確認しました。
また、paranoia gemをインストールして論理削除ができるようにする方法も紹介しました。
最後にbin/rails generateコマンドで作成したデータを削除する操作の例として、scaffoldで作成した枠組みやController、Modelを削除する方法にも触れました。
どの削除も、Railsではよく使う基本的な操作ですので、しっかり理解しておきましょう。