この記事は GMOアドマーケティング Advent Calendar 2023 4日目の記事です。
はじめに
こんにちは。 GMOアドマーケティングの石丸です。
昨年のアドベントカレンダーでは Rails 7 で追加された ComparisonValidator
について紹介しました。
2023年10月に Rails 7.1 がリリースされたため、今回の記事では Rails 7.1 から新たに追加された
ActiveRecord#Enum
のオプション instance_methods
について解説します。
概要
ActiveRecord#Enum
はデータ取得や更新のためのメソッドが自動で生成されますが、Rails 7.1 で導入された instance_methods
オプションに false
を設定することで、メソッドの生成を無効にすることが可能です。
このオプションにより、既存のメソッド名との競合を避けることができ、必要に応じてより明示的なメソッド名を宣言することが可能になります。
検証用の環境作成
実際の動作を確認するため、Rails 7.1の環境を構築し、User
モデルに status
の enum
を定義してダミーのデータを生成しました。
今回はRails 7.1.2, Ruby 3.2.2の環境で構築しました。
1 2 |
# 雛形の作成 rails g scaffold User name:string status:integer |
1 2 3 4 |
# enumの設定 class User < ApplicationRecord enum :status, [:active, :inactive, :archived] end |
1 2 3 4 |
# データ生成 User.create(name: "Jimmy", status: :active) User.create(name: "Robert", status: :inactive) User.create(name: "John", status: :archived) |
ActiveRecord#Enumの動作確認
基本動作の確認
まずは enum
が自動で生成したメソッドの動作を確認してみましょう。
デフォルトでは active?
や inactive?
といったメソッドが自動で生成されます。
1 2 3 4 5 6 7 |
irb(main):001> user = User.first User Load (1.6ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1 => #<User:0x0000ffff9473c050 id: 1, name: "Jimmy", status: "active", created_at: xxxxx, updated_at: xxxxx> irb(main):002> user.active? => true irb(main):003> user.inactive? => false |
instance_methodsオプション
続いて instance_methods: false
を設定して挙動を確認してみましょう。
1 2 3 |
class User < ApplicationRecord enum :status, [:active, :inactive, :archived], instance_methods: false end |
1 2 3 4 5 6 7 8 |
irb(main):001> user = User.first User Load (1.3ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1 => #<User:0x0000ffff9ed2ffc0 id: 1, name: "Jimmy", status: "active", created_at: xxxxx, updated_at: xxxxx> irb(main):002> user.active? /usr/local/bundle/gems/activemodel-7.1.2/lib/active_model/attribute_methods.rb:489:in `method_missing': undefined method `active?' for #<User id: 1, name: "Jimmy", status: "active", created_at: "xxxxx", updated_at: "xxxxx"> (NoMethodError) Did you mean? acts_like? irb(main):003> user.inactive? /usr/local/bundle/gems/activemodel-7.1.2/lib/active_model/attribute_methods.rb:489:in `method_missing': undefined method `inactive?' for #<User id: 1, name: "Jimmy", status: "active", created_at: "xxxxx", updated_at: "xxxxx"> (NoMethodError) |
active?
や inactive?
が NoMethodError
となり、メソッドが生成されてないことが確認できました。
scopesオプション
似たようなオプションで scopes: false
がありますが、こちらは名前の通りデフォルトで生成されるscopeを無効にするオプションです。
1 2 3 4 5 6 7 8 9 10 11 |
# 「active」のデータを取得 irb(main):001> User.active User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`status` = 0 /* loading for pp */ LIMIT 11 => [#<User:0x0000ffff89d07940 id: 1, name: "Jimmy", status: "active", created_at: xxxxx, updated_at: xxxxx>] # 「active」以外のデータを取得 irb(main):002> User.not_active User Load (4.6ms) SELECT `users`.* FROM `users` WHERE `users`.`status` != 0 /* loading for pp */ LIMIT 11 => [#<User:0x0000ffff88457800 id: 2, name: "Robert", status: "inactive", created_at: xxxxx, updated_at: xxxxx>, #<User:0x0000ffff884576c0 id: 3, name: "John", status: "archived", created_at: xxxxx, updated_at: xxxxx>] |
scopes: false
を設定して挙動を確認してみます。
1 2 3 |
class User < ApplicationRecord enum :status, [:active, :inactive, :archived], scopes: false end |
1 2 3 4 5 |
irb(main):001> User.active /usr/local/bundle/gems/activerecord-7.1.2/lib/active_record/dynamic_matchers.rb:22:in `method_missing': undefined method `active' for User:Class (NoMethodError) Did you mean? acts_like? irb(main):002> User.not_active /usr/local/bundle/gems/activerecord-7.1.2/lib/active_record/dynamic_matchers.rb:22:in `method_missing': undefined method `not_active' for User:Class (NoMethodError) |
デフォルトのscopeが無効になり、 NoMethodError
となることが確認できました。
まとめ
今回はRails 7.1で追加された ActiveRecord#Enum
の instance_methods
オプションについて紹介しました。
自動でメソッドやスコープが用意されることは便利なケースもありますが、プロジェクトによっては競合が発生することや、より明示的なメソッド名を定義したいケースがあるため、今回紹介したオプションを活用することで、より管理しやすいアプリケーションを構築することができるでしょう。
ActiveRecord#Enum
には prefix
や suffix
といったオプションも用意されているため、それぞれのオプションを組み合わせることでコードの可読性を高めることができる場合があるため、それぞれの環境に合わせてカスタマイズするとよいと思います。
参考リンク
option to disable all methods that ActiveRecord.enum generates by alfie-max · Pull Request #46490 · rails/rails (参照日: 2023年11月15日)
告知
明日はharuさんによる「【Git】新規ローカルブランチ作成時に自動でFirst Commitを行う for Four Keys」です。
引き続き、GMOアドマーケティング Advent Calendar 2023 をお楽しみください!
■採用ページはこちら!
https://recruit.gmo-ap.jp/
■GMOアドパートナーズ 公式noteはこちら!
https://note.gmo-ap.jp/
2016卒のWebエンジニア。
採用やマネジメントもやってます。