Module: WeightedAverage
- Defined in:
- lib/weighted_average.rb,
lib/weighted_average/version.rb
Constant Summary collapse
- VERSION =
'1.0.3'
Instance Method Summary collapse
-
#weighted_average(*args) ⇒ Object
Returns a number.
-
#weighted_average_relation(data_column_names, options = {}) ⇒ Object
Returns the ARel relation for a weighted average query.
Instance Method Details
#weighted_average(*args) ⇒ Object
Returns a number.
7 8 9 10 |
# File 'lib/weighted_average.rb', line 7 def weighted_average(*args) weighted_average = connection.select_value(weighted_average_relation(*args).to_sql, 'weighted_average') weighted_average.nil? ? nil : weighted_average.to_f end |
#weighted_average_relation(data_column_names, options = {}) ⇒ Object
Returns the ARel relation for a weighted average query.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 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 60 61 62 63 64 |
# File 'lib/weighted_average.rb', line 13 def weighted_average_relation(data_column_names, = {}) raise ::ArgumentError, "Only use array form if the weighting column in the foreign table is not called 'weighting'" if [:weighted_by].is_a?(::Array) and [:weighted_by].length != 2 raise ::ArgumentError, "No nil values in weighted_by, please" if ::Array.wrap([:weighted_by]).any?(&:nil?) # :airline_aircraft_seat_class association = if [:weighted_by].present? [:weighted_by].is_a?(::Array) ? reflect_on_association([:weighted_by].first.to_sym) : reflect_on_association([:weighted_by].to_sym) end # AirlineAircraftSeatClass association_class = association.klass if association # `airline_aircraft_seat_classes` weighted_by_table_name = if association_class association_class.quoted_table_name else quoted_table_name end # `airline_aircraft_seat_classes`.`weighting` weighted_by_column_name = if association_class and [:weighted_by].is_a?(::Array) [:weighted_by].last.to_s elsif !association_class and ([:weighted_by].is_a?(::String) or [:weighted_by].is_a?(::Symbol)) [:weighted_by].to_s else 'weighting' end weighted_by_column_name = [ weighted_by_table_name, connection.quote_column_name(weighted_by_column_name) ].join '.' # `aircraft`.`passengers` disaggregate_by_column_name = if [:disaggregate_by] [ quoted_table_name, connection.quote_column_name([:disaggregate_by]) ].join '.' end # [ `aircraft`.`foo`, `aircraft`.`baz` ] data_column_names = ::Array.wrap(data_column_names).map do |data_column_name| [ quoted_table_name, connection.quote_column_name(data_column_name) ].join '.' end relation = select("(SUM(1.0 * (#{data_column_names.join(' + ')}) #{"/ #{disaggregate_by_column_name} " if disaggregate_by_column_name}* #{weighted_by_column_name}) / SUM(#{weighted_by_column_name})) AS weighted_average") data_column_names.each do |data_column_name| relation = relation.where("#{data_column_name} IS NOT NULL") end # avoid division by zero relation = relation.where("#{weighted_by_column_name} > 0") relation = relation.where("#{disaggregate_by_column_name} > 0") if disaggregate_by_column_name # FIXME this will break on through relationships, where it has to be :aircraft => :aircraft_class relation = relation.joins(association.name) if association_class relation end |