reportinator 0.2.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -7
  3. data/Gemfile.lock +10 -0
  4. data/README.md +113 -22
  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 +8 -8
  10. data/lib/reportinator/base.rb +2 -1
  11. data/lib/reportinator/config.rb +10 -0
  12. data/lib/reportinator/function.rb +5 -5
  13. data/lib/reportinator/functions/array/flatten.rb +12 -0
  14. data/lib/reportinator/functions/array/helper.rb +7 -1
  15. data/lib/reportinator/functions/array/join.rb +1 -1
  16. data/lib/reportinator/functions/array/range.rb +11 -0
  17. data/lib/reportinator/functions/array/snippet.rb +30 -0
  18. data/lib/reportinator/functions/array/string.rb +10 -0
  19. data/lib/reportinator/functions/string/number.rb +26 -4
  20. data/lib/reportinator/functions/string/variable.rb +4 -2
  21. data/lib/reportinator/helpers.rb +29 -0
  22. data/lib/reportinator/parsers/method.rb +3 -0
  23. data/lib/reportinator/parsers/value.rb +12 -12
  24. data/lib/reportinator/report/column.rb +25 -0
  25. data/lib/reportinator/report/loader.rb +71 -0
  26. data/lib/reportinator/report/report.rb +33 -0
  27. data/lib/reportinator/report/row.rb +42 -0
  28. data/lib/reportinator/report/template.rb +108 -0
  29. data/lib/reportinator/{report.rb → report_type.rb} +4 -1
  30. data/lib/reportinator/types/model.rb +10 -5
  31. data/lib/reportinator/types/preset.rb +23 -2
  32. data/lib/reportinator/version.rb +1 -1
  33. data/lib/reportinator.rb +21 -11
  34. metadata +30 -5
  35. data/lib/reportinator/loader.rb +0 -120
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94a9663b55f56092c18cbb75fd7832823c7f80a20404575e168ffc7ef3c9bdb0
4
- data.tar.gz: 367ffe4a9b45bbe04b8e5992d8495d4988bf590d81daee9f8959bba4b88013f7
3
+ metadata.gz: 1640b58d6109a19bdbf48ce1065c18cee4e026a0eb4e4fc0b983664258d3794d
4
+ data.tar.gz: '097529bb768d21517db8d511fa9b7b17c029c8a513bbdd95ee52e8d8e2747450'
5
5
  SHA512:
6
- metadata.gz: 0d0a1cc0db797d02d212d33ec8fcbb50127d9d5801a92bddf0544505f4ffe903ebb4230e48114cf067c62e73e89ca5f64b91f90261ef41682244780c65c09975
7
- data.tar.gz: 64de0d19db4a9bd0553de2abd6bd5426a5b68d4efdf872c7ec7a9ab353b9223bc2f0df6737fe5174a79f3a06d6c85091de172d75a42e5004ffb95694e22a6f82
6
+ metadata.gz: a8fc97d8d0d8ad6a780d25cd07ee87ef52960b9175be94f8b9cc6f8714921b5a489cfedd77a3546ad73b8dd68e61d918ef515d221b744427490c6c949a980bbb
7
+ data.tar.gz: 8b94e32337cf10a45ac0a699e729e1361d649a0122bf4e09696cee054fc45c3318a58d72b4394816f62313ae4ecef2f2e3e70c54dff7dd9654de463430c13210
data/CHANGELOG.md CHANGED
@@ -1,4 +1,42 @@
1
- ## [Unreleased]
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.3.2] 2022-11-24
9
+ ### Fixed
10
+ - Reference to schema file
11
+
12
+ ## [0.3.1] 2022-11-24
13
+ ### Fixed
14
+ - Add "json_schemer" to gem dependencies
15
+
16
+ ## [0.3.0] 2022-11-24
17
+ ### Added
18
+ - Add template object
19
+ - Report types can opt in to parsing the data themselves
20
+ - Added "to_csv" method to report
21
+ - Added ">string" array function
22
+ - Added ">range" array function
23
+ - Added ">sum" array function
24
+ - Added "!nf" and "!ni" to convert a number to a float or integer
25
+ - Added "snippets"
26
+ - Added JSON Schema for report validation
27
+
28
+ ### Changed
29
+ - Preset report now takes in a "values" array, rather than a "data" array
30
+ - Refactor loader to be report loader
31
+ - "variables" have now been moved to be underneath the "metadata" tag.
32
+ - "metadata" is now passed to the Value parser instead of "variables"
33
+ - Re-ordered changelog to be latest change first
34
+ - Changelog now has KeepAChangelog info header
35
+
36
+ ### Fixed
37
+ - The Method function now works with non-string targets
38
+
39
+ ## [0.2.0] - 2022-10-14
2
40
  ### Added
