easy_app_helper 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,499 +1,499 @@
1
- # EasyAppHelper
2
-
3
- **This [gem][EAP] aims at providing useful helpers for command line applications.**
4
-
5
- This is a complete rewrite of the initial easy_app_helper gem. **It is not compatible with
6
- apps designed for easy_app_helper prior to version 1.0.0**, although they could be very easily adapted
7
- (anyway you always specify your gem dependencies using the [pessimistic version operator]
8
- (http://docs.rubygems.org/read/chapter/16#page74), don't you ?). Older applications should explicitly
9
- require to use the latest version of the 0.x.x series instead. The config files themselves remain
10
- compatible with all versions of **EasyAppHelper**, as they are actually just plain Yaml files...
11
-
12
- The new **EasyAppHelper** module provides:
13
-
14
- * A **super charged Config class** that:
15
- * Manages **multiple sources of configuration**(command line, multiple config files...) in a **layered config**.
16
- * Provides an **easy to customize merge mechanism** for the different **config layers** that renders a "live view"
17
- of the merged configuration, while keeping a way to access or modify independently any of them.
18
- * Allows **flexibility** when dealing with modification and provides a way to roll back modifications done to config
19
- anytime, fully reload it, blast it... Export feature could be very easily added and will probably.
20
- * A **Logger tightly coupled with the Config** class, that will behave regarding options specified be it from
21
- command line or from any source(layer) of the config object...
22
- * Embeds [Slop][slop] to handle **command line parameters** and keeps all parameters specified from the command
23
- line in a **dedicated layer of the config object**.
24
- * A mechanism that ensures that as soon as you access any of the objects or methods exposed by EasyAppHelper,
25
- all of them are **fully configured and ready to be used**.
26
-
27
- If you are writing command line applications, I hope you will like it because it's very easy to use,
28
- and as unobtrusive as possible (you choose when you want to include or use as a module) while providing
29
- a ready-for-prod config, logger and command line management.
30
-
31
-
32
- Currently the only runtime dependency is the cool [Slop gem][slop] which is used to process the command line options.
33
-
34
- [Why this gem][4] ?
35
-
36
-
37
-
38
- ## Installation
39
-
40
- Add this line to your application's Gemfile:
41
-
42
- gem 'easy_app_helper'
43
-
44
- And then execute:
45
-
46
- $ bundle
47
-
48
- Or install it yourself as:
49
-
50
- $ gem install easy_app_helper
51
-
52
-
53
-
54
-
55
- ## Usage
56
-
57
- To use it, once you installed them, you just need to require it:
58
-
59
- ```ruby
60
- require 'easy_app_helper'
61
- ```
62
-
63
- Then can can immediately access the logger or the config objects. Here under a first example:
64
-
65
- ```ruby
66
- require 'easy_app_helper'
67
-
68
- # You can directly access the config or the logger through the **EasyAppHelper** module
69
- puts "The application verbose flag is #{EasyAppHelper.config[:verbose]}"
70
-
71
- # You can directly use the logger according to the command line flags
72
- # This will do nothing unless --debug is set and --log-level is set to the correct level
73
- EasyAppHelper.logger.info "Hi guys!"
74
-
75
- # Fed up with the **EasyAppHelper** prefix ? Just include the module where you want
76
- include EasyAppHelper
77
-
78
- # You can override programmatically any part of the config
79
- config[:debug] = true
80
- logger.level = 1
81
- config[:test] = 'Groovy'
82
- EasyAppHelper.logger.info "Hi guys!... again"
83
-
84
- # You can see the internals of the config
85
- puts config.internal_configs.to_yaml
86
- # Which will output
87
- #:modified:
88
- # :content:
89
- # :log-level: 1
90
- # :debug: true
91
- # :test: cool
92
- # :source: Changed by code
93
- #:command_line:
94
- # :content:
95
- # :auto:
96
- # :simulate:
97
- # :verbose: true
98
- # :help:
99
- # :config-file:
100
- # :config-override:
101
- # :debug:
102
- # :debug-on-err:
103
- # :log-level:
104
- # :log-file:
105
- # :source: Command line
106
- #:system:
107
- # :content: {}
108
- # :source:
109
- # :origin: EasyAppHelper
110
- #:global:
111
- # :content: {}
112
- # :source:
113
- # :origin: ''
114
- #:user:
115
- # :content: {}
116
- # :source:
117
- # :origin: ''
118
- #:specific_file:
119
- # :content: {}
120
-
121
- # You see of course that the two modifications we did are in the modified sub-hash
122
- # And now the merged config
123
- puts config.to_hash
124
-
125
- # But you can see the modified part as it is:
126
- puts config.internal_configs[:modified]
127
-
128
- # Of course you can access it from any class
129
- class Dummy
130
- include EasyAppHelper
131
-
132
- def initialize
133
- puts "#{config[:test]} baby !"
134
- # Back to the original
135
- config.reset
136
- puts config.internal_configs[:modified]
137
- end
138
- end
139
-
140
- Dummy.new
141
-
142
- # Some methods are provided to ease common tasks. For example this one will log at info level
143
- # (so only displayed if debug mode and log level low enough), but will also puts on the console
144
- # if verbose if set...
145
- puts_and_logs "Hi world"
146
-
147
- # It is actually one of the few methods added to regular Logger class (The added value of this logger
148
- # is much more to be tightly coupled with the config object). Thus could access it like that:
149
- logger.puts_and_logs "Hi world"
150
-
151
- # or even
152
- EasyAppHelper.logger.puts_and_logs "Hi world... 3 is enough."
153
- ```
154
-
155
-
156
- ## Configuration layers
157
-
158
- **EasyAppHelper** will look for files in numerous places. **Both Unix and Windows places are handled**.
159
- All the files are [Yaml][yaml] files but could have names with different extensions.
160
-
161
- You can look in the [classes documentation][doc] to know exactly which extensions and places the config
162
- files are looked for.
163
-
164
- ### System config file
165
-
166
- This config file is common to all applications that use EasyAppHelper. For example on a Unix system
167
- regarding the rules described above, the framework will for the following files in that order:
168
-
169
- ```text
170
- # It will be loaded in the :system layer
171
- /etc/EasyAppHelper.conf
172
- /etc/EasyAppHelper.yml
173
- /etc/EasyAppHelper.cfg
174
- /etc/EasyAppHelper.yaml
175
- /etc/EasyAppHelper.CFG
176
- /etc/EasyAppHelper.YML
177
- /etc/EasyAppHelper.YAML
178
- /etc/EasyAppHelper.Yaml
179
- ```
180
-
181
- ### Application config files
182
-
183
- Application config file names are determined from the config.script_filename property. It initially contains
184
- the bare name of the script(path and extension removed), but you can replace with whatever you want. Changing
185
- this property causes actually the impacted files to be reloaded.
186
-
187
- It is in fact a two level configuration. One is global (the :global layer) and the other is at user level (the
188
- :user layer).
189
-
190
- For example on a Unix system or cygwin
191
-
192
- ```text
193
- # For the :global layer
194
- /etc/myscript.conf
195
- /etc/myscript.yml
196
- /etc/myscript.cfg
197
- /etc/myscript.yaml
198
- /etc/myscript.CFG
199
- /etc/myscript.YML
200
- /etc/myscript.YAML
201
- /etc/myscript.Yaml
202
- /usr/local/etc/myscript.conf
203
- /usr/local/etc/myscript.yml
204
- /usr/local/etc/myscript.cfg
205
- /usr/local/etc/myscript.yaml
206
- /usr/local/etc/myscript.CFG
207
- /usr/local/etc/myscript.YML
208
- /usr/local/etc/myscript.YAML
209
- /usr/local/etc/myscript.Yaml
210
- # For the :user level
211
- ${HOME}/.config/myscript.conf
212
- ${HOME}/.config/myscript.yml
213
- ${HOME}/.config/myscript.cfg
214
- ${HOME}/.config/myscript.yaml
215
- ${HOME}/.config/myscript.CFG
216
- ${HOME}/.config/myscript.YML
217
- ${HOME}/.config/myscript.YAML
218
- ${HOME}/.config/myscript.Yaml
219
- ```
220
-
221
- ### Command line specified config file
222
-
223
- The command line option ```--config-file``` provides a way to specify explicitly a config file. On top of this the
224
- option ```--config-override``` tells **EasyAppHelper** to ignore :system, :global and :user levels.
225
-
226
- The file will be loaded in a separated layer called :specific_file
227
-
228
-
229
- ### The command line options
230
-
231
- **EasyAppHelper** already provides by default some command line options. Imagine you have the following program.
232
-
233
- ```ruby
234
- #!/usr/bin/env ruby
235
-
236
- require 'easy_app_helper'
237
-
238
- class MyApp
239
- include EasyAppHelper
240
-
241
- APP_NAME = "My super application"
242
- VERSION = '0.0.1'
243
- DESCRIPTION = 'This application is a proof of concept for EasyAppHelper.'
244
-
245
-
246
- def initialize
247
- # Providing this data is optional but brings better logging and online help
248
- config.describes_application(app_name: APP_NAME, app_version: VERSION, app_description: DESCRIPTION)
249
- end
250
-
251
-
252
- def run
253
- if config[:help]
254
- puts config.help
255
- exit 0
256
- end
257
- puts_and_logs "Application is starting"
258
- do_some_processing
259
- end
260
-
261
- def do_some_processing
262
- puts_and_logs "Starting some heavy processing"
263
- end
264
-
265
- end
266
-
267
-
268
- MyApp.new.run
269
- ```
270
-
271
- And you run it without any command line option
272
-
273
- ```text
274
- ./test4_app.rb
275
- ```
276
-
277
- No output...
278
-
279
- Let' try
280
-
281
- ```text
282
- ./test4_app.rb --help
283
-
284
- Usage: test4_app [options]
285
- My super application Version: 0.0.1
286
-
287
- This application is a proof of concept for EasyAppHelper.
288
- -- Generic options -------------------------------------------------------------
289
- --auto Auto mode. Bypasses questions to user.
290
- --simulate Do not perform the actual underlying actions.
291
- -v, --verbose Enable verbose mode.
292
- -h, --help Displays this help.
293
- -- Configuration options -------------------------------------------------------
294
- --config-file Specify a config file.
295
- --config-override If specified override all other config.
296
- -- Debug and logging options ---------------------------------------------------
297
- --debug Run in debug mode.
298
- --debug-on-err Run in debug mode with output to stderr.
299
- --log-level Log level from 0 to 5, default 2.
300
- --log-file File to log to.
301
-
302
- ```
303
- You see there the online help. And then the program exists.
304
-
305
- Let's try the ```--verbose``` flag
306
-
307
- ```text
308
- ./test4_app.rb --verbose
309
- Application is starting
310
- Starting some heavy processing
311
- ```
312
-
313
- You see that the puts_and_logs is sensitive to the ```--verbose``` switch...
314
-
315
- But what if I debug
316
- ```text
317
- ./test4_app.rb --debug
318
- ```
319
-
320
- Humm... nothing... Let's provide the log level
321
-
322
- ```text
323
- ./test4_app.rb --debug --log-level 0
324
- I, [2013-06-23T19:37:24.975392 #10276] INFO -- My super application: Application is starting
325
- I, [2013-06-23T19:37:24.975592 #10276] INFO -- My super application: Starting some heavy processing
326
- ```
327
-
328
- You see there that the puts_and_logs logs as well with the log level 1 (Info)... Nice looks like it was claiming
329
- this in its name... ;-)
330
-
331
- If I mix ?
332
-
333
- ```text
334
- ./test4_app.rb --debug --log-level 0 --verbose
335
- Application is starting
336
- I, [2013-06-23T19:39:05.712558 #11768] INFO -- My super application: Application is starting
337
- Starting some heavy processing
338
- I, [2013-06-23T19:39:05.712834 #11768] INFO -- My super application: Starting some heavy processing
339
- ```
340
-
341
- So far so good...
342
-
343
- ### Specifying command line parameters
344
-
345
- As said, internally **EasyAppHelper** uses the [Slop gem][slop] to handle the command line parameters.
346
- You can configure the internal Slop object by calling the add_command_line_section method of the config
347
- object. You could create a method that setup your application command line parameters like this:
348
-
349
- ```ruby
350
- def add_cmd_line_options
351
- config.add_command_line_section do |slop|
352
- slop.on :u, :useless, 'Stupid option', :argument => false
353
- slop.on :anint, 'Stupid option with integer argument', :argument => true, :as => Integer
354
- end
355
- end
356
-
357
- ```
358
-
359
- See [Slop gem][slop] API documentation for more options.
360
-
361
-
362
- ### Debugging the framework itself
363
-
364
- If you want, you can even debug what happens during **EasyAppHelper** initialisation, for this you can use the
365
- ```DEBUG_EASY_MODULES``` environment variable. As how and where everything has to be logged is only specified when
366
- you actually provide command line options, **EasyAppHelper** provides a temporary logger to itself and will
367
- after all dump the logger content to the logger you specified and if you specify... So that you don't miss a log.
368
-
369
- ```text
370
- $ DEBUG_EASY_MODULES=y ruby ./test4_app.rb
371
-
372
- D, [2013-06-23T19:43:47.977031 #16294] DEBUG -- : Temporary initialisation logger created...
373
- D, [2013-06-23T19:43:47.977861 #16294] DEBUG -- : Trying "/etc/EasyAppHelper.conf" as config file.
374
- D, [2013-06-23T19:43:47.977908 #16294] DEBUG -- : Trying "/etc/EasyAppHelper.yml" as config file.
375
- D, [2013-06-23T19:43:47.977938 #16294] DEBUG -- : Loading config file "/etc/EasyAppHelper.cfg"
376
- D, [2013-06-23T19:43:47.978300 #16294] DEBUG -- : Trying "/etc/test4_app.conf" as config file.
377
- D, [2013-06-23T19:43:47.978332 #16294] DEBUG -- : Trying "/etc/test4_app.yml" as config file.
378
- D, [2013-06-23T19:43:47.978355 #16294] DEBUG -- : Trying "/etc/test4_app.cfg" as config file.
379
- D, [2013-06-23T19:43:47.978381 #16294] DEBUG -- : Trying "/etc/test4_app.yaml" as config file.
380
- D, [2013-06-23T19:43:47.978403 #16294] DEBUG -- : Trying "/etc/test4_app.CFG" as config file.
381
- D, [2013-06-23T19:43:47.978424 #16294] DEBUG -- : Trying "/etc/test4_app.YML" as config file.
382
- D, [2013-06-23T19:43:47.978445 #16294] DEBUG -- : Trying "/etc/test4_app.YAML" as config file.
383
- D, [2013-06-23T19:43:47.978466 #16294] DEBUG -- : Trying "/etc/test4_app.Yaml" as config file.
384
- D, [2013-06-23T19:43:47.978491 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.conf" as config file.
385
- D, [2013-06-23T19:43:47.978529 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.yml" as config file.
386
- D, [2013-06-23T19:43:47.978553 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.cfg" as config file.
387
- D, [2013-06-23T19:43:47.978575 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.yaml" as config file.
388
- D, [2013-06-23T19:43:47.978597 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.CFG" as config file.
389
- D, [2013-06-23T19:43:47.978619 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.YML" as config file.
390
- D, [2013-06-23T19:43:47.978670 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.Yaml" as config file.
391
- I, [2013-06-23T19:43:47.978695 #16294] INFO -- : No config file found for layer global.
392
- D, [2013-06-23T19:43:47.978725 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.conf" as config file.
393
- D, [2013-06-23T19:43:47.978748 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.yml" as config file.
394
- D, [2013-06-23T19:43:47.978770 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.cfg" as config file.
395
- D, [2013-06-23T19:43:47.978792 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.yaml" as config file.
396
- D, [2013-06-23T19:43:47.978817 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.CFG" as config file.
397
- D, [2013-06-23T19:43:47.978840 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.YML" as config file.
398
- D, [2013-06-23T19:43:47.978861 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.YAML" as config file.
399
- D, [2013-06-23T19:43:47.978974 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.Yaml" as config file.
400
- I, [2013-06-23T19:43:47.979000 #16294] INFO -- : No config file found for layer user.
401
- I, [2013-06-23T19:43:47.979025 #16294] INFO -- : No config file found for layer specific_file.
402
- D, [2013-06-23T19:43:47.979514 #16294] DEBUG -- : Trying "/etc/EasyAppHelper.conf" as config file.
403
- D, [2013-06-23T19:43:47.979561 #16294] DEBUG -- : Trying "/etc/EasyAppHelper.yml" as config file.
404
- D, [2013-06-23T19:43:47.979591 #16294] DEBUG -- : Loading config file "/etc/EasyAppHelper.cfg"
405
- D, [2013-06-23T19:43:47.979717 #16294] DEBUG -- : Trying "/etc/test4_app.conf" as config file.
406
- D, [2013-06-23T19:43:47.979747 #16294] DEBUG -- : Trying "/etc/test4_app.yml" as config file.
407
- D, [2013-06-23T19:43:47.979800 #16294] DEBUG -- : Trying "/etc/test4_app.cfg" as config file.
408
- D, [2013-06-23T19:43:47.979823 #16294] DEBUG -- : Trying "/etc/test4_app.yaml" as config file.
409
- D, [2013-06-23T19:43:47.979845 #16294] DEBUG -- : Trying "/etc/test4_app.CFG" as config file.
410
- D, [2013-06-23T19:43:47.979867 #16294] DEBUG -- : Trying "/etc/test4_app.YML" as config file.
411
- D, [2013-06-23T19:43:47.979908 #16294] DEBUG -- : Trying "/etc/test4_app.YAML" as config file.
412
- D, [2013-06-23T19:43:47.979935 #16294] DEBUG -- : Trying "/etc/test4_app.Yaml" as config file.
413
- D, [2013-06-23T19:43:47.979959 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.conf" as config file.
414
- D, [2013-06-23T19:43:47.979981 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.yml" as config file.
415
- D, [2013-06-23T19:43:47.980004 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.cfg" as config file.
416
- D, [2013-06-23T19:43:47.980026 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.yaml" as config file.
417
- D, [2013-06-23T19:43:47.980047 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.CFG" as config file.
418
- D, [2013-06-23T19:43:47.980069 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.YML" as config file.
419
- D, [2013-06-23T19:43:47.980091 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.YAML" as config file.
420
- D, [2013-06-23T19:43:47.980112 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.Yaml" as config file.
421
- I, [2013-06-23T19:43:47.980135 #16294] INFO -- : No config file found for layer global.
422
- D, [2013-06-23T19:43:47.980181 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.conf" as config file.
423
- D, [2013-06-23T19:43:47.980207 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.yml" as config file.
424
- D, [2013-06-23T19:43:47.980230 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.cfg" as config file.
425
- D, [2013-06-23T19:43:47.980252 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.yaml" as config file.
426
- D, [2013-06-23T19:43:47.980274 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.CFG" as config file.
427
- D, [2013-06-23T19:43:47.980296 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.YML" as config file.
428
- D, [2013-06-23T19:43:47.980319 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.YAML" as config file.
429
- D, [2013-06-23T19:43:47.980361 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.Yaml" as config file.
430
- I, [2013-06-23T19:43:47.980395 #16294] INFO -- : No config file found for layer user.
431
- I, [2013-06-23T19:43:47.980418 #16294] INFO -- : No config file found for layer specific_file.
432
- D, [2013-06-23T19:43:47.981934 #16294] DEBUG -- : Config layers:
433
- ---
434
- :modified:
435
- :content: {}
436
- :source: Changed by code
437
- :command_line:
438
- :content:
439
- :auto:
440
- :simulate:
441
- :verbose: true
442
- :help:
443
- :config-file:
444
- :config-override:
445
- :debug: true
446
- :debug-on-err:
447
- :log-level: 0
448
- :log-file:
449
- :source: Command line
450
- :system:
451
- :content:
452
- :copyright: (c) 2012-2013 Nanonet
453
- :source: /etc/EasyAppHelper.cfg
454
- :origin: EasyAppHelper
455
- :global:
456
- :content: {}
457
- :source:
458
- :origin: test4_app
459
- :user:
460
- :content: {}
461
- :source:
462
- :origin: test4_app
463
- :specific_file:
464
- :content: {}
465
-
466
- D, [2013-06-23T19:43:47.985357 #16294] DEBUG -- : Merged config:
467
- ---
468
- :copyright: (c) 2012-2013 Nanonet
469
- :verbose: true
470
- :debug: true
471
- :log-level: 0
472
-
473
- Application is starting
474
- I, [2013-06-23T19:43:47.986298 #16294] INFO -- My super application: Application is starting
475
- Starting some heavy processing
476
- I, [2013-06-23T19:43:47.986460 #16294] INFO -- My super application: Starting some heavy processing
477
- ```
478
-
479
- You can notice that what **EasyAppHelper** initialisation logged and what you application logged
480
- did eventually end-up in the same log...
481
-
482
-
483
- ## Contributing
484
-
485
- 1. Fork it
486
- 2. Create your feature branch (`git checkout -b my-new-feature`)
487
- 3. Commit your changes (`git commit -am 'Add some feature'`)
488
- 4. Push to the branch (`git push origin my-new-feature`)
489
- 5. Create new Pull Request
490
-
491
-
492
- That's all folks.
493
-
494
-
495
- [EAP]: https://rubygems.org/gems/easy_app_helper "**EasyAppHelper** gem"
496
- [slop]: https://rubygems.org/gems/slop "Slop gem"
497
- [yaml]: http://www.yaml.org/ "The Yaml official site"
498
- [doc]: http://rubydoc.info/github/lbriais/easy_app_helper/master "**EasyAppHelper** documentation"
1
+ # EasyAppHelper
2
+
3
+ **This [gem][EAP] aims at providing useful helpers for command line applications.**
4
+
5
+ This is a complete rewrite of the initial easy_app_helper gem. **It is not compatible with
6
+ apps designed for easy_app_helper prior to version 1.0.0**, although they could be very easily adapted
7
+ (anyway you always specify your gem dependencies using the [pessimistic version operator]
8
+ (http://docs.rubygems.org/read/chapter/16#page74), don't you ?). Older applications should explicitly
9
+ require to use the latest version of the 0.x.x series instead. The config files themselves remain
10
+ compatible with all versions of **EasyAppHelper**, as they are actually just plain Yaml files...
11
+
12
+ The new **EasyAppHelper** module provides:
13
+
14
+ * A **super charged Config class** that:
15
+ * Manages **multiple sources of configuration**(command line, multiple config files...) in a **layered config**.
16
+ * Provides an **easy to customize merge mechanism** for the different **config layers** that renders a "live view"
17
+ of the merged configuration, while keeping a way to access or modify independently any of them.
18
+ * Allows **flexibility** when dealing with modification and provides a way to roll back modifications done to config
19
+ anytime, fully reload it, blast it... Export feature could be very easily added and will probably.
20
+ * A **Logger tightly coupled with the Config** class, that will behave regarding options specified be it from
21
+ command line or from any source(layer) of the config object...
22
+ * Embeds [Slop][slop] to handle **command line parameters** and keeps all parameters specified from the command
23
+ line in a **dedicated layer of the config object**.
24
+ * A mechanism that ensures that as soon as you access any of the objects or methods exposed by EasyAppHelper,
25
+ all of them are **fully configured and ready to be used**.
26
+
27
+ If you are writing command line applications, I hope you will like it because it's very easy to use,
28
+ and as unobtrusive as possible (you choose when you want to include or use as a module) while providing
29
+ a ready-for-prod config, logger and command line management.
30
+
31
+
32
+ Currently the only runtime dependency is the cool [Slop gem][slop] which is used to process the command line options.
33
+
34
+ [Why this gem][4] ?
35
+
36
+
37
+
38
+ ## Installation
39
+
40
+ Add this line to your application's Gemfile:
41
+
42
+ gem 'easy_app_helper'
43
+
44
+ And then execute:
45
+
46
+ $ bundle
47
+
48
+ Or install it yourself as:
49
+
50
+ $ gem install easy_app_helper
51
+
52
+
53
+
54
+
55
+ ## Usage
56
+
57
+ To use it, once you installed them, you just need to require it:
58
+
59
+ ```ruby
60
+ require 'easy_app_helper'
61
+ ```
62
+
63
+ Then can can immediately access the logger or the config objects. Here under a first example:
64
+
65
+ ```ruby
66
+ require 'easy_app_helper'
67
+
68
+ # You can directly access the config or the logger through the **EasyAppHelper** module
69
+ puts "The application verbose flag is #{EasyAppHelper.config[:verbose]}"
70
+
71
+ # You can directly use the logger according to the command line flags
72
+ # This will do nothing unless --debug is set and --log-level is set to the correct level
73
+ EasyAppHelper.logger.info "Hi guys!"
74
+
75
+ # Fed up with the **EasyAppHelper** prefix ? Just include the module where you want
76
+ include EasyAppHelper
77
+
78
+ # You can override programmatically any part of the config
79
+ config[:debug] = true
80
+ logger.level = 1
81
+ config[:test] = 'Groovy'
82
+ EasyAppHelper.logger.info "Hi guys!... again"
83
+
84
+ # You can see the internals of the config
85
+ puts config.internal_configs.to_yaml
86
+ # Which will output
87
+ #:modified:
88
+ # :content:
89
+ # :log-level: 1
90
+ # :debug: true
91
+ # :test: cool
92
+ # :source: Changed by code
93
+ #:command_line:
94
+ # :content:
95
+ # :auto:
96
+ # :simulate:
97
+ # :verbose: true
98
+ # :help:
99
+ # :config-file:
100
+ # :config-override:
101
+ # :debug:
102
+ # :debug-on-err:
103
+ # :log-level:
104
+ # :log-file:
105
+ # :source: Command line
106
+ #:system:
107
+ # :content: {}
108
+ # :source:
109
+ # :origin: EasyAppHelper
110
+ #:global:
111
+ # :content: {}
112
+ # :source:
113
+ # :origin: ''
114
+ #:user:
115
+ # :content: {}
116
+ # :source:
117
+ # :origin: ''
118
+ #:specific_file:
119
+ # :content: {}
120
+
121
+ # You see of course that the two modifications we did are in the modified sub-hash
122
+ # And now the merged config
123
+ puts config.to_hash
124
+
125
+ # But you can see the modified part as it is:
126
+ puts config.internal_configs[:modified]
127
+
128
+ # Of course you can access it from any class
129
+ class Dummy
130
+ include EasyAppHelper
131
+
132
+ def initialize
133
+ puts "#{config[:test]} baby !"
134
+ # Back to the original
135
+ config.reset
136
+ puts config.internal_configs[:modified]
137
+ end
138
+ end
139
+
140
+ Dummy.new
141
+
142
+ # Some methods are provided to ease common tasks. For example this one will log at info level
143
+ # (so only displayed if debug mode and log level low enough), but will also puts on the console
144
+ # if verbose if set...
145
+ puts_and_logs "Hi world"
146
+
147
+ # It is actually one of the few methods added to regular Logger class (The added value of this logger
148
+ # is much more to be tightly coupled with the config object). Thus could access it like that:
149
+ logger.puts_and_logs "Hi world"
150
+
151
+ # or even
152
+ EasyAppHelper.logger.puts_and_logs "Hi world... 3 is enough."
153
+ ```
154
+
155
+
156
+ ## Configuration layers
157
+
158
+ **EasyAppHelper** will look for files in numerous places. **Both Unix and Windows places are handled**.
159
+ All the files are [Yaml][yaml] files but could have names with different extensions.
160
+
161
+ You can look in the [classes documentation][doc] to know exactly which extensions and places the config
162
+ files are looked for.
163
+
164
+ ### System config file
165
+
166
+ This config file is common to all applications that use EasyAppHelper. For example on a Unix system
167
+ regarding the rules described above, the framework will for the following files in that order:
168
+
169
+ ```text
170
+ # It will be loaded in the :system layer
171
+ /etc/EasyAppHelper.conf
172
+ /etc/EasyAppHelper.yml
173
+ /etc/EasyAppHelper.cfg
174
+ /etc/EasyAppHelper.yaml
175
+ /etc/EasyAppHelper.CFG
176
+ /etc/EasyAppHelper.YML
177
+ /etc/EasyAppHelper.YAML
178
+ /etc/EasyAppHelper.Yaml
179
+ ```
180
+
181
+ ### Application config files
182
+
183
+ Application config file names are determined from the config.script_filename property. It initially contains
184
+ the bare name of the script(path and extension removed), but you can replace with whatever you want. Changing
185
+ this property causes actually the impacted files to be reloaded.
186
+
187
+ It is in fact a two level configuration. One is global (the :global layer) and the other is at user level (the
188
+ :user layer).
189
+
190
+ For example on a Unix system or cygwin
191
+
192
+ ```text
193
+ # For the :global layer
194
+ /etc/myscript.conf
195
+ /etc/myscript.yml
196
+ /etc/myscript.cfg
197
+ /etc/myscript.yaml
198
+ /etc/myscript.CFG
199
+ /etc/myscript.YML
200
+ /etc/myscript.YAML
201
+ /etc/myscript.Yaml
202
+ /usr/local/etc/myscript.conf
203
+ /usr/local/etc/myscript.yml
204
+ /usr/local/etc/myscript.cfg
205
+ /usr/local/etc/myscript.yaml
206
+ /usr/local/etc/myscript.CFG
207
+ /usr/local/etc/myscript.YML
208
+ /usr/local/etc/myscript.YAML
209
+ /usr/local/etc/myscript.Yaml
210
+ # For the :user level
211
+ ${HOME}/.config/myscript.conf
212
+ ${HOME}/.config/myscript.yml
213
+ ${HOME}/.config/myscript.cfg
214
+ ${HOME}/.config/myscript.yaml
215
+ ${HOME}/.config/myscript.CFG
216
+ ${HOME}/.config/myscript.YML
217
+ ${HOME}/.config/myscript.YAML
218
+ ${HOME}/.config/myscript.Yaml
219
+ ```
220
+
221
+ ### Command line specified config file
222
+
223
+ The command line option ```--config-file``` provides a way to specify explicitly a config file. On top of this the
224
+ option ```--config-override``` tells **EasyAppHelper** to ignore :system, :global and :user levels.
225
+
226
+ The file will be loaded in a separated layer called :specific_file
227
+
228
+
229
+ ### The command line options
230
+
231
+ **EasyAppHelper** already provides by default some command line options. Imagine you have the following program.
232
+
233
+ ```ruby
234
+ #!/usr/bin/env ruby
235
+
236
+ require 'easy_app_helper'
237
+
238
+ class MyApp
239
+ include EasyAppHelper
240
+
241
+ APP_NAME = "My super application"
242
+ VERSION = '0.0.1'
243
+ DESCRIPTION = 'This application is a proof of concept for EasyAppHelper.'
244
+
245
+
246
+ def initialize
247
+ # Providing this data is optional but brings better logging and online help
248
+ config.describes_application(app_name: APP_NAME, app_version: VERSION, app_description: DESCRIPTION)
249
+ end
250
+
251
+
252
+ def run
253
+ if config[:help]
254
+ puts config.help
255
+ exit 0
256
+ end
257
+ puts_and_logs "Application is starting"
258
+ do_some_processing
259
+ end
260
+
261
+ def do_some_processing
262
+ puts_and_logs "Starting some heavy processing"
263
+ end
264
+
265
+ end
266
+
267
+
268
+ MyApp.new.run
269
+ ```
270
+
271
+ And you run it without any command line option
272
+
273
+ ```text
274
+ ./test4_app.rb
275
+ ```
276
+
277
+ No output...
278
+
279
+ Let' try
280
+
281
+ ```text
282
+ ./test4_app.rb --help
283
+
284
+ Usage: test4_app [options]
285
+ My super application Version: 0.0.1
286
+
287
+ This application is a proof of concept for EasyAppHelper.
288
+ -- Generic options -------------------------------------------------------------
289
+ --auto Auto mode. Bypasses questions to user.
290
+ --simulate Do not perform the actual underlying actions.
291
+ -v, --verbose Enable verbose mode.
292
+ -h, --help Displays this help.
293
+ -- Configuration options -------------------------------------------------------
294
+ --config-file Specify a config file.
295
+ --config-override If specified override all other config.
296
+ -- Debug and logging options ---------------------------------------------------
297
+ --debug Run in debug mode.
298
+ --debug-on-err Run in debug mode with output to stderr.
299
+ --log-level Log level from 0 to 5, default 2.
300
+ --log-file File to log to.
301
+
302
+ ```
303
+ You see there the online help. And then the program exists.
304
+
305
+ Let's try the ```--verbose``` flag
306
+
307
+ ```text
308
+ ./test4_app.rb --verbose
309
+ Application is starting
310
+ Starting some heavy processing
311
+ ```
312
+
313
+ You see that the puts_and_logs is sensitive to the ```--verbose``` switch...
314
+
315
+ But what if I debug
316
+ ```text
317
+ ./test4_app.rb --debug
318
+ ```
319
+
320
+ Humm... nothing... Let's provide the log level
321
+
322
+ ```text
323
+ ./test4_app.rb --debug --log-level 0
324
+ I, [2013-06-23T19:37:24.975392 #10276] INFO -- My super application: Application is starting
325
+ I, [2013-06-23T19:37:24.975592 #10276] INFO -- My super application: Starting some heavy processing
326
+ ```
327
+
328
+ You see there that the puts_and_logs logs as well with the log level 1 (Info)... Nice looks like it was claiming
329
+ this in its name... ;-)
330
+
331
+ If I mix ?
332
+
333
+ ```text
334
+ ./test4_app.rb --debug --log-level 0 --verbose
335
+ Application is starting
336
+ I, [2013-06-23T19:39:05.712558 #11768] INFO -- My super application: Application is starting
337
+ Starting some heavy processing
338
+ I, [2013-06-23T19:39:05.712834 #11768] INFO -- My super application: Starting some heavy processing
339
+ ```
340
+
341
+ So far so good...
342
+
343
+ ### Specifying command line parameters
344
+
345
+ As said, internally **EasyAppHelper** uses the [Slop gem][slop] to handle the command line parameters.
346
+ You can configure the internal Slop object by calling the add_command_line_section method of the config
347
+ object. You could create a method that setup your application command line parameters like this:
348
+
349
+ ```ruby
350
+ def add_cmd_line_options
351
+ config.add_command_line_section do |slop|
352
+ slop.on :u, :useless, 'Stupid option', :argument => false
353
+ slop.on :anint, 'Stupid option with integer argument', :argument => true, :as => Integer
354
+ end
355
+ end
356
+
357
+ ```
358
+
359
+ See [Slop gem][slop] API documentation for more options.
360
+
361
+
362
+ ### Debugging the framework itself
363
+
364
+ If you want, you can even debug what happens during **EasyAppHelper** initialisation, for this you can use the
365
+ ```DEBUG_EASY_MODULES``` environment variable. As how and where everything has to be logged is only specified when
366
+ you actually provide command line options, **EasyAppHelper** provides a temporary logger to itself and will
367
+ after all dump the logger content to the logger you specified and if you specify... So that you don't miss a log.
368
+
369
+ ```text
370
+ $ DEBUG_EASY_MODULES=y ruby ./test4_app.rb
371
+
372
+ D, [2013-06-23T19:43:47.977031 #16294] DEBUG -- : Temporary initialisation logger created...
373
+ D, [2013-06-23T19:43:47.977861 #16294] DEBUG -- : Trying "/etc/EasyAppHelper.conf" as config file.
374
+ D, [2013-06-23T19:43:47.977908 #16294] DEBUG -- : Trying "/etc/EasyAppHelper.yml" as config file.
375
+ D, [2013-06-23T19:43:47.977938 #16294] DEBUG -- : Loading config file "/etc/EasyAppHelper.cfg"
376
+ D, [2013-06-23T19:43:47.978300 #16294] DEBUG -- : Trying "/etc/test4_app.conf" as config file.
377
+ D, [2013-06-23T19:43:47.978332 #16294] DEBUG -- : Trying "/etc/test4_app.yml" as config file.
378
+ D, [2013-06-23T19:43:47.978355 #16294] DEBUG -- : Trying "/etc/test4_app.cfg" as config file.
379
+ D, [2013-06-23T19:43:47.978381 #16294] DEBUG -- : Trying "/etc/test4_app.yaml" as config file.
380
+ D, [2013-06-23T19:43:47.978403 #16294] DEBUG -- : Trying "/etc/test4_app.CFG" as config file.
381
+ D, [2013-06-23T19:43:47.978424 #16294] DEBUG -- : Trying "/etc/test4_app.YML" as config file.
382
+ D, [2013-06-23T19:43:47.978445 #16294] DEBUG -- : Trying "/etc/test4_app.YAML" as config file.
383
+ D, [2013-06-23T19:43:47.978466 #16294] DEBUG -- : Trying "/etc/test4_app.Yaml" as config file.
384
+ D, [2013-06-23T19:43:47.978491 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.conf" as config file.
385
+ D, [2013-06-23T19:43:47.978529 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.yml" as config file.
386
+ D, [2013-06-23T19:43:47.978553 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.cfg" as config file.
387
+ D, [2013-06-23T19:43:47.978575 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.yaml" as config file.
388
+ D, [2013-06-23T19:43:47.978597 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.CFG" as config file.
389
+ D, [2013-06-23T19:43:47.978619 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.YML" as config file.
390
+ D, [2013-06-23T19:43:47.978670 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.Yaml" as config file.
391
+ I, [2013-06-23T19:43:47.978695 #16294] INFO -- : No config file found for layer global.
392
+ D, [2013-06-23T19:43:47.978725 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.conf" as config file.
393
+ D, [2013-06-23T19:43:47.978748 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.yml" as config file.
394
+ D, [2013-06-23T19:43:47.978770 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.cfg" as config file.
395
+ D, [2013-06-23T19:43:47.978792 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.yaml" as config file.
396
+ D, [2013-06-23T19:43:47.978817 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.CFG" as config file.
397
+ D, [2013-06-23T19:43:47.978840 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.YML" as config file.
398
+ D, [2013-06-23T19:43:47.978861 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.YAML" as config file.
399
+ D, [2013-06-23T19:43:47.978974 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.Yaml" as config file.
400
+ I, [2013-06-23T19:43:47.979000 #16294] INFO -- : No config file found for layer user.
401
+ I, [2013-06-23T19:43:47.979025 #16294] INFO -- : No config file found for layer specific_file.
402
+ D, [2013-06-23T19:43:47.979514 #16294] DEBUG -- : Trying "/etc/EasyAppHelper.conf" as config file.
403
+ D, [2013-06-23T19:43:47.979561 #16294] DEBUG -- : Trying "/etc/EasyAppHelper.yml" as config file.
404
+ D, [2013-06-23T19:43:47.979591 #16294] DEBUG -- : Loading config file "/etc/EasyAppHelper.cfg"
405
+ D, [2013-06-23T19:43:47.979717 #16294] DEBUG -- : Trying "/etc/test4_app.conf" as config file.
406
+ D, [2013-06-23T19:43:47.979747 #16294] DEBUG -- : Trying "/etc/test4_app.yml" as config file.
407
+ D, [2013-06-23T19:43:47.979800 #16294] DEBUG -- : Trying "/etc/test4_app.cfg" as config file.
408
+ D, [2013-06-23T19:43:47.979823 #16294] DEBUG -- : Trying "/etc/test4_app.yaml" as config file.
409
+ D, [2013-06-23T19:43:47.979845 #16294] DEBUG -- : Trying "/etc/test4_app.CFG" as config file.
410
+ D, [2013-06-23T19:43:47.979867 #16294] DEBUG -- : Trying "/etc/test4_app.YML" as config file.
411
+ D, [2013-06-23T19:43:47.979908 #16294] DEBUG -- : Trying "/etc/test4_app.YAML" as config file.
412
+ D, [2013-06-23T19:43:47.979935 #16294] DEBUG -- : Trying "/etc/test4_app.Yaml" as config file.
413
+ D, [2013-06-23T19:43:47.979959 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.conf" as config file.
414
+ D, [2013-06-23T19:43:47.979981 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.yml" as config file.
415
+ D, [2013-06-23T19:43:47.980004 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.cfg" as config file.
416
+ D, [2013-06-23T19:43:47.980026 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.yaml" as config file.
417
+ D, [2013-06-23T19:43:47.980047 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.CFG" as config file.
418
+ D, [2013-06-23T19:43:47.980069 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.YML" as config file.
419
+ D, [2013-06-23T19:43:47.980091 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.YAML" as config file.
420
+ D, [2013-06-23T19:43:47.980112 #16294] DEBUG -- : Trying "/usr/local/etc/test4_app.Yaml" as config file.
421
+ I, [2013-06-23T19:43:47.980135 #16294] INFO -- : No config file found for layer global.
422
+ D, [2013-06-23T19:43:47.980181 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.conf" as config file.
423
+ D, [2013-06-23T19:43:47.980207 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.yml" as config file.
424
+ D, [2013-06-23T19:43:47.980230 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.cfg" as config file.
425
+ D, [2013-06-23T19:43:47.980252 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.yaml" as config file.
426
+ D, [2013-06-23T19:43:47.980274 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.CFG" as config file.
427
+ D, [2013-06-23T19:43:47.980296 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.YML" as config file.
428
+ D, [2013-06-23T19:43:47.980319 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.YAML" as config file.
429
+ D, [2013-06-23T19:43:47.980361 #16294] DEBUG -- : Trying "/home/laurent/.config/test4_app.Yaml" as config file.
430
+ I, [2013-06-23T19:43:47.980395 #16294] INFO -- : No config file found for layer user.
431
+ I, [2013-06-23T19:43:47.980418 #16294] INFO -- : No config file found for layer specific_file.
432
+ D, [2013-06-23T19:43:47.981934 #16294] DEBUG -- : Config layers:
433
+ ---
434
+ :modified:
435
+ :content: {}
436
+ :source: Changed by code
437
+ :command_line:
438
+ :content:
439
+ :auto:
440
+ :simulate:
441
+ :verbose: true
442
+ :help:
443
+ :config-file:
444
+ :config-override:
445
+ :debug: true
446
+ :debug-on-err:
447
+ :log-level: 0
448
+ :log-file:
449
+ :source: Command line
450
+ :system:
451
+ :content:
452
+ :copyright: (c) 2012-2013 Nanonet
453
+ :source: /etc/EasyAppHelper.cfg
454
+ :origin: EasyAppHelper
455
+ :global:
456
+ :content: {}
457
+ :source:
458
+ :origin: test4_app
459
+ :user:
460
+ :content: {}
461
+ :source:
462
+ :origin: test4_app
463
+ :specific_file:
464
+ :content: {}
465
+
466
+ D, [2013-06-23T19:43:47.985357 #16294] DEBUG -- : Merged config:
467
+ ---
468
+ :copyright: (c) 2012-2013 Nanonet
469
+ :verbose: true
470
+ :debug: true
471
+ :log-level: 0
472
+
473
+ Application is starting
474
+ I, [2013-06-23T19:43:47.986298 #16294] INFO -- My super application: Application is starting
475
+ Starting some heavy processing
476
+ I, [2013-06-23T19:43:47.986460 #16294] INFO -- My super application: Starting some heavy processing
477
+ ```
478
+
479
+ You can notice that what **EasyAppHelper** initialisation logged and what you application logged
480
+ did eventually end-up in the same log...
481
+
482
+
483
+ ## Contributing
484
+
485
+ 1. Fork it
486
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
487
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
488
+ 4. Push to the branch (`git push origin my-new-feature`)
489
+ 5. Create new Pull Request
490
+
491
+
492
+ That's all folks.
493
+
494
+
495
+ [EAP]: https://rubygems.org/gems/easy_app_helper "**EasyAppHelper** gem"
496
+ [slop]: https://rubygems.org/gems/slop "Slop gem"
497
+ [yaml]: http://www.yaml.org/ "The Yaml official site"
498
+ [doc]: http://rubydoc.info/github/lbriais/easy_app_helper/master "**EasyAppHelper** documentation"
499
499
  [4]: https://github.com/lbriais/easy_app_helper/wiki "**EasyAppHelper** wiki"