【Rails】toggleメソッドで真偽値を反転させる

「RailsでActive Recordインスタンスの属性の真偽値を反転させたい」

こういった方向けに記事を書きます。

最後まで読めばたった1行で属性の真偽値を反転させられるようになります。

この記事を書いているぼくは実務経験1年。独学で未経験から従業員300名以上の自社開発企業へ転職しました。実務ではVue.jsとRailsを毎日書いています。

この記事で使用するバージョンはRuby 3.1.4, Rails 6.1.7.7です。

目次

toggleメソッドで真偽値を反転させる

結論として、Ruby on Railsで用意されているtoggleメソッドを使います。

toggleメソッドとは?

toggleメソッドはboolean型の属性を対象に、反対の真偽値を割り当てるメソッドです。

ActiveRecordインスタンスに対応するメソッドです。

以下のように、引数に更新したい属性を指定して使用します。

[1] pry(main)> user = User.first
  User Load (2.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: false,
 note: "">

# activated の真偽値を反転
[2] pry(main)> user.toggle(:activated)
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: true, # true に変わった
 note: "">

# activated の真偽値をもう一度反転
[3] pry(main)> user.toggle(:activated)
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: false, # false に戻った
 note: "">

boolean型以外の属性をtoggleメソッドで更新した場合の挙動は、データ型によって変わります。

integer 型の場合

integer型の属性を更新した場合、 0 が設定されます。

再度toggleメソッドで更新すると 1 になり、以降は 0 と 1 を繰り返します。

[1] pry(main)> user = User.last
  User Load (2.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
=> #<User:0x0000ffff7d502288
 id: 60,
 username: "lastuser",
 password: "hogehoge",
 email: "last@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: nil,
 activated: false,
 note: "">

# id を更新
[2] pry(main)> user.toggle(:id)
=> #<User:0x0000ffff9aa98180
 id: 0,  # 0 に変わった
 username: "lastuser",
 password: "hogehoge",
 email: "last@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: nil,
 activated: false,
 note: "">

# id を再度更新
[3] pry(main)> user.toggle(:id)
=> #<User:0x0000ffff9aa98180
 id: 1,  # 1 に変わった
 username: "lastuser",
 password: "hogehoge",
 email: "last@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: nil,
 activated: false,
 note: "">

string 型の場合

string型の属性を更新した場合、”0″ が設定されます。

再度toggleメソッドで更新しても “0” のままです。

[1] pry(main)> user = User.first
  User Load (2.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: false,
 note: "">

# email を更新
[2] pry(main)> user.toggle(:email)
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "0",  # "0" に変わった
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: true,
 note: "">

# email を再度更新
[3] pry(main)> user.toggle(:activated)
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "0",  # "0" のまま
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: false, # false に戻った
 note: "">

toggleとtoggle!の挙動の違い

toggletoggle!では微妙に挙動が異なります。

最大の違いは、データベースに変更が保存されるかです。

実際に挙動を見てみましょう。

toggle の場合

まずはRailsコンソールに入り、前と同じようにboolean型の属性を更新します。

[1] pry(main)> user = User.first
  User Load (2.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: false,
 note: "">

# activated の真偽値を反転
[2] pry(main)> user.toggle(:activated)
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: true, # true に変わった
 note: "">

更新したら一度Railsコンソールから抜け、再度入り直して同じユーザーの情報を取得します。

[1] pry(main)> user = User.first
  User Load (2.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: false, # false に戻っている
 note: "">

このようにtoggleの場合は変更がデータベースに保存されません。

toggleを使った上でデータベースに保存したい場合は、user.toggle(:activated)の後でuser.saveを実行する必要があります。

toggle! の場合

同じことをtoggle!でやってみます。

[1] pry(main)> user = User.first
  User Load (2.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: false,
 note: "">

# activated の真偽値を反転
[2] pry(main)> user.toggle!(:activated)
  TRANSACTION (0.4ms)  BEGIN
  User::IndividualUser Update (1.4ms)  UPDATE `users` SET `users`.`updated_at` = '2024-06-18 10:27:51', `users`.`activated` = TRUE WHERE `users`.`id` = 1
  TRANSACTION (2.9ms)  COMMIT

更新したら一度Railsコンソールから抜け、再度入り直して同じユーザーの情報を取得します。

[1] pry(main)> user = User.first
  User Load (2.3ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User:0x0000ffff9aa98180
 id: 1,
 username: "sampleuser",
 password: "hogehoge",
 email: "test@example.jp",
 created_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 updated_at: Fri, 17 Nov 2023 16:53:16.000000000 JST +09:00,
 resigned_at: nil,
 birthday: Fri, 11 May 1979,
 activated: true, # true のまま
 note: "">

toggle!を使った場合は変更がデータベースに保存されました。

おわりに

この記事ではActiveRecordインスタンスが持つ boolean 型の属性に反対の真偽値を割り当てるtoggleメソッドについて解説しました。

実務ではアカウントの有効/無効、お気に入りへの追加/削除など、使える場面がそれなりにありそうです。

みなさんの参考になれば幸いです。

参考文献

技術書が好きなエンジニア向け

あわせて読みたい
【エンジニア向け】効率的な技術書の読み方5選【経験談】 スキルアップに直結させるための効率的な技術書の読み方を知りたくないですか?この記事ではエンジニア向けに効果的なインプットのための技術書の読み方を5つ紹介します。最後まで読めば自分に合う読み方が1つくらい見つかるはずです。ぜひご一読ください。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

未経験でSESから従業員300名以上の自社開発企業に転職しました。業務や個人開発で直面した問題や、転職・学習の経験を発信していきます。

コメント

コメントする

目次