3
41
  - Added parser for true, false and nil ("@true", "@false", "@nil")
4
42
  - Escape parsed methods and values starting with a special character
@@ -17,6 +55,11 @@
17
55
  - Method Parser no longer ignores empty and nil results.
18
56
  - Model report no longer double-parses values.
19
57
 
58
+ ## [0.1.1] - 2022-10-06
59
+ ### Fixed
60
+ - Move Base class to it's own file
61
+ - Now uses require_rel rather than require_all
62
+
20
63
  ## [0.1.0] - 2022-10-06
21
64
  - Initial release
22
65
 
@@ -25,9 +68,4 @@
25
68
  - Method parser
26
69
  - Preset report type
27
70
  - Model report type
28
- - Readme with report tutorial
29
-
30
- ## [0.1.1] - 2022-10-06
31
- ### Fixed
32
- - Move Base class to it's own file
33
- - Now uses require_rel rather than require_all
71
+ - Readme with report tutorial
data/Gemfile.lock CHANGED
@@ -18,9 +18,17 @@ GEM
18
18
  ast (2.4.2)
19
19
  concurrent-ruby (1.1.10)
20
20
  diff-lcs (1.5.0)
21
+ ecma-re-validator (0.4.0)
22
+ regexp_parser (~> 2.2)
23
+ hana (1.3.7)
21
24
  i18n (1.12.0)
22
25
  concurrent-ruby (~> 1.0)
23
26
  json (2.6.2)
27
+ json_schemer (0.2.23)
28
+ ecma-re-validator (~> 0.3)
29
+ hana (~> 1.3)
30
+ regexp_parser (~> 2.0)
31
+ uri_template (~> 0.7)
24
32
  minitest (5.16.3)
25
33
  parallel (1.22.1)
26
34
  parser (3.1.2.1)
@@ -65,11 +73,13 @@ GEM
65
73
  tzinfo (2.0.5)
66
74
  concurrent-ruby (~> 1.0)
67
75
  unicode-display_width (2.3.0)
76
+ uri_template (0.7.0)
68
77
 
69
78
  PLATFORMS
70
79
  x86_64-linux
71
80
 
72
81
  DEPENDENCIES
82
+ json_schemer (~> 0.2)
73
83
  rake (~> 13.0)
74
84
  reportinator!
75
85
  rspec (~> 3.0)
data/README.md CHANGED
@@ -50,19 +50,33 @@ A Report template has four attributes:
50
50
  | key | type | description |
51
51
  |-----------|--------|----------------------------------------------------|
52
52
  | type | symbol | specifies the report type to use |
53
- | variables | hash | defines variables to be used with the `$` function |
54
53
  | template | string | references another template to load and merge with |
54
+ | metadata | hash | values accessible to parser functions |
55
55
  | params | hash | report specific parameters |
56
56
 
57
- #### Reportinator String Function Cheatsheet
57
+ Values in report templates are passed through the value parser.
58
+ There are two main types of functions that can be parsed. String functions, and
59
+ array functions.
60
+
61
+ String functions return a value based on the contents of a string input.
62
+ They are useful for quick conversions, and simple functions.
63
+
64
+ Array functions return a value based on the contents of an array.
65
+ They are used for more complex functions, as more can be expressed with them.
66
+ The values in an array function are usually also parsed, although it is at the discretion
67
+ of the function do so.
68
+
69
+ #### String Function Cheatsheet
58
70
  | prefix | example | output |
59
71
  |---------|-----------------------------|--------------------------------------------|
