使用 Arel 寫出好看的 Left Join
- Backend
- 20 Oct, 2020
之前想要寫有條件的 left join 都會寫成 raw SQL query 的字串,但是其實也可以用 Arel 寫出比較好看的程式碼。
假設有個 DB 的 schema 長這樣:
create_table "posts", force: :cascade do |t|
t.string "title"
t.boolean "active"
t.integer "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
我想要寫出這種 Query:
SELECT users.name, posts.title FROM "users" LEFT OUTER JOIN "posts" ON "users"."id" = "posts"."user_id" AND "posts"."active" = 1
可以用 raw SQL query 字串的方式寫:
User.joins('LEFT OUTER JOIN "posts" ON "users"."id" = "posts"."user_id" AND "posts"."active" = 1')
.pluck('users.name', 'posts.title')
其實也可以用 Arel 來組出 join clause:
users_table = User.arel_table
posts_table = Post.arel_table
join_clause = users_table.join(posts_table, Arel::Nodes::OuterJoin)
.on(users_table[:id].eq(posts_table[:user_id]).and(posts_table[:active].eq(true)))
.join_sources
User.joins(join_clause).pluck('users.name', 'posts.title')