ActiveRecordのmergeを使ってみる (Rails)

December 25, 2022

確認環境

$ bundle exec ruby --version
ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-darwin19]
$ bundle exec rails --version
Rails 6.0.4.6

データ準備

テーブル定義確認

$ rails db
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
sqlite> .schema posts
CREATE TABLE IF NOT EXISTS "posts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar, "description" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "status" integer, "user_id" integer);
sqlite> .schema users
CREATE TABLE IF NOT EXISTS "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "email" varchar DEFAULT '' NOT NULL, "encrypted_password" varchar DEFAULT '' NOT NULL, "reset_password_token" varchar, "reset_password_sent_at" datetime, "remember_created_at" datetime, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email");
CREATE UNIQUE INDEX "index_users_on_reset_password_token" ON "users" ("reset_password_token");

検証コードを実装

app/models/user.rb

class User < ApplicationRecord
  has_many :posts
end

app/models/post.rb

class Post < ApplicationRecord
end
$ rails c
irb(main):001:0> u = User.last
  User Load (0.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1]]
irb(main):002:0> u.posts.merge(Post.where('id >= 5'))
  Post Load (0.3ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? AND (id >= 5) LIMIT ?  [["user_id", 1], ["LIMIT", 11]]

また、下記のように書けます。

$ rails c
irb(main):001:0> u = User.last
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1]]
irb(main):002:0> u.posts.where('id >= 5')
  Post Load (0.3ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? AND (id >= 5) LIMIT ?  [["user_id", 1], ["LIMIT", 11]]

SHARE

Profile picture

Written by tamesuu