【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つの読書方法を紹介します。最後まで読めば効率よくインプットできるようになります。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

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

コメント

コメントする

目次