我正在尝试学习rails [通过遵循课程中的SAAS课程]并使用ActiveRecord处理简单的Movie表。
我想要显示所有已分类标题的电影。我希望它不区分大小写。
我试过这样做:
Movie.all(:conditions => ["lower(title) = ?", title.downcase],:order => "title DESC")
=>undefined local variable or method `title' for #<MoviesController:0xb4da9a8>
我认为它不承认较低(标题)。
这是实现案件分类排序的最佳方法吗?
谢谢!
答案 0 :(得分:17)
使用where
而非all
Movie.where("lower(title) = ?", title.downcase).order("title DESC")
不过真的不明白。在这里,您将获得所有低于标题的电影等于title.downcase
。一切都是平等的,你怎么能按title desc
排序呢?
按小写标题反向按字母顺序排序所有电影:
Movie.order("lower(title) DESC").all
答案 1 :(得分:6)
你必须这样做:
Movie.order("lower(title) DESC").all
答案 2 :(得分:3)
每次MySQL执行大写或小写操作都非常昂贵。
我建议使用title
列和title_lower
列。通过这种方式,您可以在title_lower
列上轻松显示和排序不区分大小写,而不会在每次排序时执行上限或下限。
请记住将两者或至少title_lower
编入索引。
答案 3 :(得分:1)
更强大的解决方案是使用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在这方面有更多的灵活性,可以让你在不需要引用特殊列的情况下为函数创建索引,或者可以使列不区分大小写。