class Ruby::Reports::BaseReport

Class describes base report class for inheritance. BaseReport successor must implement “write(io, force)” method and may specify file extension with “extension” method call example:

class CustomTypeReport < Resque::Reports::BaseReport
  extension :type # specify that report file must ends
                  # with '.type', e.g. 'abc.type'

  # Method specifies how to output report data
  def write(io, force)
    io << 'Hello World!'
  end
end

BaseReport provides following DSL, example:

class CustomReport < CustomTypeReport
  # include Resque::Reports::Common::BatchedReport
  #   overrides data retrieving to achieve batching
  #   if included 'source :select_data' becomes needless

  queue :custom_reports # Resque queue name
  source :select_data # method called to retrieve report data
  encoding UTF8 # file encoding
  expire_in 86_400 # cache time of the file, default: 86_400

  # Specify in which directory to keep this type files
  directory File.join(Dir.tmpdir, 'resque-reports')

  # Describe table using 'column' method
  table do |element|
    column 'Column 1 Header', :decorate_one
    column 'Column 2 Header', decorate_two(element[1])
    column 'Column 3 Header', 'Column 3 Cell'
    column 'Column 4 Header', :formatted_four, formatter: :just_cute
  end

  # Class initialize if needed
  # NOTE: must be used instead of define 'initialize' method
  # Default behaviour is to receive in *args Hash with report attributes
  # like: CustomReport.new(main_param: 'value') => calls send(:main_param=, 'value')
  create do |param|
    @main_param = param
  end

  def self.just_cute_formatter(column_value)
    "I'm so cute #{column_value}"
  end

  # decorate method, called by symbol-name
  def decorate_one(element)
    "decorate_one: #{element[0]}"
  end

  # decorate method, called directly when filling cell
  def decorate_two(text)
    "decorate_two: #{text}"
  end

  # method returns report data Enumerable
  def select_data
    [[0, 'text0'], [1, 'text1']]
  end
end

Attributes

config_hash[R]
error_handle_block[R]
progress_handle_block[R]
table_block[R]
args[R]
events_handler[R]
job_id[R]

Public Class Methods

build(options = {}) click to toggle source
# File lib/ruby/reports/base_report.rb, line 85
def build(options = {})
  force = options.delete(:force)

  report = new(options)
  report.build(force)

  report
end
config(hash) click to toggle source
# File lib/ruby/reports/base_report.rb, line 77
def config(hash)
  @config_hash = hash
end
new(*args) click to toggle source
# File lib/ruby/reports/base_report.rb, line 102
def initialize(*args)
  @args = args
  assign_attributes
end
table(&block) click to toggle source
# File lib/ruby/reports/base_report.rb, line 81
def table(&block)
  @table_block = block
end

Public Instance Methods

build(force = false) click to toggle source

Builds report synchronously

# File lib/ruby/reports/base_report.rb, line 108
def build(force = false)
  @table = nil if force
  @events_handler = Services::EventsHandler.new(@progress_handle_block, @error_handle_block)

  cache_file.open(force) { |file| write(file, force) }
end
error_handler(&block) click to toggle source
# File lib/ruby/reports/base_report.rb, line 119
def error_handler(&block)
  @error_handle_block = block
end
progress_handler(&block) click to toggle source
# File lib/ruby/reports/base_report.rb, line 115
def progress_handler(&block)
  @progress_handle_block = block
end

Private Instance Methods

assign_attributes() click to toggle source
# File lib/ruby/reports/base_report.rb, line 133
def assign_attributes
  if args && (attrs_hash = args.first) && attrs_hash.is_a?(Hash)
    attrs_hash.each { |name, value| instance_variable_set("@#{name}", value) }
  end
end
cache_file() click to toggle source
# File lib/ruby/reports/base_report.rb, line 153
def cache_file
  @cache_file ||= CacheFile.new(config.directory,
                                Services::FilenameGenerator.generate(args, config.extension),
                                expire_in: config.expire_in, coding: config.encoding)
end
config() click to toggle source
# File lib/ruby/reports/base_report.rb, line 129
def config
  @config ||= Config.new(self.class.config_hash)
end
formatter() click to toggle source
# File lib/ruby/reports/base_report.rb, line 125
def formatter
  nil
end
iterator() click to toggle source
# File lib/ruby/reports/base_report.rb, line 145
def iterator
  @iterator ||= Services::DataIterator.new(query, config)
end
query() click to toggle source
# File lib/ruby/reports/base_report.rb, line 139
def query
  # descendant of QueryBuilder or SqlQuery with #take_batch(limit, offset) method defined
  # @query ||= Query.new(self)
  fail NotImplementedError
end
table() click to toggle source
# File lib/ruby/reports/base_report.rb, line 149
def table
  @table ||= Services::TableBuilder.new(self, self.class.table_block, config, formatter)
end
write(io, force) click to toggle source

Method specifies how to output report data @param [IO] io stream for output @param [true, false] force write to output or skip due its existance

# File lib/ruby/reports/base_report.rb, line 162
def write(io, force)
  # You must use ancestor methods to work with report data:
  # 1) iterator.data_size => returns source data size (calls #count on data
  #                 retrieved from 'source')
  # 2) iterator.data_each => yields given block for each source data element
  # 3) table.build_header => returns Array of report column names
  # 4) table.build_row(object) => returns Array of report cell
  #                               values (same order as header)
  # 5) events_handler.progress(progress, total) => call to iterate job progress
  # 6) events_handler.error(error) => call to handle error in job
  #
  # HINT: You may override data_size and data_each, to retrieve them
  #       effectively
  fail NotImplementedError
end