Module: Juixe::Acts::Voteable::SingletonMethods

Defined in:
lib/acts_as_voteable.rb

Overview

This module contains class methods

Instance Method Summary collapse

Instance Method Details

#options_for_tally(options = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/acts_as_voteable.rb', line 78

def options_for_tally (options = {})
    options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :at_least_total, :at_most_total 

    scope = scope(:find)
    start_at = sanitize_sql(["#{Vote.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
    end_at = sanitize_sql(["#{Vote.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]

    if respond_to?(:vote_counter_column)
      # use the counter cache column if present.
      total_col       = "#{table_name}.#{vote_counter_column}"
      at_least_total  = sanitize_sql(["#{total_col} >= ?", options.delete(:at_least_total)]) if options[:at_least_total] 
      at_most_total   = sanitize_sql(["#{total_col} <= ?", options.delete(:at_most_total)])  if options[:at_most_total]
    end
    conditions = [
      options[:conditions],
      at_least_total,
      at_most_total,
      start_at,
      end_at
    ]

    conditions = conditions.compact.join(' AND ')
    conditions = merge_conditions(conditions, scope[:conditions]) if scope

    type_and_context = "#{Vote.table_name}.voteable_type = #{quote_value(base_class.name)}"
    joins = ["LEFT OUTER JOIN #{Vote.table_name} ON #{table_name}.#{primary_key} = #{Vote.table_name}.voteable_id AND #{type_and_context}"]
    joins << scope[:joins] if scope && scope[:joins]
    at_least  = sanitize_sql(["COUNT(#{Vote.table_name}.id) >= ?", options.delete(:at_least)]) if options[:at_least]
    at_most   = sanitize_sql(["COUNT(#{Vote.table_name}.id) <= ?", options.delete(:at_most)]) if options[:at_most]
    at_least_total = at_most_total = nil # reset the values 
    unless respond_to?(:vote_counter_column)
      # aggregate the votes when counter cache is absent.
      total_col       = "SUM(#{Vote.table_name}.vote)"
      at_least_total  = sanitize_sql(["#{total_col} >= ?", options.delete(:at_least_total)]) if options[:at_least_total]
      at_most_total   = sanitize_sql(["#{total_col} <= ?", options.delete(:at_most_total)]) if options[:at_most_total]
    end
    having    = [at_least, at_most, at_least_total, at_most_total].compact.join(' AND ')
    group_by  = "#{Vote.table_name}.voteable_id HAVING COUNT(#{Vote.table_name}.id) > 0"
    group_by << " AND #{having}" unless having.blank?
  
    { :select     => "#{table_name}.*, COUNT(#{Vote.table_name}.id) AS count, #{total_col} AS total", 
      :joins      => joins.join(" "),
      :conditions => conditions,
      :group      => group_by
    }.update(options)          
end

#tally(options = {}) ⇒ Object

Calculate the vote counts for all voteables of my type. Options:

:start_at    - Restrict the votes to those created after a certain time
:end_at      - Restrict the votes to those created before a certain time
:conditions  - A piece of SQL conditions to add to the query
:limit       - The maximum number of voteables to return
:order       - A piece of SQL to order by. Two calculated columns `count`, and `total`
               are available for sorting apart from other columns. Defaults to `total DESC`. 
                 Eg: :order => 'count desc'
                     :order => 'total desc'
                     :order => 'post.created_at desc'
:at_least    - Item must have at least X votes count
:at_most     - Item may not have more than X votes count
:at_least_total    - Item must have at least X votes total
:at_most_total     - Item may not have more than X votes total


74
75
76
# File 'lib/acts_as_voteable.rb', line 74

def tally(options = {})
  find(:all, options_for_tally({:order =>"total DESC" }.merge(options)))
end