2012-08-04 25 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在这方面有更多的灵活性,并且可以让您在不需要引用特殊列的情况下对函数进行索引,也可以使列成为不区分大小写的列。