Phạm vi trong Rails là gì và tại sao nó lại hữu ích?
Chà…
Phạm vi là các truy vấn tùy chỉnh mà bạn xác định bên trong các mô hình Rails của mình với scope
phương pháp.
Mọi phạm vi có hai đối số :
- Tên mà bạn sử dụng để gọi phạm vi này trong mã của mình.
- Một lambda, thực hiện truy vấn.
Có vẻ như thế này :
class Fruit < ApplicationRecord scope :with_juice, -> { where("juice > 0") } end
Kết quả của việc gọi một phạm vi, bạn sẽ nhận được một ActiveRecord::Relation
đối tượng.
Có nghĩa là bạn có thể xâu chuỗi và kết hợp các phạm vi!
Ví dụ :
Fruit.with_juice.with_round_shape.first(3)
Bây giờ :
Còn nhiều điều cần tìm hiểu về phạm vi Rails, vì vậy chúng ta hãy tiếp tục khám phá chủ đề này.
Khi nào thì sử dụng Scopes?
Được rồi, phạm vi rất tuyệt, nhưng bạn nên sử dụng chúng khi nào?
Hãy xem một ví dụ.
def index @books = Book.where("LENGTH(title) > 20") end
Đây là một index
hành động điều khiển muốn hiển thị sách có tiêu đề dài hơn 20 ký tự.
Nó ổn.
Nhưng nếu bạn muốn sử dụng truy vấn này ở những nơi khác, bạn sẽ có mã trùng lặp.
Mã trùng lặp khiến dự án của bạn khó bảo trì hơn.
Hãy chuyển truy vấn này vào một phạm vi.
Như thế này :
class Book scope :with_long_title, -> { where("LENGTH(title) > 20") } end
Bây giờ hành động của bộ điều khiển của chúng tôi trông giống như thế này :
def index @books = Book.with_long_title end
Tốt!
Cách sử dụng Rails Scopes với các đối số
Bạn có thể muốn giới thiệu một biến vào một phạm vi để bạn có thể làm cho nó linh hoạt hơn.
Đây là cách thực hiện :
class Book scope :with_long_title, ->(length) { where("LENGTH(title) > ?", length) } end
Dấu chấm hỏi (?
) là một trình giữ chỗ, nó sẽ được thay thế bằng giá trị của length
. Điều này làm cho mã của bạn an toàn hơn.
Nếu bạn muốn một giá trị mặc định :
class Book scope :with_long_title, ->(length = 20) { where("LENGTH(title) > ?", length) } end
Hãy thử!
Phạm vi so với Phương pháp Lớp
Phạm vi không làm bất cứ điều gì kỳ diệu hoặc siêu đặc biệt.
Chúng chỉ là phương pháp.
Trên thực tế… Bạn có thể làm điều tương tự bằng cách sử dụng các phương thức lớp!
Như thế này :
class Fruit def self.with_juice where("juice > 0") end end
Nhưng có những lợi thế về thiết kế khi sử dụng phạm vi thay vì các phương thức lớp.
Đây là lý do tại sao :
- Phạm vi dẫn đến mã rõ ràng hơn do cú pháp của chúng
- Phạm vi được sử dụng cho chính xác một thứ, vì vậy, bạn biết mình nhận được gì ngay khi nhìn thấy một thứ
- Phạm vi không bị trộn lẫn với các phương pháp khác, vì vậy chúng dễ phát hiện hơn
Về mặt chức năng, sự khác biệt duy nhất là phạm vi đảm bảo ActiveRecord::Relation
và các phương thức lớp thì không.
Điều này giúp bạn tránh lỗi khi phạm vi của bạn không trả về.
Không sử dụng phạm vi mặc định
Phạm vi mặc định là phạm vi được tự động áp dụng cho mô hình của bạn.
Ví dụ :
class Post default_scope { where(published: true) } end
Vâng!
Phạm vi mặc định rất hấp dẫn.
Nhưng chúng thường là lựa chọn sai vì có thể bạn sẽ quên rằng bạn đã xác định chúng, gặp phải các lỗi lạ và lãng phí thời gian quý báu để gỡ lỗi.
Với điều đó đã nói…
Nếu bạn phải làm việc với phạm vi mặc định, bạn có thể cần sử dụng unscoped
phương pháp để vô hiệu hóa tất cả các phạm vi hiện đang được áp dụng.
Xem hướng dẫn bằng video
Tóm tắt
Làm tốt lắm! Kết quả của việc đọc bài viết này, bạn đã học được cách sử dụng phạm vi Rails một cách hiệu quả nhất.
Đừng quên áp dụng kiến thức mới này vào thực tế để bạn có thể ghi nhớ cách thức hoạt động của nó.
Cảm ơn vì đã đọc. 🙂