reportinator 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb46422febcfaac711a20fbb21418ed224bc22e59468e9295dfccdd0c7ca309e
4
- data.tar.gz: afba11ce1ecc80668797392b5c24eeffc715d349b78f93fa7d6e7ea8dfdc096a
3
+ metadata.gz: 94a9663b55f56092c18cbb75fd7832823c7f80a20404575e168ffc7ef3c9bdb0
4
+ data.tar.gz: 367ffe4a9b45bbe04b8e5992d8495d4988bf590d81daee9f8959bba4b88013f7
5
5
  SHA512:
6
- metadata.gz: 8c604e8d6b30dff8df130dd6af08fcbc7a6ee0a4bb4a9e3c39478e97f2d3a2bb073c4543dcd2f366c4a39b5b15c97925d64bcba4060ed344c4c95de616507d91
7
- data.tar.gz: 678d1ed69042d72e8f0c146abcc0a55becb31a7961f034bb58d63a1f2999100443f13e91fd71129bcaab33616a1bc0361bbac7dd62ae5003c21159574c2c4ef0
6
+ metadata.gz: 0d0a1cc0db797d02d212d33ec8fcbb50127d9d5801a92bddf0544505f4ffe903ebb4230e48114cf067c62e73e89ca5f64b91f90261ef41682244780c65c09975
7
+ data.tar.gz: 64de0d19db4a9bd0553de2abd6bd5426a5b68d4efdf872c7ec7a9ab353b9223bc2f0df6737fe5174a79f3a06d6c85091de172d75a42e5004ffb95694e22a6f82
data/CHANGELOG.md CHANGED
@@ -1,6 +1,23 @@
1
1
  ## [Unreleased]
2
+ ### Added
3
+ - Added parser for true, false and nil ("@true", "@false", "@nil")
4
+ - Escape parsed methods and values starting with a special character
5
+ - Added Report parser
6
+ - Added "!j" join function.
7
+ - Added [">"] array helper functions.
8
+
9
+ ### Changed
10
+ - Load from template method now parses the report through the Report parser.
11
+ - Plain strings in the model report method list return as a string rather than nil
12
+ - Arrays starting with a string containing only a hash attempt to use the second value as target
13
+ - Improved Loader's row splitting.
14
+ - Refactored Value parser, allowing for custom functions
2
15
 
3
- ## [0.1.0] - 2022-10-04
16
+ ### Fixed
17
+ - Method Parser no longer ignores empty and nil results.
18
+ - Model report no longer double-parses values.
19
+
20
+ ## [0.1.0] - 2022-10-06
4
21
  - Initial release
5
22
 
6
23
  ### Added
@@ -8,4 +25,9 @@
8
25
  - Method parser
9
26
  - Preset report type
10
27
  - Model report type
11
- - Readme with report tutorial
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
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- reportinator (0.1.0)
4
+ reportinator (0.2.0)
5
5
  activemodel (~> 7.0)
6
6
  require_all (~> 3.0)
7
7
 
data/README.md CHANGED
@@ -18,312 +18,8 @@ If bundler is not being used to manage dependencies, install the gem by executin
18
18
  $ gem install reportinator
19
19
 
20
20
  ## Usage
