class Resque::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
Constants
- DEFAULT_QUEUE
Attributes
_directory[RW]
_encoding[RW]
_expire_in[RW]
_extension[RW]
_output_filename[RW]
_queue[RW]
create_block[R]
directory[RW]
encoding[RW]
expire_in[RW]
extension[RW]
output_filename[RW]
queue[RW]
super_extension[RW]
job_id[R]
Public Class Methods
build(options = {})
click to toggle source
# File lib/resque/reports/base_report.rb, line 152 def self.build(options = {}) in_background = options.delete(:background) force = options.delete(:force) report = new(options) in_background ? report.bg_build(force) : report.build(force) report end
new(*args)
click to toggle source
# File lib/resque/reports/base_report.rb, line 166 def initialize(*args) # TODO: Check consistance, fail if user initialized wrong object set_instance(self) if create_block define_singleton_method(:create_dispatch, create_block) create_dispatch(*args) else if args && (attrs_hash = args.first) && attrs_hash.is_a?(Hash) attrs_hash.each { |name, value| send("#{name}=", value) } end end @args = args init_cache_file init_table end
Protected Class Methods
create(&block)
click to toggle source
# File lib/resque/reports/base_report.rb, line 99 def create(&block) @create_block = block end
encoded_string(obj)
click to toggle source
override for Extenstions::TableBuilding, to use custom encoding
# File lib/resque/reports/base_report.rb, line 104 def encoded_string(obj) obj.to_s.encode(_encoding, invalid: :replace, undef: :replace) end
method_missing(method_name, *args, &block)
click to toggle source
Calls superclass method
# File lib/resque/reports/base_report.rb, line 114 def method_missing(method_name, *args, &block) if @instance.respond_to?(method_name) @instance.send(method_name, *args, &block) else super end end
respond_to?(method, include_private = false)
click to toggle source
Calls superclass method
# File lib/resque/reports/base_report.rb, line 122 def respond_to?(method, include_private = false) super || @instance.respond_to?(method, include_private) end
set_instance(obj)
click to toggle source
# File lib/resque/reports/base_report.rb, line 95 def set_instance(obj) @instance = obj end
Public Instance Methods
bg_build(force = false)
click to toggle source
Builds report in background, returns job_id
, to watch progress
# File lib/resque/reports/base_report.rb, line 193 def bg_build(force = false) report_class = self.class.to_s args_json = [*@args, force].to_json # Check report if it already in progress and tring return its job_id... @job_id = ReportJob.enqueued?(report_class, args_json).try(:meta_id) # ...and start new job otherwise @job_id ||= ReportJob.enqueue_to(_queue || DEFAULT_QUEUE, report_class, args_json).try(:meta_id) end
build(force = false)
click to toggle source
Builds report synchronously
# File lib/resque/reports/base_report.rb, line 186 def build(force = false) init_table if force @cache_file.open(force) { |file| write(file, force) } end
Protected Instance Methods
init_cache_file()
click to toggle source
# File lib/resque/reports/base_report.rb, line 207 def init_cache_file self._extension = super_extension || DEFAULT_EXTENSION options = {coding: _encoding, expire_in: _expire_in} @cache_file = CacheFile.new(_directory, generate_filename(@args, _extension), options) 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/resque/reports/base_report.rb, line 219 def write(io, force) # You must use ancestor methods to work with report data: # 1) data_size => returns source data size (calls #count on data # retrieved from 'source') # 2) data_each => yields given block for each source data element # 3) build_table_header => returns Array of report column names # 4) build_table_row(object) => returns Array of report cell # values (same order as header) # 5) progress_message(progress, # total) => call to iterate job progress # 6) error_message(error) => call to handle error in job # # HINT: You may override data_size and data_each, to retrieve them # effectively fail NotImplementedError end