🐡

知っていたら実務で最強!Railsコンソールの使い方を実務ベースで解説

2023/11/30に公開

Railsコンソールとはそもそも何か

Railsで提供されている対話型のコマンドラインツールです。
アプリ内のモデルやコントローラのメソッドを呼び出すことができ、
データベースのレコードを作成、更新、削除ができます。

以下のコマンドで立ち上げることができます。

# rails 
# rails console

実行環境の確認

開発において環境は3種類あります。

1.開発環境 (development): 開発者がアプリケーションを開発するための環境。

2.テスト環境 (test): RSpecなどで使われユニットテストや統合テストがこの環境で実行。

3.本番環境 (production):アプリケーションを実際に運用される環境でユーザーはここを使用。

⚫︎補足
staging環境は今回はなし!

まず自分が今どの環境にいるのか確認します。コンソールで入った後にRails.envを実行します。

irb(main):001> Rails.env
=> "development"

今開発環境にいることがわかります。envはenviromentのenvです。
コンソールのコマンドによって環境を変えることができます。

# rails c   #開発環境の入り方
Loading development environment (Rails 7.0.8)
irb(main):001> Rails.env
=> "development"


# rails c -e test  #テスト環境の入り方
Loading test environment (Rails 7.0.8)
irb(main):001> Rails.env
=> "test"

# rails c -e production  #本番環境入り方

Rails6以降だと他にも以下のやり方でも起動できるみたいです。

  • RAILS_ENV=[環境] rails c
  • rails c --environment [環境]

実際に動かしてみましょうか。

1.開発環境

# RAILS_ENV= rails c
Loading development environment (Rails 7.0.8)
irb(main):001> Rails.env
=> "development"

2.テスト環境

# rails c --environment test
Loading test environment (Rails 7.0.8)
irb(main):001> Rails.env
=> "test"

⚫︎補足
RAILS_ENV=[環境] rails cのテストはどうやら廃止になったみたいですね。

https://qiita.com/keisukee/items/cf0ccb6f7e8b4e8a775b

実際にコンソールを動かしてみる

実際に実務でやった手順を解説します。

ユーザーのデータが全く入っていなかったのでデータを入れるために実行しました。

irb(main):001> User.new
=> 
=> 
#<User:〇〇
 id: nil,
 member_id: nil,
 member_name: nil,
 deleted_at: nil,
 created_at: nil,
 updated_at: nil>

User.newですが、Userモデルの新しいインスタンスを生成しています。
そのままcreateをします。createしたらsaveは不要です。
理由はクラスメソッドだからです。

irb(main):002> User.create(member_id:"123",member_name:"Mike")
  TRANSACTION (0.8ms)  BEGIN
  User Create (7.8ms)  INSERT INTO "users" ("member_id", "member_name",  "deleted_at", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["slack_id", "123"], ["slack_name", "go"],["deleted_at", nil], ["created_at", "2023-11-20 10:18:51.303718"], ["updated_at", "2023-11-20 10:18:51.303718"]]
  TRANSACTION (2.7ms)  COMMIT
=> 
#<User:〇〇
 id: 1,
 member_id: "123",
 member_name: "Mike",
 deleted_at: nil,
 created_at: Mon, 20 Nov 2023 10:18:51.303718000 UTC +00:00,
 updated_at: Mon, 20 Nov 2023 10:18:51.303718000 UTC +00:00>

⚫︎補足❗️
newするだけならsaveは必要です。

user = User.new
user.save

データは1つしかないですが、User.allで取得してみます。

irb(main):004> User.all
  User Load (0.7ms)  SELECT "users".* FROM "users"
=> 
[#<User:〇〇
  id: 1,
  member_id: "123",
  member_name: "Mike",
  deleted_at: nil,
  created_at: Mon, 20 Nov 2023 10:18:51.303718000 UTC +00:00,
  updated_at: Mon, 20 Nov 2023 10:18:51.303718000 UTC +00:00>]

userと投稿を紐付け

データが取れているのを確認したらexitしてuserと投稿を紐付けします。

# rails c
Loading development environment (Rails 7.0.8)
irb(main):001> Post.new
=> 
#<Post:〇〇
 id: nil,
 user_id: nil,
 timestamps: nil,
 deleted_at: nil,
 created_at: nil,
 updated_at: nil>

Userの情報を確認します。

irb(main):002> User.last
  User Load (0.7ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> 
#<User:〇〇
 id: 1,
 member_id: "123",
 member_name: "Mike",
 deleted_at: nil,
 created_at: Mon, 20 Nov 2023 10:18:51.303718000 UTC +00:00,
 updated_at: Mon, 20 Nov 2023 10:18:51.303718000 UTC +00:00>
irb(main):003> User.last.id
  User Load (0.9ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> 1

またこの後もcreateします。

irb(main):004> Post.create(user_id:1)
  TRANSACTION (0.4ms)  BEGIN
  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Post Create (4.8ms)  INSERT INTO "posts" ("user_id", "timestamps", "deleted_at", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["user_id", 1], ["timestamps", nil], ["deleted_at", nil], ["created_at", "2023-11-20 10:33:51.550814"], ["updated_at", "2023-11-20 10:33:51.550814"]]
  TRANSACTION (1.1ms)  COMMIT
=> 
#<Post:〇〇
 id: 1,
 user_id: 1,
 timestamps: nil,
 deleted_at: nil,
 created_at: Mon, 20 Nov 2023 10:33:51.550814000 UTC +00:00,
 updated_at: Mon, 20 Nov 2023 10:33:51.550814000 UTC +00:00>

日報の情報を確認してみます。

irb(main):005> Post.last
  Post Load (0.5ms)  SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> 
#<Post:0x00007f5155427518
 id: 1,
 user_id: 1,
 timestamps: nil,
 deleted_at: nil,
 created_at: Mon, 20 Nov 2023 10:33:51.550814000 UTC +00:00,
 updated_at: Mon, 20 Nov 2023 10:33:51.550814000 UTC +00:00>

ユーザーの情報も確認してみます。

irb(main):006> User.last
  User Load (0.7ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> 
#<User:〇〇
 id: 1,
 member_id: "123",
 member_name: "Mike",
 deleted_at: nil,
 created_at: Mon, 20 Nov 2023 10:18:51.303718000 UTC +00:00,
 updated_at: Mon, 20 Nov 2023 10:18:51.303718000 UTC +00:00>

取得した最後のユーザーに対して、postsメソッドを呼び出しています。

irb(main):007> User.last.posts
  User Load (0.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
  Post Load (0.7ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = $1  [["user_id", 1]]
=> 
[#<Post:〇〇
  id: 1,
  user_id: 1,
  timestamps: nil,
  deleted_at: nil,
  created_at: Mon, 20 Nov 2023 10:33:51.550814000 UTC +00:00,
  updated_at: Mon, 20 Nov 2023 10:33:51.550814000 UTC +00:00>]

createでまたPostのデータを作ろうと思います。

irb(main):009> Post.create(user_id:1)
  #中略
irb(main):010> Post.create(user_id:1)
  #中略

user_idが1のデータをcountを使って確認します。

irb(main):011> User.last.posts.count
  User Load (1.0ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
  Post Count (0.8ms)  SELECT COUNT(*) FROM "posts" WHERE "posts"."user_id" = $1  [["user_id", 1]]
=> 3

これで3つデータができたことがわかります。
最後確認してみましょう。

irb(main):012> User.last.posts
  User Load (0.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
  Post Load (0.4ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = $1  [["user_id", 1]]
=> 
[#<Post:〇〇
  id: 1,
  user_id: 1,
  timestamps: nil,
  deleted_at: nil,
  created_at: Mon, 20 Nov 2023 10:33:51.550814000 UTC +00:00,
  updated_at: Mon, 20 Nov 2023 10:33:51.550814000 UTC +00:00>,
 #<Post:〇〇
  id: 2,
  user_id: 1,
  timestamps: nil,
  deleted_at: nil,
  created_at: Mon, 20 Nov 2023 10:36:15.774006000 UTC +00:00,
  updated_at: Mon, 20 Nov 2023 10:36:15.774006000 UTC +00:00>,
 #<Post:〇〇
  id: 3,
  user_id: 1,
  timestamps: nil,
  deleted_at: nil,
  created_at: Mon, 20 Nov 2023 10:36:20.317372000 UTC +00:00,
  updated_at: Mon, 20 Nov 2023 10:36:20.317372000 UTC +00:00>]

user_idのデータが3つ取れました。

削除の方法

投稿のデータを全部削除するやり方は以下の通りです。

irb(main):001> Post.all
#中略
irb(main):002> Post.destroy_all

特定のデータでuser_idが1のデータを削除する場合は以下のやり方をします。

irb(main):001> Post.where(user_id: 1).destroy_all

deleted_at カラムが nil でないものを削除する場合は

irb(main):001> Post.where.not(deleted_at: nil).destroy_all

です。

Post.allで全部削除する方法は

# Post.all で取得した全ての投稿を削除
Post.destroy_all

# Post.all で取得した全ての投稿を直接データベースから削除
Post.delete_all

です。

基本的な使い方

基本的なデータベース操作例も見ていきます。

  • Userモデルの新しいユーザーを作成して保存
user = User.new(name: "Messi", email: "messi@example.com")
user.save
  • 最初のユーザーを取得
user = User.first
  • 条件に合致するユーザーを取得
users = User.where(age: 35)
  • ユーザーの名前を更新
user = User.first
user.update(name: "Ronald")
  • 最初のユーザーを削除
user = User.first
user.destroy

5番目以降のデータはどうやって取得するのか

上記のようにUserの最初や2番目のデータはfirstやsecondで取得できます。
1番目から5番目のデータは以下のように取得できます。

user = User.first
user = User.second
user = User.third
user = User.fourth
user = User.fifth

6番目以降のデータ

[1] pry(main)> User.sixth
NoMethodError: undefined method `sixth' for #中略

になってしまいます。6番目以降は以下のやり方で取得できました。

User.offset(5).limit(1).first  #6番目
User.offset(6).limit(1).first    #7番目
User.offset(7).limit(1).first    #8番目

例えば、offset 6(7番目のレコード)を指定して、1つのレコードのみを取得することで、7番目のレコードを取得します。

モデルの7番目のレコードを取得するためには、offset を使用してフィルタリングを行う必要があります。offsetは指定した数だけ結果をスキップします。
offset には1から始まるインデックスを使うのではなく、0から始まるインデックスを使うことに注意してください。

用語の解説

補足で用語の解説をしていきます。ChatGPTを参考にしました。

  • インスタンス
    あるものの具体的な実体や例のことです。例えば、車の型(設計図)があるとします。
    その型に基づいて実際に作られた車が、その型の「インスタンス」 です。

車の型ができたとするとその型が「ベンツ」だとすると、それに基づいて作られた実際のベンツが「ベンツのインスタンス」です。

プログラミングの世界でも例えてみます。例えば、あるプログラムで作成された「データの型」があるとします。その型に基づいて作成された実際のデータが、その型の「インスタンス」です。プログラムの中で、「User(ユーザー)」という型があった場合、それに基づいて作られた1人のユーザーが「Userのインスタンス」です。

つまり 「インスタンス」とは、抽象的な概念や設計図に基づいて実際に作られた具体的なもののことです。

  • クラスメソッド
    クラスメソッドは、あるクラス(例えば、Userというクラス)全体に関連する動作や処理を行うための特別なメソッドです。これは、クラス自体に対して呼び出され、クラスに関する操作を実行します。小学生にわかりやすく説明すると、以下のようになります。

クラスは、抽象的な概念や設計図です。例えば、Animalというクラスがあるとします。
このクラスには 「動物」の習性や特徴(メソッド)が定義 されています。例えば、「夜行性」や「肉食」といったメソッドがあります。

ここで、「動物」を一瞬で作りたいとなった時に実現するのがクラスメソッドです。
クラスメソッドは、クラス全体に対して影響を与えることができる特別なメソッドです。
例えば、「動物を作る」というクラスメソッドを呼び出すことで、
新しい動物が一斉に作られるイメージです。

実際のプログラムで言うと、以下のようになります。例えば、Animalクラスがあって、そのクラスに「みんなの動物を作る」クラスメソッドがあるとします。

class Animal
  def self.create_animal
    puts "動物ができた!"
  end
end

# クラスメソッドを呼び出す
Animal.create_animal

このプログラムを実行すると、「動物ができた!」と表示されます。クラスメソッドはselfキーワードを使って定義され、そのクラス自体に対して呼び出されることが特徴です。

  • インスタンス変数あとnewとsaveはインスタンス変数ですか。インスタンス変数を小学生にもわかるように書いてください。

インスタンス変数は、オブジェクト(もの)に関連する情報を保存するための特別な入れ物のようなものです。
例えば、ある動物のオブジェクトがあったときに、その動物が「名前」や「色」などの情報を持つ場合、それらの情報をデータとして入れておくことができます。このデータがインスタンス変数です。
インスタンス変数に入れておくことができます。

コンソールでnewとsaveで、動物の例で考えてみましょう。

  • new(新しく作る):

newは、新しい動物を作るための工程です。例えば、newを使って「サル」を作ると、
サルは新しくできたところで、まだ具体的な名前や色が決まっていません。
これをプログラムで表現すると、次のようになります:

monkey = Monkey.new

ここでmonkeyはサルのインスタンスを表しています。このとき、Monkeyクラスの中には
「種類」や「生息地」などが入れられる特別なポケット(インスタンス変数)がありますが、まだ具体的な情報は入っていません。

  • save(保存する)

saveは、サルに具体的な情報を入れて、それを保存する工程です。
例えば、サルに名前が「ウッキー」、色が「茶色」だと決まったら、それをsaveして保存します。
これをプログラムで表現すると

monkey.name = "ウッキー"
monkey.color = "茶色"
monkey.save

ここで、nameやcolorはサルが持っている特別なポケット(インスタンス変数)に情報を入れることを示しています。そして、saveはその情報を保存して、サルに具体的な名前や色が入った状態で完成させます。

簡単に言えば、newは新しいものを作り、saveはそれに具体的な情報を入れて保存します。
このとき、具体的な情報はインスタンス変数に入れられていると考えることができます。

参考資料

https://qiita.com/taki_21/items/b44dffc1eb13b172eb18

Discussion