21
- ### Creating my first Report
22
- Let's start by considering what we want our output to be.
23
- Say we want a multiplication table, like such:
24
- | nx1 | nx2 | nx3 | nx4 | nx5 |
25
- |-----|-----|-----|-----|-----|
26
- | 1 | 2 | 3 | 4 | 5 |
27
- | 2 | 4 | 6 | 8 | 10 |
28
- | 3 | 6 | 9 | 12 | 15 |
29
- | 4 | 8 | 12 | 16 | 20 |
30
- | 5 | 10 | 15 | 20 | 25 |
31
-
32
- Make a new file in your `app/reports` directory.
33
- Name it `multiplication.report.json`
34
-
35
- Set it's type to ":preset". The ":preset" type takes one parameter, "data",
36
- and returns any values passed inside it, but with their values parsed.
37
- We put a colon in front of the word "preset", such that the value parser
38
- knows to turn it into a symbol.
39
-
40
- ```
41
- {
42
- "type": ":preset"
43
- }
44
- ```
45
-
46
- Next we need to give it parameters to be passed into the report.
47
- ":preset" only accepts the "data" parameter.
48
- Add "data" to a "params" object, and set it to be an empty array.
49
-
50
- ```
51
- {
52
- "type": ":preset",
53
- "params": {
54
- "data": []
55
- }
56
- }
57
- ```
58
-
59
- You can now try running this report:
60
-
61
- ```
62
- > Reportinator.report("multiplication")
63
- => []
64
- ```
65
-
66
- If all went to plan, you should have gotten an empty array.
67
- Let's now add some data to this bad boy.
68
-
69
- ```
70
- {
71
- "type": ":preset",
72
- "params": {
73
- "data": ["nx1","nx2","nx3","nx4","nx5"]
74
- }
75
- }
76
- ```
77
- ```
78
- > Reportinator.report("multiplication")
79
- => [["nx1", "nx2", "nx3", "nx4", "nx5"]]
80
- ```
81
-
82
- Now we could add the other rows ourselves, by adding more rows to "data":
83
-
84
- ```
85
- {
86
- "type": ":preset",
87
- "params": {
88
- "data": [
89
- ["nx1","nx2","nx3","nx4","nx5"],
90
- [1, 2, 3, 4, 5],
91
- [2, 4, 6, 8, 10],
92
- [3, 6, 9, 12, 15],
93
- [4, 8, 12, 16, 20],
94
- [5, 10, 15, 20, 25]
95
- ]
96
- }
97
- }
98
- ```
99
- ```
100
- > Reportinator.report("multiplication")
101
- =>
102
- [
103
- ["nx1", "nx2", "nx3", "nx4", "nx5"],
104
- [1, 2, 3, 4, 5],
105
- [2, 4, 6, 8, 10],
106
- [3, 6, 9, 12, 15],
107
- [4, 8, 12, 16, 20],
108
- [5, 10, 15, 20, 25]
109
- ]
110
- ```
111
-
112
- However, there is a cleaner way of doing this.
113
- Move your entire report object inside of an array.
114
- This allows us to string reports together in the same template.
115
-
116
- ```
117
- [
118
- {
119
- "type": ":preset",
120
- "params": {
121
- "data": ["nx1","nx2","nx3","nx4","nx5"]
122
- }
123
- }
124
- ]
125
- ```
126
-
127
- Add a new report object underneath the first.
128
- This time, the type will be ":model".
129
-
130
- ":model" reports take two parameters:
131
- 1. "target"
132
- 2. "method_list"
133
-
134
- Add both these keys to the "params" of the second report object.
135
- Set both to be an empty array.
136
-
137
- ```
138
- [
139
- {
140
- "type": ":preset",
141
- "params": {
142
- "data": ["nx1","nx2","nx3","nx4","nx5"]
143
- }
144
- },
145
- {
146
- "type": ":model",
147
- "params": {
148
- "target": [],
149
- "method_list": []
150
- }
151
- }
152
- ]
153
- ```
154
-
155
- Model reports take a target, as specified in "target", and run methods against it,
156
- specified in "method_list", saving the outputs of each to the row.
157
-
158
- If the target is enumerable, said methods will run on each enumeration of the target,
159
- each enumeration adding a new row to the report.
160
-
161
- A method is specified by either a symbol, array or hash.
162
- Lets take the string "100" as our target.
163
-
164
- If our method was to be `":reverse"`, it would be the same as running"
165
-
166
- ```
167
- > "100".reverse
168
- => "001"
169
- ```
170
-
171
- We can chain methods using an array. For example: `[":reverse", ":to_i"]`
172
-
173
- ```
174
- > "100".reverse.to_i
175
- => 1
176
- ```
177
-
178
- Methods inside a hash allow for parameters to be passed to the method.
179
- The value of the hash are passed as the parameters, and an array is passed
180
- as multiple parameters.
181
-
182
- Eg. `{"gsub": ["0", "1"]}`
183
-
184
- ```
185
- > "100".gsub("0", "1")
186
- => "111"
187
- ```
188
-
189
- In Ruby, it turns out the multiplication "*" sign is a method.
190
- Using this, we can write a much smarter report.
191
-
192
- ```
193
- [
194
- {
195
- "type": ":preset",
196
- "params": {
197
- "data": ["nx1","nx2","nx3","nx4","nx5"]
198
- }
199
- },
200
- {
201
- "type": ":model",
202
- "params": {
203
- "target": [1, 2, 3, 4, 5],
204
- "method_list": [{"*": 1},{"*": 2},{"*": 3},{"*": 4},{"*": 5}]
205
- }
206
- }
207
- ]
208
- ```
209
-
210
- The "*" is behaving exactly the same way as our "gsub" example earlier.
211
-
212
- If we run our report again:
213
-
214
- ```
215
- > Reportinator.report("multiplication")
216
- =>
217
- [
218
- ["nx1", "nx2", "nx3", "nx4", "nx5"],
219
- [1, 2, 3, 4, 5],
220
- [2, 4, 6, 8, 10],
221
- [3, 6, 9, 12, 15],
222
- [4, 8, 12, 16, 20],
223
- [5, 10, 15, 20, 25]
224
- ]
225
- ```
226
-
227
- The result should be exactly the same.
228
-
229
- This is pretty good, but we can do better!
230
- Notice how the "target" was an array? As it is enumerable,
231
- we could run our methods against each element within it.
232
-
233
- But what if we wanted to have 10 rows? Or 50? Soon our array is going to get pretty long.
234
-
235
- This is where a range would be perfect. Set the start value to 1, the end to whatever number we need,
236
- and then we go from there.
237
-
238
- Unfortunately, we can't use a range in JSON.
239
-
240
- ... or can we?
241
-
242
- Reportinator has a bunch of handy built in functions, for converting strings.
243
- We have already seen ":symbol" to make a string into a symbol.
244
-
245
- We won't explore all the functions now, but we will explore "!r".
246
- Or more specifically, "!rn", which auto converts strings into numbers as well.
247
-
248
- We can make a range simply by writing "!rn 1,5". It takes the number before the comma,
249
- as the start of the range, and the one after as the end.
250
-
251
- We can test this with the actual parse method:
252
-
253
- ```
254
- > Reportinator::ValueParser.parse("!rn 1, 5")
255
- => (1..5)
256
- ```
257
-
258
- Let's add this now as the target of our report:
259
-
260
- ```
261
- [
262
- {
263
- "type": ":preset",
264
- "params": {
265
- "data": ["nx1","nx2","nx3","nx4","nx5"]
266
- }
267
- },
268
- {
269
- "type": ":model",
270
- "params": {
271
- "target": "!rn 1,5",
272
- "method_list": [{"*": 1},{"*": 2},{"*": 3},{"*": 4},{"*": 5}]
273
- }
274
- }
275
- ]
276
- ```
277
-
278
- Finally, rather than peering at the console to see if it worked,
279
- lets put it into a csv.
280
-
281
- ```
282
- > Reportinator.output("multiplication.csv","multiplication")
283
- => "multiplication.csv"
284
- ```
285
-
286
- Open the csv up in your spreadsheet viewer of choice, and revel
287
- in your brand new report!
288
- ### Reports in more detail
289
- #### The Report Template Object
290
- A Report template has four attributes:
291
-
292
- | key | type | description |
293
- |-----------|--------|----------------------------------------------------|
294
- | type | symbol | specifies the report type to use |
295
- | variables | hash | defines variables to be used with the `$` function |
296
- | template | string | references another template to load and merge with |
297
- | params | hash | report specific parameters |
298
-
299
- #### Reportinator String Parse Cheatsheet
300
- | prefix | example | output |
301
- |--------|-----------------------------|--------------------------------------------|
302
- | `:` | ":symbol" | :symbol |
303
- | `&` | "&Constant" | Constant |
304
- | `$` | "$variable" | Value of key `variable` in variables hash. |
305
- | `!a` | "!a 1,2,3" | 6 |
306
- | `!d` | "!d 1970-01-01" | 1970-01-01 00:00:00 |
307
- | `!n` | "!n 100" | 100 |
308
- | `!r` | "!r a,z" | ("a".."z") |
309
- | `!rd` | "!rd 1970-01-01,1979-01-01" | (1970-01-01 00:00:00..1979-01-01 00:00:00) |
310
- | `!rn` | "!rn 1,100" | (1..100) |
311
-
312
- #### Reportinator Method Parse Cheatsheet
313
- When an array has a string as it's first value, and that string has the `#` prefix,
314
- that string is parsed, and the result becomes the target of the following methods.
315
-
316
- Hashes within the array take the first key in the hash as the method,
317
- and the first value as parameters for that method. If the first value
318
- is an array, each item in the array is sent as a seperate parameter.
319
-
320
- Subsequent symbols in the array are sent as methods to the target.
321
- | method array | ruby equivalent |
322
- |------------------------------------------------|-------------------------------|
323
- | `["#&Date", ":today"]` | Date.today |
324
- | `["#&Date", ":today", ":to_s"]` | Date.today.to_s |
325
- | `["#&Date", ":today", {"strftime": "%b, %Y"}]` | Date.today.strftime("%b, %Y") |
326
- | `["#&Range", {"new": [1,100]}]` | Range.new(1, 100) |
21
+ For a detailed walkthrough of creating your first report, see
22
+ [Creating my First Report](docs/0_first_report.md)
327
23
 
