我正在尝试学习rails[通过在coursera中学习SAAS课程],并使用ActiveRecord处理简单的Movie表。
我想显示所有按标题排序的电影。我希望它能被无意识地分类。
我试着这样做:
Movie.all(:conditions => ["lower(title) = ?", title.downcase],:order => "title DESC")
=>undefined local variable or method `title' for #<MoviesController:0xb4da9a8>
我认为它不承认较低的(头衔)。
这是实现案例独立排序的最佳方式吗?
谢谢!
使用where
而非all
Movie.where("lower(title) = ?", title.downcase).order("title DESC")
不过,我真的不太明白。在这里,您将获得所有标题低于title.downcase
的电影。一切都是平等的,你怎么能按title desc
排序呢?
按小写标题按字母顺序倒排所有电影:
Movie.order("lower(title) DESC").all
你必须这样做:
Movie.order("lower(title) DESC").all
一个更健壮的解决方案是使用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提到的那样,如果列上没有索引,那么数据库就会很慢。然而,复制数据并将转换应用于另一列是不好的(正常)形式,因为这样一列可能会与另一列不同步。不幸的是,mysql的早期版本不允许使用触发器以外的其他选项。5.7.5之后,您可以使用虚拟生成的列来执行此操作。然后,在不区分大小写的情况下,只使用生成的列(这实际上使ruby更直接)。
Postgres在这方面有更大的灵活性,它将允许您在不必引用特殊列的情况下对函数进行索引,或者您可以将该列设置为不区分大小写的列。
让MySQL每次执行大写或小写操作是非常昂贵的。
我建议使用title
列和title_lower
列。这样,您就可以在title_lower
列上不区分大小写地轻松显示和排序,而无需每次排序都让MySQL执行上下操作。
请记住同时索引或至少索引title_lower
。