2012-08-04 80 views
9

我想學習rails [通過遵循coursera中的SAAS課程]並使用ActiveRecord使用簡單的Movie表。Rails:ActiveRecord db排序操作不區分大小寫

我想顯示標題排序的所有電影。我希望它不區分大小寫。

我試圖做這樣說:

Movie.all(:conditions => ["lower(title) = ?", title.downcase],:order => "title DESC") 
=>undefined local variable or method `title' for #<MoviesController:0xb4da9a8> 

我覺得它不承認較低(職稱)。

這是實現案例評估的最佳方式嗎?

謝謝!

回答

16

使用where而不是all

Movie.where("lower(title) = ?", title.downcase).order("title DESC") 

真的不明白的那種,雖然。在這裏,您將獲得所有電影的小標題等於title.downcase。一切都是平等的,你怎麼能通過title desc來分類?

要小寫標題排序反向字母順序所有的電影:

Movie.order("lower(title) DESC").all 
3

擁有MySQL的執行大寫或小寫操作每次都是相當昂貴的。

我推薦的是title列和title_lower列。通過這種方式,您可以在title_lower列中輕鬆顯示和區分大小寫,而不必在每次排序時MySQL都執行上限或下限。

記得索引兩個或至少title_lower

5

你必須這樣做:

Movie.order("lower(title) DESC").all 
0

一個更強大的解決方案是使用AREL節點。我建議在Movie模型定義了幾個範圍:

scope :order_by_title, -> { 
    order(arel_table['title'].lower.desc) 
} 

scope :for_title, (title)-> { 
    where(arel_table['title'].lower.eq title.downcase) 
} 

,然後調用Movie.for_title(title).order_by_title

對上市其他的答案的優勢在於.for_title.order_by_title不會,如果你打破別名title列或加入到title列的另一個表中,並且它們被sql轉義。

像rickypai mentioned,如果您沒有列上的索引,數據庫將會很慢。但是,複製數據並將變換應用於其他列是錯誤的(正常)形式,因爲一列可能與另一列不同步。不幸的是,除了觸發器之外,早期版本的mysql不允許使用許多alternatives。在5.7.5之後,您可以使用虛擬generated columns來執行此操作。然後在不區分大小寫的情況下,您只需使用生成的列(這實際上使ruby更直接)。

Postgres在這方面有更多的靈活性,並且可以讓您在不需要引用特殊列的情況下對函數進行索引,也可以使列成爲不區分大小寫的列。