60
72
  | `:` | ":symbol" | :symbol |
61
73
  | `&` | "&Constant" | Constant |
62
- | `$` | "$variable" | Value of key `variable` in variables hash. |
74
+ | `$` | "$variable" | Value `variable` in variables metadata. |
63
75
  | `!a` | "!a 1,2,3" | 6 |
64
76
  | `!d` | "!d 1970-01-01" | 1970-01-01 00:00:00 |
65
77
  | `!n` | "!n 100" | 100 |
78
+ | `!ni` | "!ni 103.34" | 103 |
79
+ | `!nf` | "!nf 103" | 103.0 |
66
80
  | `!j` | "!j 1,2,3" | "123" |
67
81
  | `!r` | "!r a,z" | ("a".."z") |
68
82
  | `!rd` | "!rd 1970-01-01,1979-01-01" | (1970-01-01 00:00:00..1979-01-01 00:00:00) |
@@ -72,9 +86,9 @@ A Report template has four attributes:
72
86
  | `@nil` | "@nil" | nil |
73
87
  | `@null` | "@null" | nil |
74
88
 
75
- #### Reportinator Array Function Cheatsheet
76
- When an array has a string as it's first value, and that string has a certain prefix
77
- the array is parsed as an Array Function.
89
+ #### Array Function Cheatsheet
90
+ When an array has a string as it's first value, and that string has a certain prefix,
91
+ the given array is parsed as an Array Function.
78
92
 
79
93
  Array functions have a target, then an array of values. Often, the values will work
80
94
  with the target to achieve an outcome.
@@ -95,7 +109,8 @@ are parsed, and sent as methods to it. The result is returned.
95
109
  This array is equivalent to running `Date.today.to_s`.
96
110
 
97
111
  Optionally, the prefix can be put on it's own, with no additional values
98
- after it.
112
+ after it. The second value, in this case "&Date", will become the target
113
+ instead.
99
114
  ```
100
115
  ["#", "&Date", ":today", ":to_s"]
101
116
  ```
@@ -106,13 +121,76 @@ to be more flexible, as it no longer has to be resolved from a string.
106
121
  ```
107
122
  This array is equally valid, and still returns the same result.
108
123
 
109
- prefix | example | ruby equivalent |
110
- -----------|------------------------------------------------|-----------------------------------------|
111
- `#` | `["#&Date", ":today"]` | Date.today |
112
- `>join` | `[">join", " - ", "a", "b", "c"]` | ["a", "b", "c"].join(" - ") |
113
- `>strf` | `[">strf", ["#&Date", ":today"], "%b, %Y"]` | Date.today.strftime("%b, %Y") |
114
- `>offset` | `[">offset $time", 2, ":month", ":end"]` | $time.advance(month: 2).at_end_of_month |
115
- `>title` | `[">title", "hello", "world"]` | ["hello", "world"].join(" ").titleize |
124
+ | prefix | example | ruby equivalent |
125
+ |-----------|------------------------------------------------|-----------------------------------------|
126
+ | `#` | `["#&Date", ":today"]` | Date.today |
127
+ | `>join` | `[">join", " - ", "a", "b", "c"]` | ["a", "b", "c"].join(" - ") |
128
+ | `>strf` | `[">strf", ["#&Date", ":today"], "%b, %Y"]` | Date.today.strftime("%b, %Y") |
129
+ | `>offset` | `[">offset $time", 2, ":month", ":end"]` | $time.advance(month: 2).at_end_of_month |
130
+ | `>title` | `[">title", "hello", "world"]` | ["hello", "world"].join(" ").titleize |
131
+ | `>snippet`| `[">snippet :test", {"var1": "hi"}]` | *See snippets section* |
132
+
133
+
134
+ ### Metadata
135
+ Metadata is defined in the "metadata" field of the template, and can be used by Parser Functions.
136
+ Metadata is merged from parent to child report template. Child metadata takes precedence over parent.
137
+
138
+ Reportinator's built in Parser Functions use two metadata fields; "variables", and "snippets".
139
+
140
+ #### Variables
141
+ Variables are values that can be accessed with the "$" string function.
142
+
143
+ ```
144
+ "metadata": {
145
+ "variables": {
146
+ "key": "value"
147
+ }
148
+ }
149
+ ```
150
+ ```
151
+ > Reportinator.parse "$key"
152
+ => "value"
153
+ ```
154
+
155
+ Variable values are also parsed, and themselves can even reference variables from parent templates.
156
+
157
+ ```
158
+ # $date = 1970-01-01
159
+ "metadata": {
160
+ "variables": {
161
+ "formatted_date": [">strf", "$date", "%b %d, %Y"]
162
+ }
163
+ }
164
+ ```
165
+ ```
166
+ > Reportinator.parse "$formatted_date"
167
+ => "Jan 01, 1970"
168
+ ```
169
+
170
+ #### Snippets
171
+ Snippets are values that are not parsed until called from the ">snippet" array function,
172
+ as opposed to variables, which are parsed before they are able to be called.
173
+
174
+ Snippets can be passed variables with a hash in the first value of the array function.
175
+
176
+ Example:
177
+ ```
178
+ "metadata": {
179
+ "snippets": {
180
+ "plus_10": [">sum", "$var", 10]
181
+ }
182
+ }
183
+ ```
184
+ ```
185
+ > Reportinator.parse [">snippet :plus_10", { "var": 5 }]
186
+ => 15
187
+ ```
188
+
189
+ Snippets help to reduce repetition of complex functionality in a report.
190
+ However, if a report is getting unwieldy with complex values to parse, it might
191
+ be a good idea to write a Custom Parser Function, or to write it into a method
192
+ on a class, and call it from a "&Constant". See the next section for setting up
193
+ custom functions.
116
194
 
