Rails:状态与状态比较失败的比较

21

我需要获取当前用户的所有好友状态,然后按创建时间排序。

class User < ActiveRecord::Base
 has_many :statuses
end

class Status < ActiveRecord::Base
 belongs_to :user
end

在控制器中:

def index
    @statuses = []
    current_user.friends.map{ |friend| friend.statuses.each { |status| @statuses << status } }
    current_user.statuses.each { |status| @statuses << status }

    @statuses.sort! { |a,b| b.created_at <=> a.created_at }
end

current_user.friends会返回一个由User对象构成的数组。

friend.statuses会返回一个由Status对象构成的数组。

Error:

comparison of Status with Status failed
app/controllers/welcome_controller.rb:10:in `sort!'
app/controllers/welcome_controller.rb:10:in `index'

1
不过这不是你的核心问题,但查找所有相关联的数据将会因为查询数量之多而拖垮你。获取所有好友及其状态,并在代码中进行排序可能会导致可怕的查询量,你的性能会迅速下降。何不编写一个可以一次性获取和排序所有记录的单个 SQL 查询呢? - Cody Caughlan
谢谢,我找到了一种容易而有效的方法:Status.where(user_id: current_user.friends.map(&:id).insert(0, current_user.id)).all 你觉得呢? - Alex
3个回答

20

我曾经遇到过类似的问题,用to_i方法解决了,但无法解释为什么会出现这种情况。

@statuses.sort! { |a,b| b.created_at.to_i <=> a.created_at.to_i }

顺便提一下,这将按降序排序。如果您想要升序,则是:

@statuses.sort! { |a,b| a.created_at.to_i <=> b.created_at.to_i }

27
“comparison of X with X failed”错误是由于<=>两边出现了nil。通过添加.to_i转换,你已经将nil转换成了0,从而解决了这个问题。 - Serge Balyuk
不错!在我的情况下,在代码的这一部分应该是不可能出现 nil 的...也许这是一个错误,我会开始记录它。谢谢! - hsgubert
1
Serge - 你应该将这个作为一个答案,并且它应该被接受,因为它实际上回答了标题的问题... - Jules Copeland

12

当sort从<=>返回nil时,会出现此错误消息。<=>可以返回-1、0、1或nil,但由于sort需要所有列表元素都是可比较的,因此无法处理nil。

class A
  def <=>(other)
    nil
  end
end

[A.new, A.new].sort
#in `sort': comparison of A with A failed (ArgumentError)
#   from in `<main>'

调试此类错误的一种方法是检查您的 <=> 返回值是否为 nil,如果是,则引发异常。

@statuses.sort! do |a,b| 
  sort_ordering = b.created_at <=> a.created_at
  raise "a:#{a} b:#{b}" if sort_ordering.nil?
  sort_ordering
end

0
今晚在小组项目中我遇到了类似的问题。这个回答并没有解决它,我们的问题是有人在我们的“def show User”控制器中放置了其他的models.new。例如...
Class UsersController < ApplicationController

def show

    @status = @user.statuses.new

end

这在我尝试调用页面上的@status时与@user.statuses之间产生了冲突。我去掉了用户并只是做了...

def show

    @status = Status.new

end

这对我来说解决了问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接