要在Rails 3中对关系进行排序,我们必须这样做:
User.where(:activated => true).order('id ASC')
但我认为:
User.where(:activated => true).order(:id => :asc)
会更有意义,因为字段名称的转义方式应取决于适配器(SqlLite vs Mysql vs PostgreSQL
),对吗?
有类似的东西吗?
答案 0 :(得分:2)
据我所知,ActiveRecord中内置的语法没有选项,但添加一个语句应该不难。我找到了order
中定义的lib/active_record/relation/query_methods.rb
方法。从理论上讲,你应该能够做到这样的事情:
module ActiveRecord
module QueryMethods
def order(*args)
args.map! do |arg|
if arg.is_a? Hash
# Format a string out of the hash that matches the original AR style
stringed_arg
else
arg
end
end
super
end
end
end
答案 1 :(得分:2)
我认为关键问题是: ActiveRecord API不知道排序语义。它只接受一个字符串并绕过底层数据库。幸运的是,Sqlite,MySQL和PostgreSQL在order
语法方面没有区别。
我认为ActiveRecord不能很好地完成这种抽象,也不需要这样做。它适用于关系数据库,但很难与NoSQL集成,例如。 MongoDB的。
另一个着名的Ruby ORMDataMapper做了更好的抽象。 Take a look at its query syntax:
@zoos_by_tiger_count = Zoo.all(:order => [ :tiger_count.desc ])
API知道排序语义。默认情况下,DataMapper将生成SQL订单声明:
https://github.com/datamapper/dm-do-adapter/blob/master/lib/dm-do-adapter/adapter.rb#L626-634
def order_statement(order, qualify)
statements = order.map do |direction|
statement = property_to_column_name(direction.target, qualify)
statement << ' DESC' if direction.operator == :desc
statement
end
statements.join(', ')
end
但是,可以在数据库适配器层覆盖:
https://github.com/solnic/dm-mongo-adapter/blob/master/lib/dm-mongo-adapter/query.rb#L260-264
def sort_statement(conditions)
conditions.inject([]) do |sort_arr, condition|
sort_arr << [condition.target.field, condition.operator == :asc ? 'ascending' : 'descending']
end
end
TL; DR:
答案 2 :(得分:0)
对于这种特殊情况,您可以放弃“ASC”。 bit,因为所有数据库中的排序都是隐式升序
Foo.order(:bar)
我知道这并不能涵盖你想做order by bar desc
的情况,但实际上由于这个并不重要,除非你使用的功能是order by子句,在这种情况下可能会有squeel之类的东西帮助