Sử dụng Arel trong Rails
Bài đăng này đã không được cập nhật trong 3 năm
Giới thiệu
Hầu hết các developer đều quen thuộc với ActiveRecord queries, Nhưng không biết hoặc không biết nhiều với Arel. Vậy Arel nó là gì? - Arel là thư viện đã được giới thiệu trong Rails 3, công cụ quản lý truy vấn dữ liệu SQL, nó cho phép bạn customize các câu queries, bạn không cần phải sử dụng các SQL plain.
- Arel là một công cụ tuyệt vời, nó cung cấp những câu query đầy đủ, nó giúp cho việc truy vấn dữ liêu của ta được rõ ràng và minh bạch
Cách sử dụng trong ứng dụng rails
-
Tạo Data Ta tạo 2 table bên dưới để dùng để minh họa cho các câu truy vấn
ActiveRecord::Schema.define(version: 20180128081302) do create_table "payments", force: :cascade do |t| t.string "order_id" t.float "amount" t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["user_id"], name: "index_payments_on_user_id" end create_table "users", force: :cascade do |t| t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "email" t.string "password_digest" t.string "status" end end
-
Arel Table
Class mà ta sử dụng chủ yếu khi làm việc với Arel đó là Arel::Table. Để get Arel::Table instance của một model ta có cách:
- Sử dụng class method của ActiveRecord
User.arel_table
- Sử dụng constructor của class Arel::table
Arel::Table.new(:users)
- Một số câu truy vấn cơ bản
- Truy vấn với điều kiện where
Ta get tất cả các User có password_digets is nil
User.where(users[:password_digest].eq nil) User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."password_digest" IS NULL LIMIT ? [["LIMIT", 11]]
- Comparison operators =, !=, <, >, <=, >=, IN:
- Truy vấn với điều kiện where
Ta get tất cả các User có password_digets is nil
users.where(users[:age].eq(10)).project(Arel.sql('*'))
=> SELECT * FROM "users" WHERE "users"."age" = 10
users.where(users[:age].not_eq(10)).project(Arel.sql('*'))
=> SELECT * FROM "users" WHERE "users"."age" != 10
users.where(users[:age].lt(10)).project(Arel.sql('*'))
=> SELECT * FROM "users" WHERE "users"."age" < 10
users.where(users[:age].gt(10)).project(Arel.sql('*'))
=> SELECT * FROM "users" WHERE "users"."age" > 10
users.where(users[:age].lteq(10)).project(Arel.sql('*'))
=> SELECT * FROM "users" WHERE "users"."age" <= 10
users.where(users[:age].gteq(10)).project(Arel.sql('*'))
=> SELECT * FROM "users" WHERE "users"."age" >= 10
users.where(users[:age].in([20, 16, 17])).project(Arel.sql('*'))
=> SELECT * FROM "users" WHERE "users"."age" IN (20, 16, 17)
- Bitwise operators &, |, ^, <<, >>:
users.where((users[:bitmap] & 16).gt(0)).project(Arel.sql('*'))
# => SELECT * FROM "users" WHERE ("users"."bitmap" & 16) > 0
users.where((users[:bitmap] | 16).gt(0)).project(Arel.sql('*'))
# => SELECT * FROM "users" WHERE ("users"."bitmap" | 16) > 0
users.where((users[:bitmap] ^ 16).gt(0)).project(Arel.sql('*'))
# => SELECT * FROM "users" WHERE ("users"."bitmap" ^ 16) > 0
users.where((users[:bitmap] << 1).gt(0)).project(Arel.sql('*'))
# => SELECT * FROM "users" WHERE ("users"."bitmap" << 1) > 0
users.where((users[:bitmap] >> 1).gt(0)).project(Arel.sql('*'))
# => SELECT * FROM "users" WHERE ("users"."bitmap" >> 1) > 0
users.where((~ users[:bitmap]).gt(0)).project(Arel.sql('*'))
# => SELECT * FROM "users" WHERE ~ "users"."bitmap" > 0
- Viết scope bằng arel
class User < ApplicationRecord
has_many :payments
has_secure_password
scope :inactive_users, ->{where(valid_updated_at).or(valid_created_at)}
class << self
def valid_updated_at
arel_table[:updated_at].lteq Time.now.utc
end
def valid_created_at
arel_table[:created_at].gteq Time.now.utc
end
end
end
All rights reserved