Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: comparison of Status with Status failed

I need to fetch all current_user.friends statuses and then sort them by created_at.

class User < ActiveRecord::Base
 has_many :statuses
end

class Status < ActiveRecord::Base
 belongs_to :user
end

And in the controller:

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 returns an array of objects User

friend.statuses returns an array of objects Status

Error:

comparison of Status with Status failed
app/controllers/welcome_controller.rb:10:in `sort!'
app/controllers/welcome_controller.rb:10:in `index'
like image 881
Alex Avatar asked Aug 22 '12 16:08

Alex


2 Answers

I had a similar problem, solved with the to_i method, but can't explain why that happens.

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

By the way, this sorts in the descending order. If you want ascending order is:

@statuses.sort! { |a,b| a.created_at.to_i <=> b.created_at.to_i }
like image 50
hsgubert Avatar answered Oct 31 '22 23:10

hsgubert


This error message appears when sort gets a nil returned from <=>. <=> can return -1, 0, 1, or nil, but sort cannot handle nil because it needs all the list elements to be comparable.

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

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

One way to debug this kind of error is by checking if the return of your <=> is nil and raising an exception if it is.

@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
like image 11
ryantm Avatar answered Oct 31 '22 23:10

ryantm