diff options
Diffstat (limited to 'activerecord/lib/active_record/relational_calculations.rb')
-rw-r--r-- | activerecord/lib/active_record/relational_calculations.rb | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/relational_calculations.rb b/activerecord/lib/active_record/relational_calculations.rb new file mode 100644 index 0000000000..10eb992167 --- /dev/null +++ b/activerecord/lib/active_record/relational_calculations.rb @@ -0,0 +1,52 @@ +module ActiveRecord + module RelationalCalculations + + def count(*args) + column_name, options = construct_count_options_from_args(*args) + distinct = options[:distinct] ? true : false + + column = if @klass.column_names.include?(column_name.to_s) + Arel::Attribute.new(@relation.table, column_name) + else + Arel::SqlLiteral.new(column_name == :all ? "*" : column_name.to_s) + end + + relation = select(column.count(distinct)) + @klass.connection.select_value(relation.to_sql).to_i + end + + private + + def construct_count_options_from_args(*args) + options = {} + column_name = :all + + # We need to handle + # count() + # count(:column_name=:all) + # count(options={}) + # count(column_name=:all, options={}) + # selects specified by scopes + + # TODO : relation.projections only works when .select() was last in the chain. Fix it! + case args.size + when 0 + column_name = @relation.send(:select_clauses).join(', ') if @relation.respond_to?(:projections) && @relation.projections.present? + when 1 + if args[0].is_a?(Hash) + column_name = @relation.send(:select_clauses).join(', ') if @relation.respond_to?(:projections) && @relation.projections.present? + options = args[0] + else + column_name = args[0] + end + when 2 + column_name, options = args + else + raise ArgumentError, "Unexpected parameters passed to count(): #{args.inspect}" + end + + [column_name || :all, options] + end + + end +end |