117
195
  ### Configuring Reportinator
118
196
  ```
@@ -135,16 +213,27 @@ of the reports.
135
213
  ### Making a Custom Report Type
136
214
  The requirements to make a Report are very simple.
137
215
  1. The report must inherit from `Reportinator::Report`
138
- 2. The report must provide a `data` method, which returns a one or two dimensional array.
216
+ 2. The report should provide some attributes, to be set with the "params" field,
217
+ 3. The report must provide a `data` method, which returns either a Reportinator::Row,
218
+ or an array of them.
139
219
 
140
- For example, this is the entire code for the Preset Report:
220
+ Here's an example of a basic report type:
141
221
  ```
142
- module Reportinator
143
- class PresetReport < Report
144
- attribute :data, default: []
145
- end
222
+ class BasicReport < Reportinator::Report
223
+ attribute :values, default: []
224
+
225
+ def data
226
+ Reportinator::Row.create(values)
227
+ end
146
228
  end
147
229
  ```
230
+
231
+ `Reportinator::Row.create` takes in an array, and turns it into a Row.
232
+ For more fine-grained control, an instance of a Row can have data
233
+ inserted into it with the `insert` method. `insert` takes any data, then
234
+ a position, being either :first, :last, or an index number, to indicate where in
235
+ the row the data should be inserted.
236
+
148
237
  Once a report has been written, it must be registed as a report type.
149
238
  See the configuration section for more details.
150
239
 
@@ -155,11 +244,13 @@ or "Reportinator::ArrayFunction"
155
244
  2. The function must have a PREFIXES constant, with an array of the prefixes it'll accept.
156
245
  3. The function must provide an `output` method
157
246
 
158
- String functions gain access to two variables:
247
+ All functions have access to the `metadata` variable.
248
+
249
+ String functions gain access to two additional variables:
159
250
  - `prefix`, the prefix that the string used
160
251
  - `body`, the rest of the string with the prefix removed
161
252
 
162
- Array functions gain access to three variables:
253
+ Array functions gain access to three additional variables:
163
254
  - `prefix`, the prefix that was used
164
255
  - `target`, the first value after the prefix
165
256
  - `values`, the rest of the values, with the target removed
@@ -1,9 +1,13 @@
1
1
  [
2
2
  {
3
3
  "type": ":preset",
4
- "variables": {"variable": "i am a variable"},
4
+ "metadata": {
5
+ "variables": {
6
+ "variable": "i am a variable"
7
+ }
8
+ },
5
9
  "params": {
6
- "data": [
10
+ "values": [
7
11
  "string", ":symbol", "&Reportinator",
8
12
  "$variable", "!i 1234", "!a !i 2, 2",
9
13
  ["#!d 1970-01-01", {"strftime": "%b, %Y"}], "!r !i 1, !i 5"
@@ -13,7 +17,7 @@
13
17
  {
14
18
  "type": ":model",
15
19
  "params": {
16
- "target": ["#&Reportinator", ":config"],
20
+ "target": ["#", "&Reportinator", ":config"],
17
21
  "method_list": [":configured_directories", ":configured_suffixes", ":configured_types"]
18
22
  }
19
23
  }
@@ -2,7 +2,7 @@
2
2
  {
3
3
  "type": ":preset",
4
4
  "params": {
5
- "data": ["nx1","nx2","nx3","nx4","nx5"]
5
+ "values": ["nx1","nx2","nx3","nx4","nx5"]
6
6
  }
7
7
  },
8
8
  {
@@ -0,0 +1,15 @@
1
+ [
2
+ {
3
+ "type": ":preset",
4
+ "params": {
5
+ "values": ["5x5","nx1","nx2","nx3","nx4","nx5"]
6
+ }
7
+ },
8
+ {
9
+ "type": ":model",
10
+ "params": {
11
+ "target": "!rn 1,5",
12
+ "method_list": [[">join", "x", "$target", "n"],{"*": 1},{"*": 2},{"*": 3},{"*": 4},{"*": 5}]
13
+ }
14
+ }
15
+ ]
@@ -0,0 +1,76 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://moxvallix.com/meta/reportinator/report_schema.json",
4
+ "title": "Report",
5
+ "description": "A Reportinator Report",
6
+ "type": ["array", "object"],
7
+ "$defs": {
8
+ "template": {
9
+ "type": "object",
10
+ "properties": {
11
+ "type": {
12
+ "type": ["string", "array"]
13
+ },
14
+ "template": {
15
+ "type": ["string", "array"]
16
+ },
17
+ "metadata": {
18
+ "type": "object",
19
+ "properties": {
20
+ "snippets": {
21
+ "type": "object"
22
+ },
23
+ "variables": {
24
+ "type": "object"
25
+ }
26
+ }
27
+ },
28
+ "params": {
29
+ "type": "object"
30
+ }
31
+ },
32
+ "oneOf": [
33
+ {
34
+ "required": ["type"]
35
+ },
36
+ {
37
+ "required": ["template"]
38
+ }
39
+ ],
40
+ "allOf": [
41
+ {
42
+ "if": {
43
+ "properties": { "type": { "const": ":preset" } }
44
+ },
45
+ "then": {
46
+ "properties": { "params": { "properties": { "values": { "type": "array" } } } }
47
+ }
48
+ },
49
+ {
50
+ "if": {
51
+ "properties": { "type": { "const": ":model" } }
52
+ },
53
+ "then": {
54
+ "properties": {
55
+ "params": {
56
+ "properties": {
57
+ "target": { "type": ["string", "array"] },
58
+ "method_list": { "type": "array" }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+ ]
65
+ }
66
+ },
67
+ "if": {
68
+ "type": "object"
69
+ },
70
+ "then": {
71
+ "$ref": "#/$defs/template"
72
+ },
73
+ "else": {
74
+ "properties": { "items": { "$ref": "#/$defs/template" } }
75
+ }
76
+ }
@@ -31,7 +31,7 @@ Add "data" to a "params" object, and set it to be an empty array.
31
31
  {
32
32
  "type": ":preset",
33
33
  "params": {
34
- "data": []
34
+ "values": []
35
35
  }
36
36
  }
37
37
  ```
