我想在我的模型中指定默认排序顺序.
因此,当我在.where()没有指定.order()的情况下执行时,它使用默认排序.但是如果我指定了一个.order(),它会覆盖默认值.
Mic*_*ant 529
default_scope这适用于Rails 4+:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
Run Code Online (Sandbox Code Playgroud)
对于Rails 2.3,3,你需要这样:
default_scope order('created_at DESC')
Run Code Online (Sandbox Code Playgroud)
对于Rails 2.x:
default_scope :order => 'created_at DESC'
Run Code Online (Sandbox Code Playgroud)
created_at您希望在哪个字段上进行默认排序.
注意:ASC是用于升序的代码,DESC用于降序(desc,不是 dsc!).
scope一旦你习惯了,你也可以使用scope:
class Book < ActiveRecord::Base
scope :confirmed, :conditions => { :confirmed => true }
scope :published, :conditions => { :published => true }
end
Run Code Online (Sandbox Code Playgroud)
对于Rails 2,您需要named_scope.
:published范围为您提供Book.published而不是
Book.find(:published => true).
从Rails 3开始,您可以通过将它们与它们之间的句点连接在一起来"链接"这些方法,因此使用上述范围,您现在可以使用它们Book.published.confirmed.
使用此方法,在需要实际结果(延迟评估)之前,实际上不会执行查询,因此可以将7个作用域链接在一起但仅产生1个实际数据库查询,以避免执行7个单独查询时出现性能问题.
您可以使用传入的参数,例如日期或user_id(在运行时会发生变化,因此需要使用lambda进行'延迟评估',如下所示:
scope :recent_books, lambda
{ |since_when| where("created_at >= ?", since_when) }
# Note the `where` is making use of AREL syntax added in Rails 3.
Run Code Online (Sandbox Code Playgroud)
最后,您可以使用以下命令禁用默
Book.with_exclusive_scope { find(:all) }
Run Code Online (Sandbox Code Playgroud)
甚至更好:
Book.unscoped.all
Run Code Online (Sandbox Code Playgroud)
这将禁用任何过滤器(条件)或排序(排序依据).
请注意,第一个版本适用于Rails2 +,而第二个版本(unscoped)仅适用于Rails3 +
所以
...如果你在想,嗯,所以这些就像方法那样......,是的,这正是这些范围的本质!
他们就像def self.method_name ...code... end拥有红宝石一样,但它们是很好的小语法快捷键(或"糖"),让你的事情变得更轻松!
事实上,它们是类级方法,因为它们在1组"所有"记录上运行.
但是它们的格式正在改变,使用rails 4时,在使用#scope而不传递可调用对象时会出现弃用警告.例如范围:红色,其中(颜色:'红色')应更改为scope :red, -> { where(color: 'red') }.
作为旁注,如果使用不当,默认的 _scope可能会被滥用/滥用.
这主要是关于什么时候它被用于where限制(过滤)默认选择(默认的坏主意)等操作,而不仅仅是用于排序结果.
对于where选择,只需使用常规命名范围.并在查询中添加该范围,例如Book.all.published,在哪里published是命名范围.
总之,范围非常好,可以帮助您将模型推向"胖模型瘦控制器"DRYer方法.
Pau*_*ver 109
迈克尔上面的优秀答案快速更新.
对于Rails 4.0+,你需要将你的排序放在这样的块中:
class Book < ActiveRecord::Base
default_scope { order('created_at DESC') }
end
Run Code Online (Sandbox Code Playgroud)
请注意,order语句放在由大括号表示的块中.
他们改变了它,因为它太容易传递动态的东西(比如当前时间).这样可以解决问题,因为在运行时会计算块.如果您不使用块,您将收到此错误:
删除了对没有阻止调用#default_scope的支持.例如
default_scope where(color: 'red'),请使用default_scope { where(color: 'red') }.(或者你可以重新定义self.default_scope.)
正如@Dan在下面的评论中提到的那样,你可以做一个像这样的rubyish语法:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
Run Code Online (Sandbox Code Playgroud)
或多列:
class Book < ActiveRecord::Base
default_scope { order({begin_date: :desc}, :name) }
end
Run Code Online (Sandbox Code Playgroud)
谢谢@Dan!
msc*_*ltz 16
接受的答案曾经是正确的 - 默认范围是执行此操作的唯一方法。然而,默认作用域实际上是链接的(作用域本身应用于任何进一步的作用域/调用),这可能会导致一些不可预测的行为。因此,默认范围被广泛认为是不惜一切代价避免的事情。
重要的是要注意,鉴于您最初的问题,默认范围实际上并不能完全满足这一点,因为为了实际跳过默认范围,任何模型都必须.unscoped首先明确指定。这意味着如果在order(:something)没有 的情况下调用 if .unscoped,结果实际上更类似于order(:default).order(:something)。:something当然,优先,但:default仍然存在,所以现在有一个多列排序,这可能不是所需要的。原始问题指定,如果调用另一个顺序,则忽略默认排序顺序,并且默认范围 without.unscoped不满足该要求。
然而,从 Rails 6 开始,现在有了implicit_order_column,可以在模型上设置。
class Book < ApplicationRecord
self.implicit_order_column = 'publish_date'
end
Run Code Online (Sandbox Code Playgroud)
这将导致模型默认按该列排序,而不是主键。与默认的内置排序(使用 id)一样,但是,如果指定了不同的顺序(使用order(:something)),则此隐式排序将被忽略,而不是链接:.order(:something)不会导致多列排序,并且.unscoped不再需要。
最常见的用途之一是切换到 UUID 作为主键。默认情况下,Rails 仍会对主键进行排序,但由于该键现在是一个无意义的字节字符串,因此此顺序现在同样没有意义。因此,要复制旧的行为,以便SomeModel.last默认返回最近创建的记录,只需在 ApplicationRecord 上设置:
class ApplicationRecord < ActiveRecord::Base
self.implicit_order_column = 'created_at'
end
Run Code Online (Sandbox Code Playgroud)
请注意,理论上这里可能会导致错误。created_at不是唯一的 - 它以微秒精度存储,但理论上可以创建具有完全相同created_at时间的记录,因此,任何仅依赖于此的返回结果都是不确定的 - 后续调用可能会返回不同的记录。然而,这样做的可能性足够低,通常认为这样做是安全的 - 特别是如果代码不依赖于此处的确定性结果(这可能不应该 - 如果需要确定性结果,引用主键或如果可能的话,其他一些独特的列会更好)。
还值得注意的是created_at(或使用任何列)默认情况下没有键。这意味着选择将稍微减慢执行此操作的速度,至少直到将键添加到该列来解决此问题为止。
最后,implicit_order_column功能有限 - 甚至无法设置排序顺序,更不用说执行多列排序等更复杂的操作了。如果需要该功能,default_scope这仍然是唯一的选择。
您可以使用default_scope实现默认排序顺序 http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html
| 归档时间: |
|
| 查看次数: |
136230 次 |
| 最近记录: |