2012-08-22 177 views
15

我需要獲取所有current_user.friends狀態,然後通過created_at對它們進行排序。Rails:狀態與狀態比較失敗

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

錯誤:

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

不是你的核心問題,但行走所有這些關聯將通過大量的查詢來殺死你。抓住所有朋友和他們的所有狀態,然後用代碼對它們進行排序可能會產生不合要求的查詢數量,您的性能會迅速下降。爲什麼不寫一個可以一次獲取並排序所有記錄的單個SQL查詢? –

+0

謝謝,我發現了一個簡單的方法和有效的方法:'Status.where(user_id:current_user.friends.map(&:id).insert(0,current_user.id))。all'你怎麼看? – Alex

回答

16

我有一個類似的問題,用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 } 
+20

「X與X失敗比較」錯誤是由'<=>'兩側的'nil'觸發的。通過添加'.to_i'轉換,你可以將nils變成0,並且可以解決這個問題。 –

+0

不錯!在我的情況下,應該不可能在這部分代碼中得到'nil' ..也許它是一個錯誤,我將開始記錄它。謝謝! – hsgubert

+1

塞爾 - 你應該把它作爲答案,它應該被接受,因爲它實際上回答了題目問題...... –

1

我今晚在一個小組項目上有類似的問題。這個答案沒有解決它,但我們的問題是,有人把其他models.new在我們的def show用戶控制器。例如...

Class UsersController < ApplicationController 

def show 

    @status = @user.statuses.new 

end 

這是在@ user.statuses和我試圖在頁面上調用的@status之間產生衝突。我脫掉了用戶,只是這樣做...

def show 

    @status = Status.new 

end 

而且這對我來說做的伎倆。

4

當排序從< =>返回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>' 

的一種方法是通過檢查你的< =>是零的回報,拋出一個異常,如果它是。

@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