@@ -50,7 +50,7 @@ Let's now add some data to this bad boy.
50
50
  {
51
51
  "type": ":preset",
52
52
  "params": {
53
- "data": ["nx1","nx2","nx3","nx4","nx5"]
53
+ "values": ["nx1","nx2","nx3","nx4","nx5"]
54
54
  }
55
55
  }
56
56
  ```
@@ -59,13 +59,13 @@ Let's now add some data to this bad boy.
59
59
  => [["nx1", "nx2", "nx3", "nx4", "nx5"]]
60
60
  ```
61
61
 
62
- Now we could add the other rows ourselves, by adding more rows to "data":
62
+ Now we could add the other rows ourselves, by adding more rows to "values":
63
63
 
64
64
  ```
65
65
  {
66
66
  "type": ":preset",
67
67
  "params": {
68
- "data": [
68
+ "values": [
69
69
  ["nx1","nx2","nx3","nx4","nx5"],
70
70
  [1, 2, 3, 4, 5],
71
71
  [2, 4, 6, 8, 10],
@@ -98,7 +98,7 @@ This allows us to string reports together in the same template.
98
98
  {
99
99
  "type": ":preset",
100
100
  "params": {
101
- "data": ["nx1","nx2","nx3","nx4","nx5"]
101
+ "values": ["nx1","nx2","nx3","nx4","nx5"]
102
102
  }
103
103
  }
104
104
  ]
@@ -119,7 +119,7 @@ Set both to be an empty array.
119
119
  {
120
120
  "type": ":preset",
121
121
  "params": {
122
- "data": ["nx1","nx2","nx3","nx4","nx5"]
122
+ "values": ["nx1","nx2","nx3","nx4","nx5"]
123
123
  }
124
124
  },
125
125
  {
@@ -174,7 +174,7 @@ Using this, we can write a much smarter report.
174
174
  {
175
175
  "type": ":preset",
176
176
  "params": {
177
- "data": ["nx1","nx2","nx3","nx4","nx5"]
177
+ "values": ["nx1","nx2","nx3","nx4","nx5"]
178
178
  }
179
179
  },
180
180
  {
@@ -242,7 +242,7 @@ Let's add this now as the target of our report:
242
242
  {
243
243
  "type": ":preset",
244
244
  "params": {
245
- "data": ["nx1","nx2","nx3","nx4","nx5"]
245
+ "values": ["nx1","nx2","nx3","nx4","nx5"]
246
246
  }
247
247
  },
248
248
  {
@@ -2,9 +2,10 @@ module Reportinator
2
2
  class Base
3
3
  include ActiveModel::API
4
4
  include ActiveModel::Attributes
5
-
6
5
  require_rel "."
7
6
 
7
+ include Helpers
8
+
8
9
  def self.config
9
10
  Reportinator.config
10
11
  end
@@ -9,6 +9,10 @@ module Reportinator
9
9
  DEFAULT_FUNCTIONS = [
10
10
  "Reportinator::HelperArrayFunction",
11
11
  "Reportinator::JoinArrayFunction",
12
+ "Reportinator::RangeArrayFunction",
13
+ "Reportinator::StringArrayFunction",
14
+ "Reportinator::SnippetArrayFunction",
15
+ "Reportinator::FlattenArrayFunction",
12
16
  "Reportinator::MethodArrayFunction",
13
17
  "Reportinator::AdditionStringFunction",
14
18
  "Reportinator::ConstantStringFunction",
@@ -20,11 +24,13 @@ module Reportinator
20
24
  "Reportinator::SymbolStringFunction",
21
25
  "Reportinator::VariableStringFunction"
22
26
  ]
27
+ DEFAULT_UNPARSEDS = [:snippets]
23
28
 
24
29
  attribute :report_directories, default: []
25
30
  attribute :report_suffixes, default: []
26
31
  attribute :report_types, default: {}
27
32
  attribute :parser_functions, default: []
33
+ attribute :unparsed_metadata, default: []
28
34
  attribute :output_directory, default: "reports"
29
35
 
30
36
  def configured_directories
@@ -44,5 +50,9 @@ module Reportinator
44
50
  functions = DEFAULT_FUNCTIONS + parser_functions
45
51
  functions.map { |function| function.constantize }
46
52
  end
53
+
54
+ def configured_metadata
55
+ DEFAULT_UNPARSEDS + unparsed_metadata
56
+ end
47
57
  end
48
58
  end
@@ -1,18 +1,18 @@
1
1
  module Reportinator
2
2
  class Function < Base
3
3
  attribute :element
4
- attribute :variables, default: {}
4
+ attribute :metadata, default: {}
5
5
 
6
- def self.parse(element, variables = {})
7
- new(element: element, variables: variables).get
6
+ def self.parse(element, metadata = {})
7
+ new(element: element, metadata: metadata).get
8
8
  end
9
9
 
10
10
  def parse_value(value)
11
- ValueParser.parse(value, variables)
11
+ ValueParser.parse(value, metadata)
12
12
  end
13
13
 
14
14
  def parse_and_execute_value(target, value)
15
- ValueParser.parse_and_execute(target, value, variables)
15
+ ValueParser.parse_and_execute(target, value, metadata)
16
16
  end
17
17
 
18
18
  def prefixes
@@ -0,0 +1,12 @@
1
+ module Reportinator
2
+ class FlattenArrayFunction < ArrayFunction
3
+ PREFIXES = [">flatten"]
4
+
5
+ def output
6
+ array = []
7
+ array.append parse_value(target)
8
+ array.append parse_value(values)
9
+ array.flatten
10
+ end
11
+ end
12
+ end
@@ -1,6 +1,6 @@
1
1
  module Reportinator
2
2
  class HelperArrayFunction < ArrayFunction
3
- PREFIXES = [">strf", ">offset", ">title"]
3
+ PREFIXES = [">strf", ">offset", ">title", ">sum"]
4
4
 
5
5
  INTERVALS = {
6
6
  days: {start: "at_beginning_of_day", end: "at_end_of_day"},
@@ -15,6 +15,7 @@ module Reportinator
15
15
  return parse_strftime if prefix == ">strf"
16
16
  return parse_offset if prefix == ">offset"
17
17
  return parse_title if prefix == ">title"
18
+ return parse_sum if prefix == ">sum"
18
19
  element
19
20
  end
20
21
 
@@ -55,6 +56,11 @@ module Reportinator
55
56
  to_join.join(" ").titleize
56
57
  end
57
58
 
59
+ def parse_sum
60
+ sum_values = parsed_values.append parsed_target
61
+ sum_values.sum { |value| parse_value("!n #{value}") }
62
+ end
63
+
58
64
  def parsed_target
59
65
  @parsed_target ||= parse_target
60
66
  end
@@ -3,7 +3,7 @@ module Reportinator
3
3
  PREFIXES = [">join"]
4
4
 
5
5
  def output
6
- joiner = ValueParser.parse(target, variables)
6
+ joiner = parse_value(target)
7
7
  joiner = (joiner.instance_of?(String) ? joiner : target)
8
8
  values.map { |value| parse_value(value) }.join(joiner)
9
9
  end
@@ -0,0 +1,11 @@
1
+ module Reportinator
2
+ class RangeArrayFunction < ArrayFunction
3
+ PREFIXES = [">range"]
4
+
5
+ def output
6
+ start_value = parse_value(target)
7
+ end_value = parse_value(values[0])
8
+ (start_value..end_value)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ module Reportinator
2
+ class SnippetArrayFunction < ArrayFunction
3
+ PREFIXES = [">snippet"]
4
+
5
+ def output
6
+ name = target
7
+ name.strip! if name.instance_of? String
8
+ parsed_name = parse_value(name)
9
+ snippet = find_snippet(parsed_name)
10
+ return "Missing Snippet" unless snippet.present?
11
+ parse_snippet(snippet)
12
+ end
13
+
14
+ def find_snippet(name)
15
+ snippets = metadata[:snippets]
16
+ return false unless snippets.present?
17
+ return false unless snippets[name].present?
18
+ snippets[name]
19
+ end
20
+
21
+ def parse_snippet(snippet)
22
+ snippet_metadata = metadata.dup
23
+ snippet_metadata.delete :snippets
24
+ variables = values[0]
25
+ parsed_variables = parse_value(variables)
26
+ input_metadata = merge_hash(snippet_metadata, {variables: parsed_variables})
27
+ ValueParser.parse(snippet, input_metadata)
28
+ end
29
+ end
30
+ end