简体   繁体   English

由于nil值而导致Array上的Rails sort_by引发ArgumentError -它不应该仅根据数据库进行排序吗?

[英]Rails sort_by on Array throwing ArgumentError because of nil values - shouldn't it just sort depending on database?

I am sorting an Array in Rails 4 using sort_by: 我正在使用sort_by在Rails 4中对数组进行排序:

sort_column = 'experience_in_months'
@userstoshow=@userstoshow.sort_by(&:"#{sort_column}")

This throws an error 这引发一个错误

An ArgumentError occurred in SNIP : SNIP中发生ArgumentError:

comparison of Fixnum with nil failed Fixnum与nil的比较失败

This is a strange problem because I remember reading about this earlier. 这是一个奇怪的问题,因为我记得之前已经读过。 It was supposed to put the nil values first or last based on the database used. 应该根据所使用的数据库将nil值放在第一位或最后一位。 I am using PostGreSQL. 我正在使用PostGreSQL。

I remember this working quite flawlessly a few days ago - it just put nil values at the top in my table. 我记得几天前这项工作非常完美-它只是将nil值放在表格的顶部。

It isn't a difficult problem to solve - I can take out the nil values, sort the rest and then add back the nil enteries. 解决这个问题并不困难-我可以取出nil值,对其余的值进行排序,然后再添加nil的肠子。 But I would like to be clear if this is a random behaviour or if it is as expected. 但是我想弄清楚这是随机行为还是预期的行为。

@arunt, I am guessing that you have in @userstoshow objects of type User or something as such. @arunt,我猜您在@userstoshowUser类型为User或类似的对象。

Now when you use Ruby 's sort_by it enumerates over the collection and tries to a <=> b , here is an equivalent code snippet. 现在,当您使用Rubysort_by它将枚举集合,并尝试到a <=> b ,这是等效的代码段。

@userstoshow = @userstoshow.sort_by do |a, b|
  a.experience_in_months <=> b.experience_in_months
end

Now Ruby doesn't know how to compare a Fixnum to a NilClass, here is a similar case 现在,Ruby不知道如何将Fixnum与NilClass进行比较,这是一个类似的情况

[1, 2, 3, nil].sort => ArgumentError: comparison of Fixnum with nil failed

So the problem is that your User object is returning nil for some of it's object rather than a Fixnum value. 因此,问题在于您的User对象为其某些对象返回了nil而不是Fixnum值。

So you can either change your sort_by to include a code block or fix your User object to return a default value which is not nil. 因此,您可以更改sort_by以包含代码块,也可以修复User对象以返回默认值nil。

This is expected behavior 这是预期的行为

Database ordering only applies in database queries 数据库排序仅适用于数据库查询

Once the data is out of the database, Ruby has full control and ruling over ordering rules. 一旦数据从数据库中移出,Ruby就可以完全控制和控制排序规则。 Databases' rules no longer apply because arrays are used everywhere and no gems expect them to be broken in this way. 数据库的规则不再适用,因为数组无处不在,而且没有宝石期望以这种方式破坏数组。

Taking advantage of the fact that nil.to_i is 0 , you can use the following: 利用nil.to_i0的事实,可以使用以下代码:

attribute_proc = sort_column.to_sym.to_proc
@userstoshow = @userstoshow.sort_by { |x| attribute_proc.call(x).to_i }

...and you're replacing the value in-place, so you can use sort_by! ...并且您正在就地替换值,因此可以使用sort_by! , not sort_by : ,而不是sort_by

attribute_proc = sort_column.to_sym.to_proc
@userstoshow.sort_by! { |x| attribute_proc.call(x).to_i }

Looks kinda intimidating. 看起来有点吓人。 That's because you're not using a fixed attribute name. 那是因为您没有使用固定的属性名称。 Otherwise, it'd be: 否则,它将是:

@userstoshow.sort_by! { |x| x.experience_in_months.to_i }

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

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