Skip to content

Instantly share code, notes, and snippets.

@avit
Created September 8, 2012 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avit/3681183 to your computer and use it in GitHub Desktop.
Save avit/3681183 to your computer and use it in GitHub Desktop.
ActiveRecord::Calculations API discussion
# Goal: split responsibilities of count and grouped_count so they are responsible for returning
# count => Fixnum and grouped_count => Hash in all cases
#
# This option removes original calculation options for count(:group => x)
# in favour of grouped_count(:group => x)
#
# (I'm showing count and average as examples of optional & required column_name params,
# but this would apply to all calculation methods.)
relation = Post.group("author_id").order("created_at")
#
# count(column_name=nil)
#
# * deprecate options
#
relation.count # => Fixnum
# SELECT COUNT(*) FROM (((SELECT ...))) posts
relation.count(:name) # => Fixnum
# SELECT COUNT(posts.name) FROM (((SELECT ...))) posts
#
# average(column_name)
#
# * deprecate options
#
relation.average(:rating) # => Float
# SELECT AVG(posts.rating) FROM (((SELECT ...))) posts
#
# grouped_count(*args)
#
# * group_values is implicitly taken from relation when :group option is not given
#
relation.grouped_count # => Hash
# SELECT posts.author_id, COUNT(*) FROM (((SELECT ...))) posts GROUP BY posts.author_id
relation.grouped_count(:name) # => Hash
# SELECT posts.author_id, COUNT(posts.name) FROM (((SELECT ...))) posts GROUP BY posts.author_id
relation.grouped_count(:group => "extra") # => Hash
# SELECT extra, COUNT(*) FROM (((SELECT ...))) posts GROUP BY extra
relation.grouped_count(:name, :group => "extra") # => Hash
# SELECT extra, COUNT(posts.name) FROM (((SELECT ...))) posts GROUP BY extra
#
# grouped_average(column_name, options)
#
# * group_values is implicitly taken from relation when :group option is not given
#
relation.grouped_average(:rating) # => Hash
# SELECT posts.author_id, AVG(posts.rating) FROM (((SELECT ...))) posts GROUP BY posts.author_id
relation.grouped_average(:rating, :group => "extra") # => Hash
# SELECT extra, AVG(posts.rating) FROM (((SELECT ...))) posts GROUP BY extra
# Goal: keep existing methods for compatibility & familiarity, requiring
# explicit {:group => x} option for a Hash, else return a numeric value.
#
# This option keeps the original calculation methods and just adds grouped_count
# as a shortcut wrapper for using existing group_values from the relation, instead of
# requiring it be specified.
#
# (I'm showing count and average as examples of optional & required column_name params,
# but this would apply to all calculation methods.)
relation = Post.group("author_id").order("created_at")
#
# count(column_name=nil, options={})
#
relation.count # => Fixnum
# SELECT COUNT(*) FROM (((SELECT ...))) posts
relation.count(:name) # => Fixnum
# SELECT COUNT(posts.name) FROM (((SELECT ...))) posts
relation.count(:group => "author_id") # => Hash
# SELECT posts.author_id, COUNT(*) FROM (((SELECT ...))) posts GROUP BY posts.author_id
relation.count(:name, :group => "author_id") # => Hash
# SELECT posts.author_id, COUNT(posts.name) FROM (((SELECT ...))) posts GROUP BY posts.author_id
#
# average(column_name, options={})
#
relation.average(:rating) # => Float
# SELECT AVG(posts.rating) FROM (((SELECT ...))) posts
relation.average(:rating, :group => "author_id")
# SELECT posts.author_id, AVG(posts.rating) FROM (((SELECT ...))) posts GROUP BY posts.author_id
#
# grouped_count(column_name=nil)
#
# * raises error if relation has no group_values
#
relation.grouped_count # => Hash
# SELECT posts.author_id, COUNT(*) FROM (((SELECT ...))) posts GROUP BY posts.author_id
relation.grouped_count(:name) # => Hash
# SELECT posts.author_id, COUNT(posts.name) FROM (((SELECT ...))) posts GROUP BY posts.author_id
#
# grouped_average(column_name)
#
# * raises error if relation has no group_values
#
relation.grouped_average(:rating) # => Hash
# SELECT posts.author_id, AVG(posts.rating) FROM (((SELECT ...))) posts GROUP BY posts.author_id
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment