reportinator 0.1.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -7
  3. data/Gemfile.lock +11 -1
  4. data/README.md +201 -291
  5. data/app/reports/example.report.json +7 -3
  6. data/app/reports/multiplication.report.json +1 -1
  7. data/app/reports/multiplication_v2.report.json +15 -0
  8. data/data/schema/report_schema.json +76 -0
  9. data/docs/0_first_report.md +267 -0
  10. data/lib/reportinator/base.rb +2 -1
  11. data/lib/reportinator/config.rb +30 -0
  12. data/lib/reportinator/function.rb +33 -0
  13. data/lib/reportinator/functions/array/flatten.rb +12 -0
  14. data/lib/reportinator/functions/array/helper.rb +77 -0
  15. data/lib/reportinator/functions/array/join.rb +11 -0
  16. data/lib/reportinator/functions/array/method.rb +9 -0
  17. data/lib/reportinator/functions/array/range.rb +11 -0
  18. data/lib/reportinator/functions/array/snippet.rb +30 -0
  19. data/lib/reportinator/functions/array/string.rb +10 -0
  20. data/lib/reportinator/functions/array.rb +43 -0
  21. data/lib/reportinator/functions/string/addition.rb +11 -0
  22. data/lib/reportinator/functions/string/constant.rb +9 -0
  23. data/lib/reportinator/functions/string/date.rb +9 -0
  24. data/lib/reportinator/functions/string/join.rb +10 -0
  25. data/lib/reportinator/functions/string/logical.rb +14 -0
  26. data/lib/reportinator/functions/string/number.rb +33 -0
  27. data/lib/reportinator/functions/string/range.rb +14 -0
  28. data/lib/reportinator/functions/string/symbol.rb +9 -0
  29. data/lib/reportinator/functions/string/variable.rb +12 -0
  30. data/lib/reportinator/functions/string.rb +29 -0
  31. data/lib/reportinator/helpers.rb +29 -0
  32. data/lib/reportinator/parser.rb +25 -0
  33. data/lib/reportinator/parsers/method.rb +8 -3
  34. data/lib/reportinator/parsers/report.rb +47 -0
  35. data/lib/reportinator/parsers/value.rb +15 -112
  36. data/lib/reportinator/report/column.rb +25 -0
  37. data/lib/reportinator/report/loader.rb +71 -0
  38. data/lib/reportinator/report/report.rb +33 -0
  39. data/lib/reportinator/report/row.rb +42 -0
  40. data/lib/reportinator/report/template.rb +108 -0
  41. data/lib/reportinator/{report.rb → report_type.rb} +4 -1
  42. data/lib/reportinator/types/model.rb +15 -7
  43. data/lib/reportinator/types/preset.rb +23 -2
  44. data/lib/reportinator/version.rb +1 -1
  45. data/lib/reportinator.rb +23 -9
  46. metadata +48 -5
  47. data/lib/reportinator/loader.rb +0 -112
@@ -1,5 +1,8 @@
1
1
  module Reportinator
2
- class Report < Base
2
+ class ReportType < Base
3
+ PARSE_PARAMS = true
4
+
5
+ attr_accessor :metadata
3
6
  attribute :title
4
7
 
5
8
  def self.generate(params)
@@ -1,20 +1,21 @@
1
1
  module Reportinator
2
- class ModelReport < Report
2
+ class ModelReport < ReportType
3
+ include Helpers
4
+ PARSE_PARAMS = false
3
5
  attribute :target
4
6
  attribute :method_list, default: []
5
7
 
6
8
  validates :target, presence: true
7
9
 
8
10
  def data
9
- return get_model_data(target) unless target.methods.include? :first
10
- records_data
11
+ self.target = ValueParser.parse(target, metadata)
12
+ return Row.create(get_model_data(target)) unless target.respond_to? :each
13
+ records_data.map { |data| Row.create(data) }
11
14
  end
12
15
 
13
16
  def records_data
14
- records = target
15
- records = target.all if target.methods.include? :all
16
17
  output = []
17
- records.each do |model|
18
+ target.each do |model|
18
19
  value = get_model_data(model)
19
20
  output << value
20
21
  end
@@ -23,8 +24,15 @@ module Reportinator
23
24
 
24
25
  def get_model_data(target)
25
26
  method_list.map do |method|
26
- ValueParser.parse_and_execute(target, method)
27
+ parse_method(target, method)
27
28
  end
28
29
  end
30
+
31
+ def parse_method(target, method)
32
+ parser_metadata = merge_hash(metadata, {variables: {target: target}})
33
+ parsed_method = ValueParser.parse(method, parser_metadata)
34
+ return parsed_method if parsed_method.instance_of? String
35
+ MethodParser.parse(target, parsed_method)
36
+ end
29
37
  end
30
38
  end
@@ -1,5 +1,26 @@
1
1
  module Reportinator
2
- class PresetReport < Report
3
- attribute :data, default: []
2
+ class PresetReport < ReportType
3
+ attribute :values
4
+
5
+ def data
6
+ split_values.map { |row| Row.create(row) }
7
+ end
8
+
9
+ def split_values
10
+ data = values.instance_of?(Array) ? values : [values]
11
+ rows = []
12
+ temp = []
13
+ data.each do |col|
14
+ if col.instance_of?(Array)
15
+ rows << temp unless temp.empty?
16
+ temp = []
17
+ rows << col
18
+ else
19
+ temp << col
20
+ end
21
+ end
22
+ rows << temp unless temp.empty?
23
+ rows
24
+ end
4
25
  end
5
26
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Reportinator
4
- VERSION = "0.1.1"
4
+ VERSION = "0.3.2"
5
5
  end
data/lib/reportinator.rb CHANGED
@@ -6,14 +6,17 @@ require "fileutils"
6
6
  require "active_support"
7
7
  require "active_model"
8
8
  require "require_all"
9
+ require "json_schemer"
9
10
  require_relative "reportinator/version"
10
11
  require_relative "reportinator/base"
11
12
 
12
13
  module Reportinator
14
+ SCHEMA = "#{__dir__}/../data/schema/report_schema.json"
13
15
  class Error < StandardError; end
14
16
  class << self
15
17
  attr_writer :config
16
18
  attr_writer :logger
19
+ attr_writer :schema
17
20
  end
18
21
 
19
22
  def self.config
@@ -24,24 +27,35 @@ module Reportinator
24
27
  yield(config)
25
28
  end
26
29
 
30
+ def self.schema
31
+ return @schema if @schema.instance_of? JSONSchemer
32
+ schema = JSON.parse(File.read(SCHEMA))
33
+ @schema = JSONSchemer.schema(schema)
34
+ end
35
+
27
36
  def self.logger
28
37
  @logger || ActiveSupport::Logger.new($stdout)
29
38
  end
30
39
 
31
- def self.report(template, additional_params = {})
32
- Loader.data_from_template(template, additional_params)
40
+ def self.parse(input, metadata = {})
41
+ ValueParser.parse(input, metadata)
42
+ end
43
+
44
+ def self.report(template, metadata = {})
45
+ report = ReportLoader.load(template, metadata).report
46
+ report.output
33
47
  end
34
48
 
35
- def self.output(template, additional_params = {}, filename = "")
49
+ def self.output(template, metadata = {}, filename = "")
36
50
  filename = (filename.present? ? filename : "#{template}.csv")
37
51
  path = "#{config.output_directory}/#{filename}"
38
52
  FileUtils.mkdir_p(File.dirname(path))
39
- data = Loader.data_from_template(template, additional_params)
40
- CSV.open(path, "wb") do |csv|
41
- data.each do |row|
42
- csv << row
43
- end
53
+ report = ReportLoader.load(template, metadata).report
54
+ data = report.to_csv
55
+ if File.write(path, data)
56
+ path
57
+ else
58
+ raise "Error writing to: #{path}"
44
59
  end
45
- path
46
60
  end
47
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reportinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moxvallix
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-06 00:00:00.000000000 Z
11
+ date: 2022-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json_schemer
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.2'
41
55
  description: Behold! My Reportinator! Reportinator makes reports from JSON files.
42
56
  email:
43
57
  - dev@moxvallix.com
@@ -56,13 +70,42 @@ files:
56
70
  - Rakefile
57
71
  - app/reports/example.report.json
58
72
  - app/reports/multiplication.report.json
73
+ - app/reports/multiplication_v2.report.json
74
+ - data/schema/report_schema.json
75
+ - docs/0_first_report.md
59
76
  - lib/reportinator.rb
60
77
  - lib/reportinator/base.rb
61
78
  - lib/reportinator/config.rb
62
- - lib/reportinator/loader.rb
79
+ - lib/reportinator/function.rb
80
+ - lib/reportinator/functions/array.rb
81
+ - lib/reportinator/functions/array/flatten.rb
82
+ - lib/reportinator/functions/array/helper.rb
83
+ - lib/reportinator/functions/array/join.rb
84
+ - lib/reportinator/functions/array/method.rb
85
+ - lib/reportinator/functions/array/range.rb
86
+ - lib/reportinator/functions/array/snippet.rb
87
+ - lib/reportinator/functions/array/string.rb
88
+ - lib/reportinator/functions/string.rb
89
+ - lib/reportinator/functions/string/addition.rb
90
+ - lib/reportinator/functions/string/constant.rb
91
+ - lib/reportinator/functions/string/date.rb
92
+ - lib/reportinator/functions/string/join.rb
93
+ - lib/reportinator/functions/string/logical.rb
94
+ - lib/reportinator/functions/string/number.rb
95
+ - lib/reportinator/functions/string/range.rb
96
+ - lib/reportinator/functions/string/symbol.rb
97
+ - lib/reportinator/functions/string/variable.rb
98
+ - lib/reportinator/helpers.rb
99
+ - lib/reportinator/parser.rb
63
100
  - lib/reportinator/parsers/method.rb
