Scoping
虽然只有 4 个方法,但很实用。
方法
解释
scope
命名 scope
default_scope
设置默认 scope
和
方法
解释
unscoped
跳过之前设置的 scope
all
all 方法,默认已经 scope
scope
重点说说这个方法。
两个参数:第一个是名字,第二个是内容,需要以 proc 的形式定义。
scope 相当于类方法,可检索、查询对象
可执行一系列的查询语句,如:
可以调用 Shirt.red
和 Shirt.dry_clean_only
. Shirt.red
功能和 Shirt.where(color: 'red')
一样。
也就是说,功能上和以下代码一样:
scope 返回的是 Relation,而不是数组
你可以调用 Shirt.red.first
, Shirt.red.count
, Shirt.red.where(size: 'small')
等. 但是 Relation 也可以有数组的行为, 如 Shirt.red.each(&block)
, Shirt.red.first
, 和 Shirt.red.inject(memo, &block)
等。
scope 可以链式调用
Shirt.red.dry_clean_only
运行结果是 red
和 dry_clean_only
综合的结果。
Shirt.red.dry_clean_only.count
返回的是 red
和 dry_clean_only
综合结果的数目。在这里和 Shirt.red.dry_clean_only.average(:thread_count)
类似。
scope 是一步步走下去的
假设,elton 是 Person 的实例对象,则 elton.shirts.red.dry_clean_only 返回的是 elton(限制条件) 的 red 和 dry_clean_only shirts.
scope 后可直接跟 extensions
和 has_many 类似的:
scope 后可直接跟 creating/building 等方法
用于创建 record
scope 后可直接跟类方法
定义如下:
调用如下:
default_scope
1) 一个参数,需要以 proc 的形式定义:
2) 始终起作用,不能覆盖,冲突时取合集。
3) 会影响 initialization 过程。例如以上示例,默认新创建的对象 published 为 true.
4) 基于第2、3点请慎用。
unscoped
前面说过 scope 可以链式调用,但如果调用了 unscoped
的话,它可以把之前的 scope 给清除掉,包括 default_scope.
示例:
all
all
方法,本身已经 scope,返回的是 Relation 对象。如果已调用了别的 scope 方法,则没必要使用它,因为默认返回的就已经是所有符合条件的数据。
为什么参数要是 proc 类型?
可以看到这里的 2.day.ago
是动态生成的,每一次执行的时候才知道结果。不使用 proc 类型的话,这里立即执行,就和想像中的结果不同了。
Note: 并不是所有的方法都可以做为 scope 的内容,更多内容 Active Record Query Interface
scope 可以调用的时候带参数
注意,使用后不能再进行链式调用。
最后更新于