328
24
  ### Where to put my Reports?
329
25
  By default, Reportinator checks `app/reports` for reports.
@@ -347,6 +43,77 @@ Here is how templates are resolved:
347
43
  Params is a hash, accepting the same keys as a template would.
348
44
  Params are merged with those provided by the template, overriding any conflicts.
349
45
 
46
+ ### Reports in more detail
47
+ #### The Report Template Object
48
+ A Report template has four attributes:
49
+
50
+ | key | type | description |
51
+ |-----------|--------|----------------------------------------------------|
52
+ | type | symbol | specifies the report type to use |
53
+ | variables | hash | defines variables to be used with the `$` function |
54
+ | template | string | references another template to load and merge with |
55
+ | params | hash | report specific parameters |
56
+
57
+ #### Reportinator String Function Cheatsheet
58
+ | prefix | example | output |
59
+ |---------|-----------------------------|--------------------------------------------|
60
+ | `:` | ":symbol" | :symbol |
61
+ | `&` | "&Constant" | Constant |
62
+ | `$` | "$variable" | Value of key `variable` in variables hash. |
63
+ | `!a` | "!a 1,2,3" | 6 |
64
+ | `!d` | "!d 1970-01-01" | 1970-01-01 00:00:00 |
65
+ | `!n` | "!n 100" | 100 |
66
+ | `!j` | "!j 1,2,3" | "123" |
67
+ | `!r` | "!r a,z" | ("a".."z") |
68
+ | `!rd` | "!rd 1970-01-01,1979-01-01" | (1970-01-01 00:00:00..1979-01-01 00:00:00) |
69
+ | `!rn` | "!rn 1,100" | (1..100) |
70
+ | `@true` | "@true" | true |
71
+ | `@false`| "@false" | false |
72
+ | `@nil` | "@nil" | nil |
73
+ | `@null` | "@null" | nil |
74
+
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.
78
+
79
+ Array functions have a target, then an array of values. Often, the values will work
80
+ with the target to achieve an outcome.
81
+
82
+ Take for example this array:
83
+ ```
84
+ ["#&Date", ":today", ":to_s"]
85
+ ```
86
+ This array has the following
87
+ - a prefix: `#`
88
+ - a target: `&Date` (Date)
89
+ - values: `[":today", ":to_s"]` ([:today, :to_s])
90
+
91
+ The `#` prefix tells the parser to run it as a Method Array.
92
+ The target, `&Date`, is parsed, then the values `[":today", ":to_s"]`
93
+ are parsed, and sent as methods to it. The result is returned.
94
+
95
+ This array is equivalent to running `Date.today.to_s`.
96
+
97
+ Optionally, the prefix can be put on it's own, with no additional values
98
+ after it.
99
+ ```
100
+ ["#", "&Date", ":today", ":to_s"]
101
+ ```
102
+ This will still return the same result. Note that this allows the target
103
+ to be more flexible, as it no longer has to be resolved from a string.
104
+ ```
105
+ ["#", ["#&Date", ":today"], ":to_s"]
106
+ ```
107
+ This array is equally valid, and still returns the same result.
108
+
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 |
116
+
350
117
  ### Configuring Reportinator