101
+ - lib/reportinator/parsers/report.rb
64
102
  - lib/reportinator/parsers/value.rb
65
- - lib/reportinator/report.rb
103
+ - lib/reportinator/report/column.rb
104
+ - lib/reportinator/report/loader.rb
105
+ - lib/reportinator/report/report.rb
106
+ - lib/reportinator/report/row.rb
107
+ - lib/reportinator/report/template.rb
108
+ - lib/reportinator/report_type.rb
66
109
  - lib/reportinator/types/model.rb
67
110
  - lib/reportinator/types/preset.rb
68
111
  - lib/reportinator/version.rb
@@ -74,7 +117,7 @@ metadata:
74
117
  rubygems_mfa_required: 'true'
75
118
  homepage_uri: https://github.com/moxvallix/reportinator
76
119
  source_code_uri: https://github.com/moxvallix/reportinator
77
- changelog_uri: https://github.com/moxvallix/reportinator
120
+ changelog_uri: https://github.com/moxvallix/reportinator/blob/main/CHANGELOG.md
78
121
  post_install_message:
79
122
  rdoc_options: []
80
123
  require_paths:
@@ -1,112 +0,0 @@
1
- module Reportinator
2
- class Loader < Base
3
- attribute :type
4
- attribute :template
5
- attribute :variables
6
- attribute :params
7
-
8
- def self.data_from_template(template, additional_params = {})
9
- template_data = load_template(template, additional_params)
10
- return split_rows(template_data.data) unless template_data.instance_of?(Array)
11
- output = []
12
- template_data.each { |report| output += report.data }
13
- split_rows(output)
14
- end
15
-
16
- def self.load_template(template, additional_params = {})
17
- data = parse_template(template)
18
- return load_multiple(data, additional_params) if data.instance_of?(Array)
19
- load_singular(data, additional_params)
20
- end
21
-
22
- def self.load_multiple(data, additional_params)
23
- data.map { |report| load_singular(report, additional_params) }
24
- end
25
-
26
- def self.load_singular(data, additional_params)
27
- data.merge!(additional_params) { |key, old_value, new_value| merge_values(new_value, old_value) }
28
- filtered_data = filter_params(data, attribute_names)
29
- variables = filtered_data[:variables]
30
- parsed_data = ValueParser.parse(filtered_data, variables)
31
- new(parsed_data).report
32
- end
33
-
34
- def self.find_template(template)
35
- suffixes = config.configured_suffixes
36
- directories = config.configured_directories
37
- template_files = suffixes.map { |suffix| (suffix.present? ? "#{template}.#{suffix}" : template) }
38
- template_paths = directories.map { |dir| template_files.map { |file| "#{dir}/#{file}" } }
39
- template_paths.flatten!
40
- template_paths.each do |path|
41
- return path if File.exist? path
42
- end
43
- raise "Missing template: #{template}. Searched: #{template_paths}"
44
- end
45
-
46
- def self.parse_template(template)
47
- file = find_template(template)
48
- begin
49
- json = File.read(file)
50
- JSON.parse(json, symbolize_names: true)
51
- rescue
52
- raise "Error parsing template file: #{file}"
53
- end
54
- end
55
-
56
- def self.split_rows(data)
57
- data = data.instance_of?(Array) ? data : [data]
58
- rows = []
59
- temp = []
60
- data.each do |col|
61
- if col.instance_of?(Array)
62
- rows << temp unless temp.empty?
63
- temp = []
64
- rows << col
65
- else
66
- temp << col
67
- end
68
- end
69
- rows << temp unless temp.empty?
70
- rows
71
- end
72
-
73
- def self.filter_params(params, allowed_params)
74
- filtered_params = params.select { |param| allowed_params.include? param.to_s }
75
- if params.size > filtered_params.size
76
- invalid_params = (params.keys - filtered_params.keys).map { |key| key.to_s }
77
- logger.warn "Invalid attributes found: #{invalid_params} Valid attributes are: #{allowed_params}"
78
- end
79
- filtered_params
80
- end
81
-
82
- def self.merge_values(new_value, old_value)
83
- return old_value.merge(new_value) if old_value.is_a?(Hash) && new_value.is_a?(Hash)
84
- new_value
85
- end
86
-
87
- def report
88
- if template.present?
89
- additional_params = {type: type, variables: variables, params: params}
90
- self.class.load_template(template, additional_params.compact)
91
- else
92
- attribute_list = report_class.attribute_names
93
- filtered_params = self.class.filter_params(params, attribute_list)
94
- report_class.new(filtered_params)
95
- end
96
- end
97
-
98
- def report_class
99
- types = config.configured_types
100
- raise "Invalid type: #{type}" unless types.include? type
101
- types[type].constantize
102
- end
103
-
104
- def template_file
105
- self.class.find_template(template)
106
- end
107
-
108
- def template_data
109
- self.class.parse_template(template)
110
- end
111
- end
112
- end