Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Thành Thạo Scope trong Ruby on Rails: Hướng Dẫn Thực Hành

Scope trong Rails là gì và tại sao nó hữu ích?

Scope là các truy vấn tùy chỉnh bạn định nghĩa bên trong model Rails bằng phương thức scope.

Mỗi scope nhận hai đối số:

  1. Một tên, dùng để gọi scope này trong code.
  2. Một lambda, triển khai truy vấn.

Cú pháp trông như sau:

class Fruit < ApplicationRecord
  scope :with_juice, -> { where("juice > 0") }
end

Kết quả khi gọi một scope là một đối tượng ActiveRecord::Relation.

Điều này có nghĩa là bạn có thể chuỗi (chain) và kết hợp các scope!

Ví dụ:

Fruit.with_juice.with_round_shape.first(3)

Khi Nào Nên Sử Dụng Scope?

Scope rất hay, nhưng khi nào nên dùng chúng? Xem ví dụ sau:

def index
  @books = Book.where("LENGTH(title) > 20")
end

Đây là action index trong controller muốn hiển thị các sách có tiêu đề dài hơn 20 ký tự.

Code này chạy tốt. Nhưng nếu bạn muốn dùng truy vấn này ở nơi khác, bạn sẽ phải lặp lại code.

Code lặp lại khiến dự án khó bảo trì hơn. Hãy chuyển truy vấn này vào một scope.

Như sau:

class Book
  scope :with_long_title, -> { where("LENGTH(title) > 20") }
end

Bây giờ action controller trông như sau:

def index
  @books = Book.with_long_title
end

Gọn gàng hơn!

Cách Sử Dụng Scope Với Tham Số

Bạn có thể muốn đưa một biến vào scope để làm cho nó linh hoạt hơn.

Cách làm:

class Book
  scope :with_long_title, ->(length) { where("LENGTH(title) > ?", length) }
end

Dấu hỏi (?) là placeholder, sẽ được thay thế bởi giá trị của length. Điều này làm cho code an toàn hơn (tránh SQL injection).

Nếu muốn giá trị mặc định:

class Book
  scope :with_long_title, ->(length = 20) { where("LENGTH(title) > ?", length) }
end

Scope vs Phương Thức Lớp (Class Method)

Scope không làm gì phép màu cả. Chúng chỉ là các phương thức.

Thực tế... Bạn có thể làm điều tương tự bằng class method!

Ví dụ:

class Fruit
  def self.with_juice
    where("juice > 0")
  end
end

Nhưng scope có ưu điểm thiết kế so với class method:

  • Scope tạo ra code sạch hơn nhờ cú pháp riêng
  • Scope chỉ dùng cho một mục đích duy nhất, nên bạn biết ngay mình nhận được gì khi thấy nó
  • Scope không bị lẫn lộn với các phương thức khác, dễ dàng nhận diện hơn

Về mặt chức năng, khác biệt duy nhất là scope đảm bảo trả về ActiveRecord::Relation, còn class method thì không. Điều này giúp tránh lỗi khi scope không trả về kết quả.

Không Nên Dùng Default Scope

Default scope là scope được áp dụng tự động cho model.

Ví dụ:

class Post
  default_scope { where(published: true) }
end

Default scope rất hấp dẫn. Nhưng thường là lựa chọn sai vì bạn dễ quên chúng đã được định nghĩa, dẫn đến lỗi kỳ lạ và tốn thời gian debug.

Nếu buộc phải làm việc với default scope, bạn có thể dùng phương thức unscoped để vô hiệu hóa tất cả scope đang áp dụng.

Tóm Tắt

Chúc mừng! Bạn đã học cách sử dụng Rails scope hiệu quả nhất. Đừng quên áp dụng kiến thức mới này vào thực tế để nhớ lâu. Cảm ơn bạn đã đọc! 🙂