351
118
  ```
352
119
  Reportinator.configuration do |config|
@@ -356,6 +123,9 @@ Reportinator.configuration do |config|
356
123
  config.report_types = {
357
124
  my_type: "MyModule::MyReportType"
358
125
  }
126
+ config.parser_functions = [
127
+ "MyModule::MyParserFunction"
128
+ ]
359
129
  end
360
130
  ```
361
131
  Configuration set will not override the default configuration.
@@ -378,6 +148,55 @@ end
378
148
  Once a report has been written, it must be registed as a report type.
379
149
  See the configuration section for more details.
380
150
 
151
+ ### Making a Custom Parser Function
152
+ The requirements to make a Parser Function are fairly simple:
153
+ 1. The function must inherit from either "Reportinator::StringFunction"
154
+ or "Reportinator::ArrayFunction"
155
+ 2. The function must have a PREFIXES constant, with an array of the prefixes it'll accept.
156
+ 3. The function must provide an `output` method
157
+
158
+ String functions gain access to two variables:
159
+ - `prefix`, the prefix that the string used
160
+ - `body`, the rest of the string with the prefix removed
161
+
162
+ Array functions gain access to three variables:
163
+ - `prefix`, the prefix that was used
164
+ - `target`, the first value after the prefix
165
+ - `values`, the rest of the values, with the target removed
166
+
167
+ Once a function has been written, it must be registed as a parser function.
168
+ See the configuration section for more details.
169
+
170
+ #### Example String Function:
171
+ ```
172
+ class TitleizeStringFunction < Reportinator::StringFunction
173
+ PREFIXES = ["!t"]
174
+
175
+ def output
176
+ body.titleize
177
+ end
178
+ end
179
+ ```
180
+ ```
181
+ > Reportinator.parse "!t hello world"
182
+ => "Hello World"
183
+ ```
184
+
185
+ #### Example Array Function:
186
+ ```
187
+ class TargetSumArrayFunction < Reportinator::ArrayFunction
188
+ PREFIXES = [">targetsum"]
189
+
190
+ def output
191
+ values.map { |value| value + target }
192
+ end
193
+ end
194
+ ```
195
+ ```
196
+ > Reportinator.parse [">targetsum", 10, 1, 2, 3]
197
+ => [11, 12, 13]
198
+ ```
199
+
381
200
  ## Development
382
201
 
383
202
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -386,7 +205,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
386
205
 
387
206
  ## Contributing
388
207
 
389
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/reportinator. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/reportinator/blob/master/CODE_OF_CONDUCT.md).
208
+ Bug reports and pull requests are welcome on GitHub at https://github.com/moxvallix/reportinator. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/moxvallix/reportinator/blob/master/CODE_OF_CONDUCT.md).
390
209
 
391
210
  ## License
392
211
 
@@ -394,4 +213,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
394
213
 
395
214
  ## Code of Conduct
396
215
 
397
- Everyone interacting in the Reportinator project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/reportinator/blob/master/CODE_OF_CONDUCT.md).
216
+ Everyone interacting in the Reportinator project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/moxvallix/reportinator/blob/master/CODE_OF_CONDUCT.md).