reportinator 0.1.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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