Module: WeightedAverage::ActiveRecordRelationInstanceMethods

Defined in:
lib/weighted_average/active_record_relation_instance_methods.rb

Instance Method Summary collapse

Instance Method Details

#weighted_average(data_column_names, options = {}) ⇒ Float?

Get the weighted average of column(s).

In addition to the options available on WeightedAverage::ArelSelectManagerInstanceMethods#weighted_average, this ActiveRecord-specific method understands associations.

Examples:

Get the average m3 of all aircraft, weighted by a column named :weighting in flight segments table. But wait… there is no column called :weighting! So see the next example.

Aircraft.weighted_average(:m3, :weighted_by => :segments)

Get the average m3 of all aircraft, weighted by how many :passengers flew in a particular aircraft.

Aircraft.weighted_average(:m3, :weighted_by => [:segments, :passengers])

Parameters:

  • data_column_names (Symbol, Array<Symbol>)

    One or more column names whose average should be calculated. Added together before being multiplied by the weighting if more than one.

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :weighted_by (Symbol)

    The name of an association to weight against OR a column name just like in the pure ARel version.

  • :weighted_by (Array{Symbol,Symbol})

    The name of an association and a weighting column inside that association table to weight against. Not available in the pure ARel version.

  • :disaggregate_by (Symbol)

    Same as its meaning in the pure ARel version.

Returns:

  • (Float, nil)

See Also:



23
24
25
26
# File 'lib/weighted_average/active_record_relation_instance_methods.rb', line 23

def weighted_average(data_column_names, options = {})
  weighted_average = connection.select_value weighted_average_relation(data_column_names, options).to_sql
  weighted_average.nil? ? nil : weighted_average.to_f
end

#weighted_average_relation(data_column_names, options = {}) ⇒ Arel::SelectManager

Same as WeightedAverage::ArelSelectManagerInstanceMethods#weighted_average, except it can interpret associations.

Returns:

  • (Arel::SelectManager)

See Also:



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/weighted_average/active_record_relation_instance_methods.rb', line 33

def weighted_average_relation(data_column_names, options = {})
  if weighted_by_option = options[:weighted_by]
    case weighted_by_option
    when Array
      # :weighted_by specifies a custom column on an association table (least common)
      unless association = reflect_on_association(weighted_by_option.first)
        raise ArgumentError, "#{name} does not have association #{weighted_by_option.first.inspect}"
      end
      weighted_by_column = association.klass.arel_table[weighted_by_option.last]
    when Symbol, String
      if association = reflect_on_association(weighted_by_option)
        # :weighted_by specifies an association table with a column named "weighting"
        weighted_by_column = association.klass.arel_table[DEFAULT_WEIGHTED_BY_COLUMN_NAME]
      else
        # :weighted_by specifies a custom column on the same table
        weighted_by_column = arel_table[weighted_by_option]
      end
    end
    if association
      joins(association.name).arel.weighted_average_relation data_column_names, options.merge(:weighted_by => weighted_by_column)
    else
      arel.weighted_average_relation data_column_names, options.merge(:weighted_by => weighted_by_column)
    end
  else
    arel.weighted_average_relation data_column_names, options
  end
end