RailsのActiveRecordで使える便利メソッドを集めてみました。
first_or_create
条件に一致したレコードを持っている場合に一致した最初のレコードを、ない場合は新規作成をするメソッドです。このメソッドは引数にブロックを渡すことができ、属性を保存することができます。
User.where(email: 'hoge@example.com').first_or_create do |user|
user.name = 'sakai'
user.phone = '080-1234-5678'
end
ただし、属性の更新をすることはできません。これで結構ハマってしまうことがありました。
user = User.create(email: 'hoge@example.com')
User.where(email: 'hoge@example.com').first_or_create do |user|
user.name = 'sakai'
user.phone = '080-1234-5678'
end
=> #<User id: 4, email: "hoge@example.com", name: nil, phone: nil, created_at: "2021-07-31 22:06:55", updated_at: "2021-08-12 00:48:23">
find_each
eachメソッドは全件データをメモリに展開して処理を開始します。それだと十分にメモリに載るデータ量であれば問題ないですが、数百万、数千万というデータ量になってくると処理が重くなることがあります。そういう場合にfind_eachを使います。
find_eachを使うとORDER BYでid順に並び替えて、デフォルトでは1000件ごとに処理を行います。
User.where(age: 28).each do |user|
user.name = '28歳の人'
user.save
end
User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`age` = 28
User Update (0.7ms) UPDATE `users` SET `name` = '28歳の人', `updated_at` = '2021-08-14 21:30:30' WHERE `users`.`id` = 4
User.where(age: 28).find_each do |user|
user.name = '28歳の人'
user.save
end
User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`age` = 28 ORDER BY `users`.`id` ASC LIMIT 1000
User Update (0.5ms) UPDATE `users` SET `first_name` = '28歳の人', `updated_at` = '2021-08-14 21:36:52' WHERE `users`.`id` = 4
ActiveRecord::AttributeMethods#attributes
カラムの属性値をハッシュ形式で取ることができます。
article.attributes
=> {"id"=>1,
"title"=>"Harry Potter And The Sorcerer’s Stone",
"content"=>"aa",
"created_at"=>Tue, 13 Dec 2022 17:36:38.762864000 JST +09:00,
"updated_at"=>Wed, 14 Dec 2022 06:39:02.427697000 JST +09:00,
"is_public"=>true,
"priority"=>"important"}
このメソッドは下のようにカラム名と同じ名前のインスタンスメソッドを持っている場合に便利です。
class Article < ApplicationRecord
def title
# title カラムの値を大文字にする
self.attributes[:title]&.upcase
end
end
# 上のメソッドを通過するので大文字で表示される
article.title
=> "HARRY POTTER AND THE SORCERER’S STONE"
# カラム属性値経由で取得するため、上のメソッドを通過しない
article.attributes["title"]
=> "Harry Potter And The Sorcerer’s Stone"
# こちらでも同じ
article["title"]
=> "Harry Potter And The Sorcerer’s Stone"
個人的には attributes メソッドを使ったほうが、読みやすいので好きです。
さいごに
またなにかあれば追記していこうと思います。