0

How to Use Scopes in Ruby on Rails

Scope in Rails là gì & Tại sao nó lại hữu ích.

Scope là một custom queries mà bạn có thể define trong Model

Every scope takes two arguments:

  1. Tên (name) mà bạn dùng để gọi scope trong code của mình
  2. A lambda, để thực hiện câu truy vấn

Ví dụ:

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

Kết quả sau khi gọi một scope, bạn sẽ nhận được ActiveRecord::Relation object. Có nghĩa là bạn có thể chain & combine scopes! Ví dụ:

Fruit.with_juice.with_round_shape.first(3)

Có nhiều điều cần tìm hiểu về Rails scopes. Vì vậy chúng ta hãy tiếp tục khám phá chủ đề này.

When To Use Scopes? Ok, scopes rất tuyệt, nhưng bạn nên sử dụng chúng khi nào?

Hãy xem ví dụ dưới đây:

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

Đây là index controller action để hiển thị tất cả books với titles có độ dài > 20 ký tự.

Nhưng nếu bạn sử dụng câu query này ở nơi khác, code bạn sẽ bị trùng lặp. Trùng lặp code sẽ làm cho project khó maintain. Hãy move câu query vào scope

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

Tại controller action code

def index
  @books = Book.with_long_title
end

How to Use Rails Scopes With Arguments

Bạn có thể truyền biến vào trong scope để có thể sủ dụng linh hoạt hơn

Cách sử dụng

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

Dấu chấm hỏi (?) là một placeholder, nó sẽ được thay thế bằng giá trị của biến length truyền vào khi gọi scope. Điều này giúp cho code được an toàn hơn.

Gán giá trị mặc định

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

Scope vs Class Method

Scopes không có gì kỳ diệu hay đặc biệt. Chúng chỉ là methods. Trên thực tế... Bạn có thể làm điều tương tự bằng cách sử dụng class methods!

Như thế này:

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

Nhưng có những lợi thế khi sử dụng scope so với class methods

Lý do:

  • Dùng scope giúp code bạn clean hơn bởi cú pháp của nó.
  • Scope được sử dụng cho chính xác một nhiệm vụ. Bạn có thể hiểu ngay mục đích của scope khi lần đầu sử dụng nó.
  • Scope không mixed với các method khác

Về mặt chức năng sự khác biệt của scope là kết quả trả về là một ActiveRecord::Relation, class method thì không. Điều này giúp bạn tránh được lỗi khi scope returns nothing.

Don’t Use Default Scopes default_scope sẽ tự động được gọi mỗi khi gọi 1 scope bất kỳ nếu bạn khai báo trong model

Ví dụ:

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

Yes!. default_scope rất tiện khai báo 1 lần nó sẽ applied vào tất các scope trong model. Nhưng đó là lựa chọn sai khi sử dụng nó, bới bạn có thể sẽ quên là có nó trong model của mình. Gặp lỗi lạ không mong muốn, làm tốn thời gian debbug.

Bạn có thể dùng unscoped method để vô hiệu hóa default_scope.

Summary Qua bài viết này bạn đã cơ bản học được cách sử dụng scope trong rails.

Đừng quên áp dụng kiến thức học được vào dự án của mình để hiểu được cách thức hoạt động của nó nhé.

Cám ơn bạn đã đọc. 🙂

Nguồn tham khảo: https://www.rubyguides.com/2019/10/scopes-in-ruby-on-rails/


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí