Rails中的scope / named_scope是什么?


105

我最近开始实习。我的雇主在铁路上使用红宝石,而我经常遇到需要查找以了解的新语法。我在Google上搜索了named_scope的一个很好的解释,但是到目前为止,我发现的大部分是博客文章,对此给予了高度评价,而不是直接的定义或介绍。

在Rails上的ruby中究竟是named_scope(现在简称为scope)是什么?



2
学习命名范围时,此博客文章对我来说是无价的:ryandaigle.com/articles/2008/8/20/…–
Peter Brown

@notapatch链接失效了,您还有另一个吗?
mbigras

瑞安·戴格(Ryan Daigle):命名范围:不仅是为了满足条件,还知道吗?:web.archive.org/web/20160306110506/http
//…

Answers:


212

范围是集合的子集。听起来复杂吗?不是。想象一下:

您有用户。现在,其中一些用户已订阅您的新闻通讯。您通过在用户数据库中添加字段来标记那些接收时事通讯的用户(user.subscribed_to_newsletter = true)。自然,有时您希望获得订阅您的新闻通讯的那些用户。

您当然可以始终这样做:

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

但是,您不必总是编写此代码,而是可以执行类似的操作。

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

如果您使用的是Rails 4或更高版本,请执行以下操作:

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

这样,您只需执行以下操作即可访问您的订户:

User.newsletter.each do #something

这是一个非常简单的示例,但是在一般情况下,它们可以是使工作轻松的非常强大的工具。

查看此链接:API描述


7
我可以问一下,这比在用户类中定义一个称为“ subscribedUsers”的方法有什么好处吗?例如'def self.subscribedUsers self.where(:subscribed_to_newsletter => true)结束
redroot 2011年

3
@redroot的优点是scope语法更简洁,您只得到一行而得到相同的结果
Aldo'xoen'Giambelluca'2013年

9
@redroot曾经有一个很大的效率优势,因为范围会懒惰地查询数据库,而方法会急于这样做。在Rails 3中,方法也变得很懒,所以现在区别更加句法化了。来源
福音医学


还允许使用范围内的路线链接
Benjineer 2014年

34

活动记录中的作用域类似于类方法,但是它们返回Relation对象,这意味着您可以在其上调用另一个作用域或活动记录查询方法。

例如,如果您的Zombie模型(僵尸表)具有以下提到的范围方法,

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

然后你打电话

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

它在SQL中翻译为以下内容,

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

上面的示例基于Rails 4语法


我在任何文档中都找不到order(:created_at,:desc)的示例。你有可能scope :recent, -> { order(created_at: :desc) }吗? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch

7

了解详细信息的最佳方法是转到API文档。

您将获得完整的详细信息以及我们使用范围的方式。

范围的API文档


7

范围不过是类方法。

为什么要使用它们?

范围界定允许您指定常用查询(对于长期或最常用的查询,可以将其视为快捷方式),可以将其引用为关联对象或模型上的方法调用。通过这些作用域,您可以使用以前涵盖的每种方法,例如,在何处,在何处加入和包括。所有作用域方法都将返回一个ActiveRecord :: Relation对象,该对象将允许在其上调用其他方法(例如其他作用域)。

为了定义一个简单的作用域,我们在类内部使用了scope方法,并在该作用域被调用时传递要运行的查询:

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

这与定义类方法完全相同,您可以根据个人喜好使用:

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

请点击以下链接以获取示例的完整说明。我希望这能帮到您。

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


3
与定义类方法并不完全相同。类方法nil在少数情况下会返回,因此在某些情况下无法链接。
Arslan Ali

1
  • 假设您有一个模型:Person

现在想象你:

  • 希望世界上所有拥有红头发的人。
  • 希望世界上所有玩板球的人

您可以通过使用范围来获得那些特定类别的人!

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.

现在不是那么难吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.