module RubyReportable::Report

Attributes

data_source[RW]
filters[RW]
records_returned[RW]

Public Instance Methods

_convert_for_sort(value) click to toggle source
# File lib/ruby_reportable/report.rb, line 174
def _convert_for_sort(value)
  case value.class
  when NilClass
    value.to_s
  when Date, DateTime, Time
    value
  when Array
    value.map {|sub| _convert_for_sort(sub)}
  else
    value.to_s
  end
end
_data(sandbox, options = {}) click to toggle source
# File lib/ruby_reportable/report.rb, line 143
def _data(sandbox, options = {})
  _filter(@filters, sandbox, options)
end
_filter(filters, original_sandbox, options) click to toggle source
# File lib/ruby_reportable/report.rb, line 117
def _filter(filters, original_sandbox, options)
  # sort filters by priority then apply to sandbox
  filters.sort_by do |filter_name, filter|
    filter[:priority]
  end.inject(original_sandbox) do |sandbox, (filter_name, filter)|

    # find input for given filter
    sandbox[:input] = options[:input][filter[:key]] if options[:input].is_a?(Hash)

    if filter[:valid].nil? || sandbox.instance_eval(&filter[:valid])
      if filter[:logic].nil?
        sandbox
      else
        sandbox.build(:source, filter[:logic])
      end
    else
      sandbox
    end
  end
end
_finalize(sandbox, options = {}) click to toggle source
# File lib/ruby_reportable/report.rb, line 147
def _finalize(sandbox, options = {})
  if @finalize.nil?
    sandbox
  else
    sandbox[:inputs] = options[:input] || {}
    sandbox.build(:source, @finalize)
  end
end
_group(group, data, options = {}) click to toggle source
# File lib/ruby_reportable/report.rb, line 197
def _group(group, data, options = {})
  # Run through elements in data which are ordered
  # from the previous call to #_sort via #run
  #
  # Since the elements are already sorted, as we pop
  # them into their grouping they will remain sorted as
  # intended
  #
  if group.to_s.empty?
    {:results => data}
  else
    group = [group] unless group.is_a?(Array)
    group.map!(&:to_s)

    # the last group critieria should contain an array
    # so lets pop it off for special use
    last_group = group.pop

    data.inject({}) do |hash, element|
      # grab a local reference to the hash
      ref = hash

      # run through initial groupings to grab local ref
      # and default them to {}
      group.map do |grouping|
        key = element[grouping]
        ref[key] ||= {}
        ref = ref[key]
      end

      # handle our last grouping
      key = element[last_group]
      ref[key] ||= []
      ref[key] << element

      hash
    end
  end
end
_output(source_data, options = {}) click to toggle source
# File lib/ruby_reportable/report.rb, line 156
def _output(source_data, options = {})
  # build sandbox for building outputs
  sandbox = RubyReportable::Sandbox.new(:meta => @meta, :inputs => options[:input] || {}, @data_source[:as] => nil)

  source_data.inject([]) do |rows, element|
    # fill sandbox with data element
    sandbox[@data_source[:as]] = element

    # grab outputs
    rows << @outputs.inject({}) do |row, output|
      row[output.name] = sandbox.instance_eval(&output.logic)
      row
    end

    rows
  end
end
_sort(sort, data, options = {}) click to toggle source
# File lib/ruby_reportable/report.rb, line 187
def _sort(sort, data, options = {})
  if sort.to_s.empty?
    data
  else
    sort = [sort] unless sort.is_a?(Array)

    data.sort_by {|element| sort.map {|column| _convert_for_sort(element[column]) }}
  end
end
_source(options = {}) click to toggle source
# File lib/ruby_reportable/report.rb, line 138
def _source(options = {})
  # build sandbox for getting the data
  RubyReportable::Sandbox.new(:meta => @meta, :source => @data_source[:logic], :inputs => options[:input] || {}, :input => nil)
end
allow_group(string = nil) click to toggle source
# File lib/ruby_reportable/report.rb, line 59
def allow_group(string = nil)
  if string.nil?
    @allow_group
  else
    @allow_group = string
  end
end
allow_sort(string = nil) click to toggle source
# File lib/ruby_reportable/report.rb, line 67
def allow_sort(string = nil)
  if string.nil?
    @allow_sort
  else
    @allow_sort = string
  end
end
benchmark(name) { || ... } click to toggle source
# File lib/ruby_reportable/report.rb, line 26
def benchmark(name)
  benchmarks[name] ||= 0.0

  @result = nil

  time = Benchmark.realtime do
    @result = yield
  end

  benchmarks[name] += time
  @result
end
benchmarks() click to toggle source

:sandbox, :filters, :finalize, :output, :group, :sort

# File lib/ruby_reportable/report.rb, line 22
def benchmarks
  @benchmarks ||= {}
