对于我的一个模特,我试图设置一个按年份和季节排序的默认范围。由于年份是整数,因此很容易订购。我的麻烦是按季节排序(如果年份相同)。这里只是按年订购:
class League < ActiveRecord::Base
def self.default_scope
order(:year)
end
# The season's that are allowed to be used
# This is also the order I'd like to use
def self.season_collection
{
"Spring" => "Spring",
"Summer" => "Summer",
"Fall" => "Fall"
}
end
end
如果我尝试order(:year, :season)
,那么就会按字母顺序执行。有没有办法使用order
(所以它在数据库端完成)?
答案 0 :(得分:0)
您可以在数据库中对它们进行排序,但它不会非常高效,因为您需要将season
字段的值强制转换为整数,然后使用它来对记录进行排序。请参阅此答案以获取示例:
SQL: ORDER BY using a substring within a specific column... possible?
更好的方法是将季节存储为数据库中的整数,而不是字符串。最简单的方法是在Rails 4.1+中使用ActiveRecord::Enum
。在你的模型中添加:
class League < ActiveRecord::Base
enum season: %w{Spring Summer Autumn Winter}
end
然后你可以创建这样的记录:
0> league1 = League.create!(season: 'Summer')
=> #<League id: 1>
1> league2 = League.create!(season: 'Spring')
=> #<League id: 2>
2> league3 = League.create!(season: 'Autumn')
=> #<League id: 3>
3> league3.season
=> "Autumn"
引擎盖下ActiveRecord不存储字符串,而是存储引用它的整数。您可以按如下方式找到整数:
4> League.seasons
=> {"Spring"=>0, "Summer"=>1, "Autumn"=>2, "Winter"=>3}
为了让它们按顺序排列,那么只需要对字段进行排序:
5> League.order(:season)
SELECT * FROM leagues ORDER BY season
=> #<ActiveRecord::Relation [#<League id: 2>, #<League id: 1>, #<League id: 3>]>
如果您想查询特定季节,ActiveRecord会自动将名称映射到ID:
6> League.where(season: 'Summer')
SELECT * FROM leagues WHERE season = 1
=> #<ActiveRecord::Relation [#<League id: 1>]>
如果您尝试设置无效季节,ActiveRecord会通知您:
7> league3.season = 'Tomato'
ArgumentError: 'Tomato' is not a valid season