aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/query_methods.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/relation/query_methods.rb')
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb132
1 files changed, 132 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
new file mode 100644
index 0000000000..631c80da25
--- /dev/null
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -0,0 +1,132 @@
+module ActiveRecord
+ module QueryMethods
+
+ def preload(*associations)
+ spawn.tap {|r| r.preload_associations += Array.wrap(associations) }
+ end
+
+ def eager_load(*associations)
+ spawn.tap {|r| r.eager_load_associations += Array.wrap(associations) }
+ end
+
+ def readonly(status = true)
+ spawn.tap {|r| r.readonly = status }
+ end
+
+ def select(selects)
+ if selects.present?
+ relation = spawn(@relation.project(selects))
+ relation.readonly = @relation.joins(relation).present? ? false : @readonly
+ relation
+ else
+ spawn
+ end
+ end
+
+ def from(from)
+ from.present? ? spawn(@relation.from(from)) : spawn
+ end
+
+ def having(*args)
+ return spawn if args.blank?
+
+ if [String, Hash, Array].include?(args.first.class)
+ havings = @klass.send(:merge_conditions, args.size > 1 ? Array.wrap(args) : args.first)
+ else
+ havings = args.first
+ end
+
+ spawn(@relation.having(havings))
+ end
+
+ def group(groups)
+ groups.present? ? spawn(@relation.group(groups)) : spawn
+ end
+
+ def order(orders)
+ orders.present? ? spawn(@relation.order(orders)) : spawn
+ end
+
+ def lock(locks = true)
+ case locks
+ when String
+ spawn(@relation.lock(locks))
+ when TrueClass, NilClass
+ spawn(@relation.lock)
+ else
+ spawn
+ end
+ end
+
+ def reverse_order
+ relation = spawn
+ relation.instance_variable_set(:@orders, nil)
+
+ order_clause = @relation.send(:order_clauses).join(', ')
+ if order_clause.present?
+ relation.order(reverse_sql_order(order_clause))
+ else
+ relation.order("#{@klass.table_name}.#{@klass.primary_key} DESC")
+ end
+ end
+
+ def limit(limits)
+ limits.present? ? spawn(@relation.take(limits)) : spawn
+ end
+
+ def offset(offsets)
+ offsets.present? ? spawn(@relation.skip(offsets)) : spawn
+ end
+
+ def on(join)
+ spawn(@relation.on(join))
+ end
+
+ def joins(join, join_type = nil)
+ return spawn if join.blank?
+
+ join_relation = case join
+ when String
+ @relation.join(join)
+ when Hash, Array, Symbol
+ if @klass.send(:array_of_strings?, join)
+ @relation.join(join.join(' '))
+ else
+ @relation.join(@klass.send(:build_association_joins, join))
+ end
+ else
+ @relation.join(join, join_type)
+ end
+
+ spawn(join_relation).tap { |r| r.readonly = true }
+ end
+
+ def where(*args)
+ return spawn if args.blank?
+
+ if [String, Hash, Array].include?(args.first.class)
+ conditions = @klass.send(:merge_conditions, args.size > 1 ? Array.wrap(args) : args.first)
+ conditions = Arel::SqlLiteral.new(conditions) if conditions
+ else
+ conditions = args.first
+ end
+
+ spawn(@relation.where(conditions))
+ end
+
+ private
+
+ def reverse_sql_order(order_query)
+ order_query.to_s.split(/,/).each { |s|
+ if s.match(/\s(asc|ASC)$/)
+ s.gsub!(/\s(asc|ASC)$/, ' DESC')
+ elsif s.match(/\s(desc|DESC)$/)
+ s.gsub!(/\s(desc|DESC)$/, ' ASC')
+ else
+ s.concat(' DESC')
+ end
+ }.join(',')
+ end
+
+ end
+end