简体   繁体   English

Rails订单记录按列和自定义方法

[英]Rails order records by column and custom method

For one of my models I'm trying to set a default scope that sorts by year and season. 对于我的其中一个模型,我试图设置一个按年份和季节排序的默认范围。 Since year is an integer, it's easy to order by that. 由于year是一个整数,因此可以很容易地进行排序。 My trouble is ordering by season (if the year is the same). 我的麻烦是按季节订购(如果年份相同)。 Here's just ordering by year: 仅按年份订购:

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

If I try order(:year, :season) then that will just do it alphabetically. 如果我尝试order(:year, :season) ,那将按字母顺序进行。 Is there any way to use order (so it's done on the database end)? 有什么方法可以使用order (因此在数据库端完成)?

You can order them in the database, but it isn't going to be very efficient as you'll need to coerce the value of the season field into a integer, and then use that to order the records. 您可以在数据库中对它们进行排序,但是效率不高,因为您需要将season字段的值强制为整数,然后使用该值对记录进行排序。 See this answer for an example: 请参见以下答案以获取示例:

SQL: ORDER BY using a substring within a specific column... possible? SQL:ORDER BY在特定列中使用子字符串...可能吗?

A better way would be to store the season as an integer, not a string, in the database. 更好的方法是将季节以整数而不是字符串的形式存储在数据库中。 The easiest way to use this would be ActiveRecord::Enum available in Rails 4.1+. 最简单的方法是在Rails 4.1+中使用ActiveRecord::Enum In your model add this: 在模型中添加以下内容:

class League < ActiveRecord::Base
  enum season: %w{Spring Summer Autumn Winter}
end

Then you can create records like this: 然后,您可以创建如下记录:

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"

Under the hood ActiveRecord doesn't store the string, but an integer referring to it. 在内部,ActiveRecord不会存储字符串,但会存储一个引用它的整数。 You can find the integers as follows: 您可以找到以下整数:

4> League.seasons
=> {"Spring"=>0, "Summer"=>1, "Autumn"=>2, "Winter"=>3}

To get them in order it's then just a case of ordering the field: 为了使它们井然有序,这只是订购字段的一种情况:

5> League.order(:season)
SELECT * FROM leagues ORDER BY season
=> #<ActiveRecord::Relation [#<League id: 2>, #<League id: 1>, #<League id: 3>]>

If you want to query for a specific season ActiveRecord will automatically map the name to the ID: 如果要查询特定季节,ActiveRecord会自动将名称映射到ID:

6> League.where(season: 'Summer')
SELECT * FROM leagues WHERE season = 1
=> #<ActiveRecord::Relation [#<League id: 1>]>

If you try and set an invalid season, ActiveRecord will let you know: 如果您尝试设置无效的季节,ActiveRecord将通知您:

7> league3.season = 'Tomato'
ArgumentError: 'Tomato' is not a valid season

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM