轨道模型的默认sorting顺序?
我想在我的模型中指定一个默认的sorting顺序。
所以,当我做一个.where()
没有指定.order()
它使用默认sorting。 但是,如果我指定.order()
,它将覆盖默认值。
default_scope
这适用于Rails 4+:
class Book < ActiveRecord::Base default_scope { order(created_at: :desc) } end
对于Rails 2.3,3,你需要这个:
default_scope order('created_at DESC')
对于Rails 2.x:
default_scope :order => 'created_at DESC'
其中created_at
是你想要默认sorting的字段。
注: ASC是用于升序的代码, DESC用于降序( desc
, NOT dsc
!)。
scope
一旦你习惯了,你也可以使用scope
:
class Book < ActiveRecord::Base scope :confirmed, :conditions => { :confirmed => true } scope :published, :conditions => { :published => true } end
对于Rails 2,你需要named_scope
。
:published
范围给你Book.published
而不是Book.find(:published => true)
。
由于Rails 3可以通过将这些方法与它们之间的句点连接在一起来“链接”这些方法,所以现在可以使用Book.published.confirmed
。
使用这种方法,只有在需要实际结果(懒惰评估)时,才能实际执行查询,因此可以将7个作用域链接在一起,但仅导致1个实际的数据库查询,以避免执行7个单独查询时的性能问题。
你可以使用一个传入的参数,例如date或者user_id(在运行时会改变的东西,所以需要用'lazy evaluation',用一个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.
最后,您可以使用以下命令来禁用默
Book.with_exclusive_scope { find(:all) }
甚至更好:
Book.unscoped.all
这将禁用任何filter(条件)或sorting(按顺序)。
请注意,第一个版本在Rails2 +中工作,而第二个版本(unscoped)仅在Rails3 +中使用
所以 ……如果你在想,呃,那么这些就像方法那么…呃,这正是这些范围!
他们就像def self.method_name ...code... end
但一如既往的ruby,他们是很好的语法快捷方式(或“糖”),使您更容易!
事实上,他们是在一套“所有”logging上操作的类级方法。
然而,它们的格式正在改变, 使用rails 4时,如果不使用可调用对象,使用#scope时会出现弃用警告。 例如,作用域:红色,其中(颜色:“红色”)应该改为scope :red, -> { where(color: 'red') }
。
作为一个侧面说明,如果使用不当, 默认 _scope可能会被滥用/滥用。
这主要是关于什么时候它被用于像限制(过滤) 默认select那样的操作(对于缺省而言是一个坏主意 ),而不是用于sorting结果。
对于where
select,只需使用常规的命名范围即可。 并在查询中添加该范围,例如Book.all.published
,其中published
是命名范围。
总而言之,示波器非常棒,可以帮助您将事物推入“胖模式瘦控制器”DRYer方法的模型中。
迈克尔上面的优秀答案的快速更新。
对于Rails 4.0+,你需要把你的sorting放在这样一个块中:
class Book < ActiveRecord::Base default_scope { order('created_at DESC') } end
请注意,顺序语句被放置在由大括号表示的块中。
他们改变了它,因为它太容易传递一些dynamic的东西(比如当前时间)。 这消除了问题,因为块在运行时被评估。 如果你不使用块,你会得到这个错误:
支持调用没有块的#default_scope被删除。 例如,而不是
default_scope where(color: 'red')
,请使用default_scope { where(color: 'red') }
。 (或者,您可以重新定义self.default_scope。)
正如@丹在下面的评论中提到的,你可以做一个更像ruby的语法:
class Book < ActiveRecord::Base default_scope { order(created_at: :desc) } end
或与多个列:
class Book < ActiveRecord::Base default_scope { order({begin_date: :desc}, :name) } end
谢谢@丹 !
你可以使用default_scope来实现默认sorting顺序http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html