Phạm vi / tên_scope trong đường ray là gì?


105

Gần đây tôi đã bắt đầu thực tập. Chủ nhân của tôi sử dụng ruby ​​trên đường ray và tôi thường xuyên gặp phải những cú pháp mới mà tôi cần phải tra cứu để hiểu. Tôi đã đi khắp nơi để tìm kiếm lời giải thích tốt về tên_scope, nhưng những gì tôi tìm thấy cho đến nay hầu hết là các bài đăng trên blog dành lời khen ngợi cho nó, thay vì một định nghĩa hoặc giới thiệu thẳng thắn.

Chính xác thì tên_scope (bây giờ được gọi đơn giản là phạm vi) trong ruby ​​trên đường ray là gì?



2
Bài đăng trên blog này là vô giá đối với tôi khi biết được phạm vi có tên: ryandaigle.com/articles/2008/8/20/…
Peter Brown

@notapatch liên kết đã chết bạn có cái khác không?
mbigras

Ryan Daigle: Đặt tên Phạm vi: nó không chỉ cho điều kiện, Ya Know ?: web.archive.org/web/20160306110506/http://...
notapatch

Câu trả lời:


212

Phạm vi là một tập hợp con của một tập hợp. Nghe có vẻ phức tạp? Nó không phải. Hãy tưởng tượng điều này:

Bạn có Người dùng. Bây giờ, một số Người dùng đó đã đăng ký nhận bản tin của bạn. Bạn đã đánh dấu những người nhận được bản tin bằng cách thêm trường vào Cơ sở dữ liệu người dùng (user.subscribe_to_newsletter = true). Đương nhiên, đôi khi bạn muốn có được những Người dùng đã đăng ký nhận bản tin của bạn.

Tất nhiên, bạn có thể luôn làm điều này:

User.where(subscribed_to_newsletter: true).each do #something

Tuy nhiên, thay vì luôn viết điều này, bạn có thể làm điều gì đó như thế này.

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, where(subscribed_to_newsletter: true)
  #yada yada
end

Nếu bạn đang sử dụng Rails 4 hoặc mới hơn , hãy thực hiện việc này thay thế:

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, -> { where(subscribed_to_newsletter: true) }
  #yada yada
end

Điều này cho phép bạn truy cập người đăng ký của mình bằng cách chỉ cần thực hiện điều này:

User.newsletter.each do #something

Đây là một ví dụ rất đơn giản nhưng nhìn chung phạm vi có thể là công cụ rất mạnh để dễ dàng thực hiện công việc của bạn.

Kiểm tra liên kết này: Mô tả API


7
Tôi có thể hỏi ưu điểm của điều này là gì so với việc xác định một phương thức trong Lớp người dùng được gọi là 'subscriberUsers'? ví dụ: 'def self.subscribeUsers self.where (: subscriber_to_newsletter => true) end
redroot

3
@redroot lợi thế là scopecú pháp được nhiều bụi, bạn sẽ có được kết quả tương tự nhưng với chỉ một dòng
Aldo 'xoen' Giambelluca

9
@redroot Đã từng có một lợi thế lớn về hiệu quả, vì phạm vi sẽ truy vấn cơ sở dữ liệu một cách lười biếng trong khi các phương thức sẽ thực hiện nó một cách háo hức. Trong Rails 3, các phương thức cũng trở nên lười biếng, vì vậy bây giờ sự khác biệt là cú pháp nhiều hơn. Nguồn
evanrmurphy

Liên kết tài liệu API bị hỏng, vui lòng cập nhật api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/…
Lohith MV

Cũng cho phép sử dụng liên kết
Benjineer

34

phạm vi trong bản ghi hoạt động giống như các phương thức lớp nhưng chúng trả về đối tượng Quan hệ có nghĩa là bạn có thể gọi một phạm vi khác hoặc phương thức truy vấn bản ghi hoạt động trên đó.

Ví dụ: nếu bạn có mô hình Zombie (bảng zombie) với các phương pháp phạm vi được đề cập bên dưới,

class Zombie
  scope :rotting, -> { where(rotting: true) }
  scope :fresh, -> { where('age < ?', 25) }
  scope :recent, -> { order(created_at: :desc) }
end

Và bạn gọi

Zombie.rotting.fresh.recent.limit(3)

Nó dịch sang bên dưới trong SQL,

select "zombies.*" from "zombies" where "zombies"."rotting" = 't' and (age<20) order by create_at desc limit 3

Ví dụ trên dựa trên cú pháp rails 4


Tôi không thể tìm thấy ví dụ về order (: create_at,: desc) trong bất kỳ tài liệu nào. Là nó có thể bạn có nghĩa là scope :recent, -> { order(created_at: :desc) }? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch vào

7

Cách tốt nhất để hiểu chi tiết là truy cập Tài liệu API.

Bạn sẽ nhận được thông tin chi tiết đầy đủ và các cách chúng tôi có thể sử dụng Scopes.

Tài liệu API về Phạm vi


7

Phạm vi không là gì ngoài các phương thức lớp.

Tại sao sử dụng chúng?

Phạm vi cho phép bạn chỉ định các truy vấn thường được sử dụng (nó có thể được coi là một lối tắt cho các truy vấn dài hoặc được sử dụng thường xuyên nhất) có thể được tham chiếu như các cuộc gọi phương thức trên các đối tượng hoặc mô hình liên kết. Với các phạm vi này, bạn có thể sử dụng mọi phương pháp đã đề cập trước đó như ở đâu, tham gia và bao gồm. Tất cả các phương thức phạm vi sẽ trả về một đối tượng ActiveRecord :: Relation, đối tượng này sẽ cho phép các phương thức khác (chẳng hạn như các phạm vi khác) được gọi trên nó.

Để xác định một phạm vi đơn giản, chúng tôi sử dụng phương thức phạm vi bên trong lớp, chuyển truy vấn mà chúng tôi muốn chạy khi phạm vi này được gọi:

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end

Điều này hoàn toàn giống với việc xác định phương thức lớp và bạn sử dụng phương thức nào là vấn đề sở thích cá nhân:

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end

Vui lòng theo liên kết sau để có mô tả đầy đủ với ví dụ. Tôi hy vọng điều này sẽ giúp bạn.

http://guides.rubyonrails.org/active_record_querying.html


3
Nó không hoàn toàn giống với việc định nghĩa một phương thức lớp . Các phương thức lớp trả về niltrong một số trường hợp, và do đó không thể thay thế cho các điều kiện nhất định.
Arslan Ali

1
  • Hãy tưởng tượng bạn có một hình mẫu: Người .

Bây giờ hãy tưởng tượng bạn:

  • muốn tất cả những người trên thế giới có mái tóc đỏ.
  • muốn tất cả những người trên thế giới chơi cricket

Bạn có thể có được những lớp người cụ thể đó bằng cách sử dụng một phạm vi!

Person.red_hair.cricket ## finds all people with red hair who play cricket
Person.red_hair ## finds all people with red hair
Person.cricket ## finds all people who play cricket.

Bây giờ điều đó không quá khó phải không?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.