Rails consoleの理解度を上げるために、 ChatGPTに問題を出力してもらった【中級編】
はじめに
前回【初級編】を行なったので、今回は【中級編】に挑戦したいと思います。
中級編では、モデル間の関連性、バリデーション、スコープ、クエリの操作などを取り扱います。
なお、使用するアプリケーションは初級編からのものを引き続き使用します。
初級編はこちら
アプリケーションの概要
- アプリ名
BlogApp
- モデル
User
Post
Comment
が存在します。
User
1 対Post
多 の関係。
Post
1 対Comment
多 の関係。 - Userテーブル
name
カラムとemail
カラムを持ちます。
name
は必須のバリデーション、email
は一意性のバリデーションを設定しています。 - Postテーブル
title
カラムとcontent
カラムを持ちます。 - Commentテーブル
body
カラムを持ちます。
chatGTPに出題してもらった問題(中級)
- 特定のUserが作成したPostの数を取得するコマンドを書いてください。
- 特定のUserが作成したPostのうち、タイトルに特定のキーワード("Rails")が含まれるものをすべて取得するコマンドを書いてください。
- Userのemailが未設定のものがあるかどうかを確認するコマンドを書いてください。
- Userモデルに新しいバリデーションを追加するためのコードを書いてください。このバリデーションでは、名前が必須であること、Eメールが一意であることを確認します。
- 上記のバリデーションが正しく機能しているかどうかをテストするためのコマンドを書いてください。新しいユーザーを作成し、バリデーションエラーメッセージを表示してください。
- Postのタイトルと内容からなる新しいメソッド info をPostモデルに追加するためのコードを書いてください。このメソッドはタイトルと内容を連結した文字列を返すものとします。
- 上記で作成したメソッドを使用して、特定のPostのタイトルと内容を表示するコマンドを書いてください。
- スコープを使用して、特定のキーワードを含むPostを取得するためのメソッドを作成してください。スコープ名は with_keyword とし、引数は keyword とします。
- 上記で作成したスコープを使用して、特定のキーワード("Rails")を含むPostを取得するコマンドを書いてください。
- 特定のUserが作成したPostを作成日の新しい順に取得するコマンドを書いてください。
私の回答
問題1の回答
Q. 特定のUserが作成したPostの数を取得するコマンドを書いてください。
まず、userを作成します。
irb(main):00:0> user = User.create(name: "ippei shimizu", email: "test@example.com")
irb(main):00:0> user
=> #<User id: 1, name: "ippei shimizu", email: "test@example.com", created_at: "2023-07-24 11:49:41", updated_at: "2023-07-24 11:49:41">
次に、user
でpost
を作成します。
irb(main):00:0> post = user.posts.create(title: "ippeiの投稿", content: "今日はお散歩をしました")
irb(main):00:0> post
=> #<Post id: 3, title: "ippeiの投稿", content: "今日はお散歩をしました", user_id: 1, created_at: "2023-07-24 23:25:51", updated_at: "2023-07-24 23:25:51">
もう一つ作成しておきます。
irb(main):00:0> post1 = user.posts.create(title: "Railsの勉強をした", content: "modelを作成します。")
irb(main):00:0> post1
=> #<Post id: 4, title: "Railsの勉強をした", content: "modelを作成します。", user_id: 1, created_at: "2023-07-24 23:35:14", updated_at: "2023-07-24 23:35:14">
これで、user_id: 1
を持つPost
が2つ作成できました。
最後に、user
が作成したpost
の数を取得するコマンドを実行します。
irb(main):00:0> user.posts.count
問題2の回答
Q. 特定のUserが作成したPostのうち、タイトルに特定のキーワード("Rails")が含まれるものをすべて取得するコマンドを書いてください。
irb(main):00:0> user.posts.where('title LIKE ?', "%Rails%")
問題3の回答
Q. Userのemailが未設定のものがあるかどうかを確認するコマンドを書いてください。
まず、email
が未設定のuser
を作成。
irb(main):00:0> user1 = User.create(name: "nivea sun", email: "")
irb(main):00:0> user1
=> #<User id: 3, name: "nivea sun", email: "", created_at: "2023-07-24 23:49:37", updated_at: "2023-07-24 23:49:37">
where
でemail
が未設定(nilまたは空)の場合を探す。
irb(main):00:0> User.where(email: [nil,""])
User Load (0.5ms) SELECT "users".* FROM "users" WHERE ("users"."email" = ? OR "users"."email" IS NULL) LIMIT ? [["email", ""], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 3, name: "nivea sun", email: "", created_at: "2023-07-24 23:49:37", updated_at: "2023-07-24 23:49:37">]>
問題4の回答
Q. Userモデルに新しいバリデーションを追加するためのコードを書いてください。このバリデーションでは、名前が必須であること、Eメールが一意であることを確認します。
class User < ApplicationRecord
has_many :posts, dependent: :destroy
validates :name, presence: true
validates :email, uniqueness: true
end
問題5の回答
Q. 上記のバリデーションが正しく機能しているかどうかをテストするためのコマンドを書いてください。新しいユーザーを作成し、バリデーションエラーメッセージを表示してください。
まず、nameカラムが空のuser
をUser.new
で作成します。
irb(main):00:0> user5 = User.new(name: "", email: "user5@example.com")
=> #<User id: nil, name: "", email: "user5@example.com", created_at: nil, updated_at: nil>
valid?メソッドでバリデーションを実行します。
irb(main):00:0> user5.valid?
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "user5@example.com"], ["LIMIT", 1]]
=> false
バリデーションのエラーメッセージを確認します。
irb(main):00:0> user5.errors.messages
=> {:name=>["can't be blank"]}
問題6の回答
Q. Postのタイトルと内容からなる新しいメソッド info をPostモデルに追加するためのコードを書いてください。このメソッドはタイトルと内容を連結した文字列を返すものとします。
post.rb
にinfo
メソッドを定義します。
class Post < ApplicationRecord
belongs_to :user
has_many :comments, dependent: :destroy
def info
"#{self.title} #{self.content}"
end
end
問題7の回答
Q. 上記で作成したメソッドを使用して、特定のPostのタイトルと内容を表示するコマンドを書いてください。
irb(main):00:0> post
=> #<Post id: 3, title: "ippeiの投稿", content: "今日はお散歩をしました", user_id: 1, created_at: "2023-07-24 23:25:51", updated_at: "2023-07-24 23:25:51">
irb(main):00:0> post.info
=> "ippeiの投稿 今日はお散歩をしました"
問題8の回答
Q. スコープを使用して、特定のキーワードを含むPostを取得するためのメソッドを作成してください。スコープ名は with_keyword とし、引数は keyword とします。
モデルのscope
機能は、モデル側であらかじめ条件式に対して名前をつけ、その名前をメソッドで呼び出すことで、条件式の管理がしやすくなります。
class Post < ApplicationRecord
belongs_to :user
has_many :comments, dependent: :destroy
scope :with_keyword, -> (keyword){where('title LIKE ? OR content LIKE ?'), "%#{keyword}%", "%#{keyword}%"}
def info
"#{self.title} #{self.content}"
end
end
問題9の回答
Q. 上記で作成したスコープを使用して、特定のキーワード("Rails")を含むPostを取得するコマンドを書いてください。
irb(main):00:0> Post.with_keyword("Rails")
Post Load (0.7ms) SELECT "posts".* FROM "posts" WHERE (title LIKE '%Rails%' OR content LIKE '%Rails') LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Post id: 4, title: "Railsの勉強をした", content: "modelを作成します。", user_id: 1, created_at: "2023-07-24 23:35:14", updated_at: "2023-07-24 23:35:14">, #<Post id: 5, title: "Rails楽しい", content: "controllerを作成します。", user_id: 1, created_at: "2023-07-24 23:37:20", updated_at: "2023-07-24 23:37:20">]>
問題10の回答
Q. 特定のUserが作成したPostを作成日の新しい順に取得するコマンドを書いてください。
irb(main):00:0> user
=> #<User id: 1, name: "ippei shimizu", email: "test@example.com", created_at: "2023-07-24 11:49:41", updated_at: "2023-07-24 11:49:41">
irb(main):00:0> user.posts.order(created_at: "DESC")
Post Load (0.5ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? ORDER BY "posts"."created_at" DESC LIMIT ? [["user_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::AssociationRelation [#<Post id: 5, title: "Rails楽しい", content: "controllerを作成します。", user_id: 1, created_at: "2023-07-24 23:37:20", updated_at: "2023-07-24 23:37:20">, #<Post id: 4, title: "Railsの勉強をした", content: "modelを作成します。", user_id: 1, created_at: "2023-07-24 23:35:14", updated_at: "2023-07-24 23:35:14">, #<Post id: 3, title: "ippeiの投稿", content: "今日はお散歩をしました", user_id: 1, created_at: "2023-07-24 23:25:51", updated_at: "2023-07-24 23:25:51">]>
ChatGPTに確認してもらう
素晴らしい!全ての回答が適切です。以下に各問題に対する詳細な解説を記載します。
問題1
user.posts.countで、特定のユーザーが作成したポストの数を取得することができます。ここでは、UserとPostの間に定義されたhas_many関連付けを利用しています。この関連付けにより、特定のUserオブジェクトから関連するPostオブジェクトにアクセスすることができます。
問題2
user.posts.where('title LIKE ?', "%Rails%")により、特定のユーザーが作成したポストのうち、タイトルに特定のキーワード("Rails")が含まれるものをすべて取得できます。ここでも、UserとPostの間のhas_many関連付けを利用しています。
問題3
User.where(email: [nil,""])で、Userのemailが未設定のものがあるかどうかを確認できます。ここではwhereメソッドを使っています。このメソッドは、指定した条件に一致するレコードを全て取得します。
問題4
バリデーションはモデル層でデータの整合性を担保するための機能です。ここでは、validatesメソッドを使用して、名前が必須であること(presence: true)、Eメールが一意であること(uniqueness: true)を指定しています。
問題5
バリデーションのチェックはvalid?メソッドで行います。ここでは、名前が空の新しいユーザー(user5)を作成し、user5.valid?を実行してバリデーションをチェックしています。結果がfalseとなり、名前が空ではならないというバリデーションが働いていることがわかります。
問題6
ここでは、インスタンスメソッドinfoを定義し、Postのタイトルと内容を連結した文字列を返すようにしています。selfは、現在のオブジェクト(この場合はPostオブジェクト)を指します。
問題7
問題6で作成したinfoメソッドを使用して、特定のPostのタイトルと内容を表示するためには、Postオブジェクト(この場合はpost)に対してinfoメソッドを呼び出します。これにより、Postのタイトルと内容が連結した文字列が表示されます。
問題8
スコープは、頻繁に使用するクエリをモデル内に定義して名前を付け、その名前をメソッドとして呼び出すことができるようにするRailsの機能です。ここでは、タイトルまたは内容に特定のキーワードが含まれるPostを取得するクエリをwith_keywordという名前で定義しています。
問題9
問題8で作成したスコープwith_keywordを使用して、特定のキーワード("Rails")を含むPostを取得します。スコープを使用すると、コードが短くて読みやすくなり、再利用性も向上します。
問題10
特定のUserが作成したPostを作成日の新しい順に取得するためには、orderメソッドを使用します。このメソッドは、指定したカラムに基づいてレコードを並べ替えます。この場合、created_at: "DESC"を指定しているので、作成日時の新しい順にレコードが並び替えられます。
最後に
valid?
メソッドを使用して、バリデーションが正しく設定されているかの確認や、メソッドを定義して、コンソールでメソッドを実行して確認するなど、実際のアプリケーション開発でも使えることを学べました。また、chatGPTは回答の正誤判定だけでなく、解説も詳しく行なってくれるので、理解度を深めることができまし。
Discussion