Rails按列和自定义方法排序记录

时间:2014-04-19 00:46:26

标签: ruby-on-rails activerecord ruby-on-rails-4

对于我的一个模特,我试图设置一个按年份和季节排序的默认范围。由于年份是整数,因此很容易订购。我的麻烦是按季节排序(如果年份相同)。这里只是按年订购:

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(所以它在数据库端完成)?

1 个答案:

答案 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