class Repor::Dimensions::BinDimension

Public Instance Methods

bin_start() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 79
def bin_start
  self.min
end
bin_width() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 75
def bin_width
  raise NotImplementedError
end
domain() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 24
def domain
  return 0 if min.nil? || max.nil?
  max - min
end
filter(relation) click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 37
def filter(relation)
  filter_values.filter(relation, expression)
end
filter_max() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 20
def filter_max
  filter_values_for(:max).max
end
filter_min() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 16
def filter_min
  filter_values_for(:min).min
end
filter_values() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 33
def filter_values
  @filter_values ||= to_bins(super)
end
group(relation) click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 41
def group(relation)
  group_values.group(relation, expression, sql_value_name)
end
group_values() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 29
def group_values
  @group_values ||= to_bins(array_param(:bins).presence || autopopulate_bins)
end
max() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 12
def max
  @max ||= filter_max || report.records.maximum(expression)
end
max_bins() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 4
def max_bins
  2000
end
min() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 8
def min
  @min ||= filter_min || report.records.minimum(expression)
end
validate_params!() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 45
def validate_params!
  super

  if params.key?(:bin_count)
    unless Repor.numeric?(params[:bin_count])
      invalid_param!(:bin_count, "must be numeric")
    end

    unless params[:bin_count].to_i > 0
      invalid_param!(:bin_count, "must be greater than 0")
    end

    unless params[:bin_count].to_i <= max_bins
      invalid_param!(:bin_count, "must be less than #{max_bins}")
    end
  end

  if array_param(:bins).present?
    unless group_values.all?(&:valid?)
      invalid_param!(:bins, "must be hashes with min/max keys and valid values, or nil")
    end
  end

  if array_param(:only).present?
    unless filter_values.all?(&:valid?)
      invalid_param!(:only, "must be hashes with min/max keys and valid values, or nil")
    end
  end
end

Private Instance Methods

autopopulate_bins() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 117
def autopopulate_bins
  iters = 0
  bins = []
  bin_edge = self.bin_start
  return bins if bin_edge.blank? || max.blank?
  approx_count = (max - bin_edge)/(bin_width)
  if approx_count > max_bins
    invalid_param!(:bin_width, "is too small for the domain; would generate #{approx_count} bins")
  end

  loop do
    break if bin_edge > max
    break if bin_edge == max && filter_values_for(:max).present?
    bin = { min: bin_edge, max: bin_edge + bin_width }
    bins << bin
    bin_edge = bin[:max]
    iters += 1
    raise "too many bins, likely an internal error" if iters > max_bins
  end

  bins.reverse! if sort_desc?

  if data_contains_nil?
    nulls_last?? bins.push(nil) : bins.unshift(nil)
  end

  bins
end
bin_class() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 97
def bin_class
  self.class.const_get(:Bin)
end
bin_table_class() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 93
def bin_table_class
  self.class.const_get(:BinTable)
end
data_contains_nil?() click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 113
def data_contains_nil?
  report.records.where("#{expression} IS NULL").exists?
end
filter_values_for(key) click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 85
def filter_values_for(key)
  filter_values.each_with_object([]) do |filter, values|
    if value = filter.send(key)
      values << value
    end
  end
end
sanitize_sql_value(value) click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 109
def sanitize_sql_value(value)
  bin_class.from_sql(value)
end
to_bin(bin) click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 105
def to_bin(bin)
  bin_class.from_hash(bin)
end
to_bins(bins) click to toggle source
# File lib/repor/dimensions/bin_dimension.rb, line 101
def to_bins(bins)
  bin_table_class.new(bins.map(&method(:to_bin)))
end