end
category(string = nil) click to toggle source
# File lib/ruby_reportable/report.rb, line 75
def category(string = nil)
  if string.nil?
    @category
  else
    @category = string
  end
end
clear() click to toggle source
# File lib/ruby_reportable/report.rb, line 8
def clear
  @outputs = []
  @filters = {}
  @data_source = nil
  @report = self.to_s
  @category = 'Reports'
  @allow_group = true
  @allow_sort = true
  @meta = {}
  @benchmarks = {}
  @records_returned = 0
end
filter(name, &block) click to toggle source
# File lib/ruby_reportable/report.rb, line 88
def filter(name, &block)
  @filters[name] = RubyReportable::Filter.new(name)
  @filters[name].instance_eval(&block)
end
finalize(&block) click to toggle source
# File lib/ruby_reportable/report.rb, line 93
def finalize(&block)
  @finalize = block
end
meta(key, value = nil, &block) click to toggle source
# File lib/ruby_reportable/report.rb, line 39
def meta(key, value = nil, &block)
  if block_given?
    @meta[key] = block
  else
    if value.nil?
      @meta[key]
    else
      @meta[key] = value
    end
  end
end
output(name, options = {}, &block) click to toggle source
# File lib/ruby_reportable/report.rb, line 97
def output(name, options = {}, &block)
  @outputs << RubyReportable::Output.new(name, options, block)
end
outputs(hidden = false) click to toggle source

methods you shouldn't use inside the blocks

# File lib/ruby_reportable/report.rb, line 105
def outputs(hidden = false)
  if hidden
    @outputs
  else
    @outputs.select {|output| output[:hidden] != true}
  end
end
report(string = nil) click to toggle source
# File lib/ruby_reportable/report.rb, line 51
def report(string = nil)
  if string.nil?
    @report
  else
    @report = string
  end
end
run(options = {}) click to toggle source
# File lib/ruby_reportable/report.rb, line 237
def run(options = {})
  options = {:input => {}}.merge(options)

  # initial sandbox
  sandbox = benchmark(:sandbox) do
    _source(options)
  end

  # apply filters to source
  filtered_sandbox = benchmark(:filters) do
    _data(sandbox, options)
  end

  # finalize raw data from source
  source_data = benchmark(:finalize) do
    _finalize(filtered_sandbox, options).source
  end

  # {:default => [{outputs => values}]
  data = benchmark(:output) do
    _output(source_data, options)
  end

  # now that we have all of our data go ahead and cache the size
  records_returned = data.size

  # sort the data first cause that makes sense you know
  sorted = benchmark(:sort) do
    _sort(options[:sort], data, options)
  end

  # transform into {group => {group => [outputs => values]}}
  # level of grouping depends on how many groups are passed in
  benchmark(:group) do
    _group(options[:group], sorted, options)
  end
end
source(&block) click to toggle source
# File lib/ruby_reportable/report.rb, line 83
def source(&block)
  @data_source = RubyReportable::Source.new
  @data_source.instance_eval(&block)
end
useable_filters(scope) click to toggle source
# File lib/ruby_reportable/report.rb, line 113
def useable_filters(scope)
  @filters.values.select {|filter| !filter[:input].nil? && (filter[:use].nil? || filter[:use].call(scope))}.sort_by {|filter| filter[:priority].to_i}
end
valid?(options = {}) click to toggle source
# File lib/ruby_reportable/report.rb, line 275
def valid?(options = {})
  options = {:input => {}}.merge(options)
  errors = []

  # initial sandbox
  sandbox = _source(options)

  # add in inputs
  sandbox[:inputs] = options[:input]

  validity = @filters.map do |filter_name, filter|

    # find input for given filter
    sandbox[:input] = options[:input][filter[:key]] if options[:input].is_a?(Hash)

    filter_validity = filter[:valid].nil? || sandbox.instance_eval(&filter[:valid])

    if filter_validity == false
      # Ignore an empty filter unless it's required
      if !sandbox[:input].to_s.blank?
        errors << "#{filter_name} is invalid."
        false
      else
        if sandbox[:input].to_s.blank? && !filter[:require].blank?
          errors << "#{filter_name} is required."
          false
        else
          true
        end
      end
    elsif filter_validity == true
      if sandbox[:input].to_s.blank? && !filter[:require].blank?
        errors << "#{filter_name} is required."
        false
      else
        true
      end
    elsif !filter_validity.nil? && !filter_validity[:status].nil? && filter_validity[:status] == false
      # Ignore an empty filter unless it's required or the error is forced.
      if !sandbox[:input].to_s.blank? || filter_validity[:force_error] == true
        errors << filter_validity[:errors]
        false
      else
        if sandbox[:input].to_s.blank? && !filter[:require].blank?
          errors << "#{filter_name} is required."
          false
        else
          true
        end
      end
    end
  end

  return {:status => !validity.include?(false), :errors => errors}

end