diff --git a/README.md b/README.md index 389db40..2bd25ce 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,69 @@ # Ruby::Reports -Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ruby/reports`. To experiment with that code, run `bin/console` for an interactive prompt. +This gem was written for report automation provided by DSL. -TODO: Delete this and the text above, and describe your gem +Main concept is following: +- You have report class where you define attributes, column names and mapped to them + keys from source data +- Report has ```query``` method. It defines what object will serve data querying from any source +- (Optional) Report has ```formatter``` method. It defines what object will serve cell value formatting + +Example: +```ruby + class MyNiceReport < Ruby::Reports::CsvReport + config( + source: :fetch_data, + expire_in: 15 * 60, + encoding: Ruby::Reports::CP1251, + directory: File.join('/home', 'my_home', 'nice_reports') + ) + + table do + column 'ID', :id + column 'User Name', :username + column 'Email', :email, formatter: :mail_to_link + column 'Last Seen', :last_seen_date, formatter: :date + end + + def formatter + @formatter ||= Formatter.new + end + + def query + @query ||= Query.new(self) + end + + class Formatter + def mail_to_link(email) + "mailto:#{email}" + end + + def date(date) + Date.parse(date).strftime('%d.%m.%Y') + end + end + + class Query < Ruby::Reports::Services::QueryBuilder + def fetch_data + [ + {id: 1, username: 'user#1', email: 'user1@reports.org', last_seen_date: '2015/06/06'}, + {id: 2, username: 'user#2', email: 'user2@reports.org', last_seen_date: '2015/02/07'}, + {id: 3, username: 'user#3', email: 'user3@reports.org', last_seen_date: '2015/08/13'} + ] + end + end + end + + > report = MyNiceReport.build + # => # + > report.ready? + # => true + > report.filename + # => '/home/my_home/nice_reports/asdvdsadvasdv.csv' + > IO.read(report.filename) + # => "ID;User Name;Email;Last Seen\r\n1;user#1;mailto:user1@reports.org;06.06.2015\r\n + # 2;user#2;mailto:user2@reports.org;07.02.2015\r\n3;user#3;mailto:user3@reports.org;13.08.2015\r\n" +``` ## Installation @@ -32,8 +93,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To ## Contributing -Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/ruby-reports. - +Bug reports and pull requests are welcome on GitHub at https://github.com/sclinede/ruby-reports. ## License diff --git a/lib/ruby/reports/base_report.rb b/lib/ruby/reports/base_report.rb index be5ebab..87d6f7d 100644 --- a/lib/ruby/reports/base_report.rb +++ b/lib/ruby/reports/base_report.rb @@ -101,6 +101,7 @@ def build(options = {}) def initialize(*args) @args = args + assign_attributes end # Builds report synchronously @@ -125,6 +126,12 @@ def formatter private + 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 + def query # descendant of QueryBuilder or SqlQuery with #take_batch(limit, offset) method defined # @query ||= Query.new(self) diff --git a/lib/ruby/reports/services/data_iterator.rb b/lib/ruby/reports/services/data_iterator.rb index 2118c2c..2e672ba 100644 --- a/lib/ruby/reports/services/data_iterator.rb +++ b/lib/ruby/reports/services/data_iterator.rb @@ -7,7 +7,7 @@ class DataIterator @custom_source = query.send(config.source) if config.source end - def iterate_data_source + def iterate_custom_source custom_source.each do |row| yield row end @@ -16,7 +16,7 @@ def iterate_data_source # # Returns Nothing def data_each(force = false, &block) - return iterate_data_source(&block) if custom_source + return iterate_custom_source(&block) if custom_source batch_offset = 0 @@ -34,7 +34,6 @@ def data_size custom_source.size else query.request_count - # expects Integer, like connection.execute(count_sql)[0]['count'].to_i end end end diff --git a/lib/ruby/reports/services/filename_generator.rb b/lib/ruby/reports/services/filename_generator.rb index b7c74ed..28e5d9b 100644 --- a/lib/ruby/reports/services/filename_generator.rb +++ b/lib/ruby/reports/services/filename_generator.rb @@ -1,3 +1,6 @@ +require 'digest' +require 'json' + # coding: utf-8 module Ruby module Reports diff --git a/lib/ruby/reports/services/table_builder.rb b/lib/ruby/reports/services/table_builder.rb index 785f044..41185fc 100644 --- a/lib/ruby/reports/services/table_builder.rb +++ b/lib/ruby/reports/services/table_builder.rb @@ -2,7 +2,7 @@ require 'iron/dsl' # coding: utf-8 -# Resque namespace +# Ruby namespace module Ruby # Resque::Reports namespace module Reports @@ -15,11 +15,7 @@ class TableBuilder init_table end - def encoded_string(obj) - obj.to_s.encode(config.encoding, invalid: :replace, undef: :replace) - end - - def column(name, value, options = {}) + def column(name, value = nil, options = {}) if (skip_if = options.delete(:skip_if)) if skip_if.is_a?(Symbol) return if report.send(skip_if) @@ -28,7 +24,27 @@ def column(name, value, options = {}) end end - building_header ? add_column_header(name) : add_column_cell(value, options) + building_header ? add_header_cell(name) : add_row_cell(value, options) + end + + def build_row(row) + @row = row.is_a?(Hash) ? row.rekey! : row + row = DslProxy.exec(self, @row, &table_block) + cleanup_row + row + end + + def build_header + @building_header = true + header = DslProxy.exec(self, Dummy.new, &table_block) + @building_header = false + header + end + + private + + def encoded_string(obj) + obj.to_s.encode(config.encoding, invalid: :replace, undef: :replace) end def init_table @@ -40,12 +56,12 @@ def cleanup_row @table_row = [] end - def add_column_header(column_name) + def add_header_cell(column_name) @table_header << encoded_string(column_name) end - def add_column_cell(column_value, options = {}) - column_value = @row_object[column_value] if column_value.is_a? Symbol + def add_row_cell(column_value, options = {}) + column_value = @row[column_value] if column_value.is_a? Symbol if (formatter_name = options[:formatter]) column_value = report.formatter.send(formatter_name, column_value) @@ -54,20 +70,6 @@ def add_column_cell(column_value, options = {}) @table_row << encoded_string(column_value) end - def build_row(row_object) - @row_object = row_object.is_a?(Hash) ? row_object.rekey! : row_object - row = DslProxy.exec(self, @row_object, &table_block) - cleanup_row - row - end - - def build_header - @building_header = true - header = DslProxy.exec(self, Dummy.new, &table_block) - @building_header = false - header - end - class Dummy def method_missing(method, *arguments, &block) nil diff --git a/lib/ruby/reports/version.rb b/lib/ruby/reports/version.rb index 32df527..673beb4 100644 --- a/lib/ruby/reports/version.rb +++ b/lib/ruby/reports/version.rb @@ -1,7 +1,7 @@ # coding: utf-8 module Ruby module Reports - VERSION = '0.0.1' + VERSION = '0.0.2' end end diff --git a/ruby-reports.gemspec b/ruby-reports.gemspec index a8714bd..fe7c9b9 100644 --- a/ruby-reports.gemspec +++ b/ruby-reports.gemspec @@ -19,14 +19,13 @@ Gem::Specification.new do |spec| spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] - spec.add_runtime_dependency 'rake' spec.add_runtime_dependency 'iron-dsl' spec.add_runtime_dependency 'attr_extras' spec.add_runtime_dependency 'facets' + spec.add_development_dependency 'rake' spec.add_development_dependency 'pry' spec.add_development_dependency 'pry-debugger' - spec.add_development_dependency 'rake' spec.add_development_dependency 'rspec', '>= 2.14.0' spec.add_development_dependency 'simplecov' spec.add_development_dependency 'timecop', '~> 0.7.1'