「RailsでActive Recordインスタンスの属性の真偽値を反転させたい」
こういった方向けに記事を書きます。
最後まで読めばたった1行で属性の真偽値を反転させられるようになります。
この記事を書いているぼくは実務経験1年。独学で未経験から従業員300名以上の自社開発企業へ転職しました。実務ではVue.jsとRailsを毎日書いています。
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!の挙動の違い
toggle
とtoggle!
では微妙に挙動が異なります。
最大の違いは、データベースに変更が保存されるかです。
実際に挙動を見てみましょう。
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
メソッドについて解説しました。
実務ではアカウントの有効/無効、お気に入りへの追加/削除など、使える場面がそれなりにありそうです。
みなさんの参考になれば幸いです。
参考文献
- https://railsdoc.com/page/toggle
- https://github.com/rails/rails/blob/984c3ef2775781d47efa9f541ce570daa2434a80/activerecord/lib/active_record/persistence.rb#L882
コメント