tinyconfig 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/.travis.yml +12 -0
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +43 -0
- data/Gemfile +13 -0
- data/LICENSE +20 -0
- data/README.md +149 -0
- data/Thorfile +60 -0
- data/example/config-invalid.rb +1 -0
- data/example/config1.rb +1 -0
- data/example/config2.rb +1 -0
- data/example/config3.rb +2 -0
- data/example/hello.rb +23 -0
- data/example/lambda.rb +18 -0
- data/lib/tinyconfig.rb +94 -0
- data/lib/tinyconfig/version.rb +3 -0
- data/spec/fixtures/basic.rb +1 -0
- data/spec/fixtures/basic_nested.rb +1 -0
- data/spec/fixtures/directory.rb +1 -0
- data/spec/fixtures/directory/config1.rb +1 -0
- data/spec/fixtures/directory/config2.rb +1 -0
- data/spec/fixtures/glob1.rb +1 -0
- data/spec/fixtures/glob2.rb +1 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/tinyconfig/version_spec.rb +9 -0
- data/spec/tinyconfig_lambda_spec.rb +43 -0
- data/spec/tinyconfig_spec.rb +76 -0
- data/spec/tinyconfig_validation_spec.rb +32 -0
- data/tinyconfig.gemspec +28 -0
- metadata +183 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZWNjYTc2NjdhZGYzMzJkODIwY2Y3YzYyNWMwZmMyZmU2YTU3MWYyNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZjAzNWQzYjcxNTkwNjIyODljOWU1MTBiZmRjMTEzZTNiNzUyM2U3Yw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NGI1N2ZiZjgxZTk4OTRkOWM4NjQzODJiMjhhZDM3ZTM4ZTQzYmRjZGMzNzIz
|
10
|
+
NThiYzAyN2I1NDg1NjY4NTY4ZTcwOGJjNTRjNTczMjBmMDU2NGJjOWM3ODIx
|
11
|
+
ZTc3MDA3MGEyZmY1MTY1ZWIyNDdjMDAwMjM4MjlmOTFkZjQ3OWQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
OTI3OWMzYmRmYjA4MjExOWE0Nzc1MTVjNTljZTk5OTlmM2UxYTc2N2Q0NGY3
|
14
|
+
MWUyZGQ2NGUzNzc1NzRhNWVlNTVjMTlkZjYzM2YzODhkNTkyMDUwMDhmN2Nm
|
15
|
+
MzQ4MDZkMGZlNGM4NDQ5NTMxMDRlY2M4OTczYTQxMWU4ODI5MjA=
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
---
|
2
|
+
bundler_args: --without developer_workstation
|
3
|
+
script: bundle exec thor test:ci
|
4
|
+
rvm:
|
5
|
+
- 1.9.3
|
6
|
+
- 2.0.0
|
7
|
+
- jruby-19mode
|
8
|
+
- jruby-head
|
9
|
+
- rbx-19mode
|
10
|
+
notifications:
|
11
|
+
hipchat:
|
12
|
+
secure: BdOAQHgi1RaQk8OyBbZzlgmrxVIF8RSYmDytZct4ynLrh8N19I/NeXTRFsnBlIcvRkWfrkztQ9YiGDS/IWoVvfLIz6Z3JJuDCE5AfrDdBFHRgjy0EeSxFoQYiKoaXkafdzCeN7lKs1uquU7SvFgE8o1zV9KiqYB2BuDqPkru3Kc=
|
data/CHANGELOG.md
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
## Developing
|
4
|
+
|
5
|
+
1. Fork the repository on GitHub
|
6
|
+
2. Create your feature branch (`git checkout -b feature/awesomeness`)
|
7
|
+
3. Create your changes.
|
8
|
+
* Add test cases in `spec/`. It's best if you first write a failing
|
9
|
+
test case, commit it, and then fix it in next commit - this makes
|
10
|
+
the whole change easier to review.
|
11
|
+
* Document your changes.
|
12
|
+
4. Commit your changes (`git commit -am 'Add more awesomeness'`)
|
13
|
+
5. Push to the branch (`git push -u origin feature/awesomeness`)
|
14
|
+
6. Create new Pull Request on GitHub
|
15
|
+
|
16
|
+
## Testing
|
17
|
+
|
18
|
+
### Install what's needed
|
19
|
+
|
20
|
+
Make sure you have [http://gembundler.com/](Gem Bundler) version 1.3
|
21
|
+
or greater installed. If in doubt, just use [http://rvm.io/](RVM) or
|
22
|
+
[http://rbenv.org/](rbenv).
|
23
|
+
|
24
|
+
$ gem install bundler
|
25
|
+
|
26
|
+
Clone the project:
|
27
|
+
|
28
|
+
$ git clone git://github.com/3ofcoins/tinyconfig.git
|
29
|
+
|
30
|
+
Then, run:
|
31
|
+
|
32
|
+
$ cd tinyconfig
|
33
|
+
$ bundle install
|
34
|
+
|
35
|
+
Bundler will install all the needed gems and their dependencies.
|
36
|
+
|
37
|
+
### Running tests
|
38
|
+
|
39
|
+
$ bundle exec thor spec
|
40
|
+
|
41
|
+
To generate test coverage report, tell it to Thor
|
42
|
+
|
43
|
+
$ bundle exec thor spec --coverage
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
# Helpers used with development, but not needed in runtime, build
|
6
|
+
# time, or for tests.
|
7
|
+
group :developer_workstation do
|
8
|
+
gem 'awesome_print'
|
9
|
+
gem 'pry'
|
10
|
+
gem 'pry-debugger'
|
11
|
+
gem 'pry-rescue'
|
12
|
+
gem 'pry-stack_explorer'
|
13
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (C) 2013 Maciej Pasternacki <maciej@3ofcoins.net>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
# Tinyconfig
|
2
|
+
|
3
|
+
TinyConfig provides a base class to create a Ruby configuration file
|
4
|
+
loader.
|
5
|
+
|
6
|
+
The resulting configuration file is usable for people not familiar
|
7
|
+
with Ruby, but it is possible for a power user to use full power of
|
8
|
+
Ruby to script the configuration
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'tinyconfig'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install tinyconfig
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
First, define your configuration class by creating a subclass of
|
27
|
+
`TinyConfig`. Use `option` method to define known options. You may
|
28
|
+
provide a default value as a second argument, and a
|
29
|
+
validator/postprocessing as a block.
|
30
|
+
|
31
|
+
The block receives one argument: value as provided by user. It should
|
32
|
+
raise `::ArgumentError` if the provided value is invalid, and return
|
33
|
+
the desired value otherwise. See the `example/hello.rb` file for a
|
34
|
+
sample usage:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'tinyconfig'
|
38
|
+
|
39
|
+
class HelloConfig < TinyConfig
|
40
|
+
option :recipient, 'World'
|
41
|
+
|
42
|
+
option :repeat, 1 do |value|
|
43
|
+
int_value = value.to_i
|
44
|
+
if int_value < 1
|
45
|
+
raise ::ArgumentError, "#{value.inspect} is not a number or is less than 1"
|
46
|
+
end
|
47
|
+
int_value
|
48
|
+
end
|
49
|
+
|
50
|
+
option :extra_greeting
|
51
|
+
end
|
52
|
+
|
53
|
+
cfg = HelloConfig.new
|
54
|
+
cfg.load ARGV.first if ARGV.first
|
55
|
+
|
56
|
+
cfg.repeat.times do
|
57
|
+
puts "Hello, #{cfg.recipient}!"
|
58
|
+
end
|
59
|
+
puts cfg.extra_greeting if cfg.extra_greeting
|
60
|
+
```
|
61
|
+
|
62
|
+
```
|
63
|
+
$ ruby hello.rb
|
64
|
+
Hello, World!
|
65
|
+
$ cat config1.rb
|
66
|
+
recipient 'You'
|
67
|
+
$ ruby hello.rb config1.rb
|
68
|
+
Hello, You!
|
69
|
+
$ cat config2.rb
|
70
|
+
repeat 3
|
71
|
+
$ ruby hello.rb config2.rb
|
72
|
+
Hello, World!
|
73
|
+
Hello, World!
|
74
|
+
Hello, World!
|
75
|
+
$ cat config3.rb
|
76
|
+
repeat '2'
|
77
|
+
extra_greeting 'Really, hello!'
|
78
|
+
$ ruby hello.rb config3.rb
|
79
|
+
Hello, World!
|
80
|
+
Hello, World!
|
81
|
+
Really, hello!
|
82
|
+
$ cat config-invalid.rb
|
83
|
+
repeat 'whatever'
|
84
|
+
$ ruby hello.rb config-invalid.rb
|
85
|
+
hello.rb:9:in `block in <class:HelloConfig>': "whatever" is not a number or is less than 1 (ArgumentError)
|
86
|
+
from /Users/japhy/Projekty/tinyconfig/lib/tinyconfig.rb:16:in `call'
|
87
|
+
from /Users/japhy/Projekty/tinyconfig/lib/tinyconfig.rb:16:in `block in option'
|
88
|
+
from ./config-invalid.rb:in `load'
|
89
|
+
from /Users/japhy/Projekty/tinyconfig/lib/tinyconfig.rb:36:in `instance_eval'
|
90
|
+
from /Users/japhy/Projekty/tinyconfig/lib/tinyconfig.rb:36:in `load'
|
91
|
+
from hello.rb:18:in `<main>'
|
92
|
+
```
|
93
|
+
|
94
|
+
You can use the `load` method multiple times from your code, or you
|
95
|
+
can `load` other files from your config files. The method also accepts
|
96
|
+
glob expressions (e.g. `load 'config_*.rb'`). The `bulk_load` method load all files
|
97
|
+
in the directory next to current config file, of the same name as current config.
|
98
|
+
|
99
|
+
Example: If file `foo.rb` calls:
|
100
|
+
|
101
|
+
`bulk_load`
|
102
|
+
|
103
|
+
it should do the same as
|
104
|
+
|
105
|
+
`load 'foo/*.rb'`
|
106
|
+
|
107
|
+
You can also use `cfg.configure` method to update the configuration
|
108
|
+
inline in a block.
|
109
|
+
|
110
|
+
When you provide a lambda as a default or provided value, it will be
|
111
|
+
called at runtime to determine the value. This way you can use
|
112
|
+
settings that are not yet specified when the config file is being
|
113
|
+
read:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
class LambdaExample < TinyConfig
|
117
|
+
option :foo
|
118
|
+
option :bar, ->{ "Bar for foo=#{foo.inspect}" }
|
119
|
+
option :baz
|
120
|
+
end
|
121
|
+
|
122
|
+
cfg = LambdaExample.new
|
123
|
+
cfg.bar # => "Bar for foo=nil"
|
124
|
+
|
125
|
+
cfg.configure do
|
126
|
+
foo 23
|
127
|
+
end
|
128
|
+
cfg.bar # => "Bar for foo=23"
|
129
|
+
|
130
|
+
cfg.configure do
|
131
|
+
baz ->{ bar.reverse }
|
132
|
+
end
|
133
|
+
cfg.baz # => "32=oof rof raB"
|
134
|
+
```
|
135
|
+
|
136
|
+
For details and corner cases, look into `spec/` for the test cases.
|
137
|
+
|
138
|
+
## Acknowledements
|
139
|
+
|
140
|
+
TinyConfig has been heavily inspired by Opscode's
|
141
|
+
[Mixlib::Config](https://github.com/opscode/mixlib-config). We chose
|
142
|
+
to implement our own tool, because `Mixlib::Config` configuration is
|
143
|
+
global, which makes it very hard to provide isolation between test
|
144
|
+
cases in the unit tests. TinyConfig is instance-based, which is easier
|
145
|
+
to manage locally.
|
146
|
+
|
147
|
+
## Contributing
|
148
|
+
|
149
|
+
See the [CONTRIBUTING.md](CONTRIBUTING.md) file
|
data/Thorfile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
|
6
|
+
require 'rake/testtask'
|
7
|
+
require 'thor/rake_compat'
|
8
|
+
|
9
|
+
class Default < Thor
|
10
|
+
class Gem < Thor
|
11
|
+
namespace :gem
|
12
|
+
|
13
|
+
include Thor::RakeCompat
|
14
|
+
Bundler::GemHelper.install_tasks
|
15
|
+
|
16
|
+
desc "build", "Build tinyconfig-#{TinyConfig::VERSION}.gem into the pkg directory"
|
17
|
+
def build
|
18
|
+
Rake::Task["build"].execute
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "release", "Create tag v#{TinyConfig::VERSION} and build and push tinyconfig-#{TinyConfig::VERSION}.gem to Rubygems"
|
22
|
+
def release
|
23
|
+
Rake::Task["release"].execute
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "install", "Build and install tinyconfig-#{TinyConfig::VERSION}.gem into system gems"
|
27
|
+
def install
|
28
|
+
Rake::Task["install"].execute
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Test < Thor
|
33
|
+
namespace :test
|
34
|
+
default_command :all
|
35
|
+
|
36
|
+
include Thor::RakeCompat
|
37
|
+
|
38
|
+
Rake::TestTask.new :spec do |task|
|
39
|
+
task.libs << 'spec'
|
40
|
+
task.test_files = FileList['spec/**/*_spec.rb']
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'spec', 'Run specs'
|
44
|
+
def spec
|
45
|
+
Rake::Task['spec'].execute
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'all', 'Run all tests'
|
49
|
+
def all
|
50
|
+
invoke(:spec)
|
51
|
+
end
|
52
|
+
|
53
|
+
desc 'ci', 'Run all tests for continuous integration'
|
54
|
+
def ci
|
55
|
+
ENV['CI'] = 'true'
|
56
|
+
invoke(:all)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
repeat 'whatever'
|
data/example/config1.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
recipient 'You'
|
data/example/config2.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
repeat 3
|
data/example/config3.rb
ADDED
data/example/hello.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'tinyconfig'
|
2
|
+
|
3
|
+
class HelloConfig < TinyConfig
|
4
|
+
option :recipient, 'World'
|
5
|
+
|
6
|
+
option :repeat, 1 do |value|
|
7
|
+
int_value = value.to_i
|
8
|
+
if int_value < 1
|
9
|
+
raise ::ArgumentError, "#{value.inspect} is not a number or is less than 1"
|
10
|
+
end
|
11
|
+
int_value
|
12
|
+
end
|
13
|
+
|
14
|
+
option :extra_greeting
|
15
|
+
end
|
16
|
+
|
17
|
+
cfg = HelloConfig.new
|
18
|
+
cfg.load ARGV.first if ARGV.first
|
19
|
+
|
20
|
+
cfg.repeat.times do
|
21
|
+
puts "Hello, #{cfg.recipient}!"
|
22
|
+
end
|
23
|
+
puts cfg.extra_greeting if cfg.extra_greeting
|
data/example/lambda.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class LambdaExample < TinyConfig
|
2
|
+
option :foo
|
3
|
+
option :bar, ->{ "Bar for foo=#{foo.inspect}" }
|
4
|
+
option :baz
|
5
|
+
end
|
6
|
+
|
7
|
+
cfg = LambdaExample.new
|
8
|
+
cfg.bar # => "Bar for foo=nil"
|
9
|
+
|
10
|
+
cfg.configure do
|
11
|
+
foo 23
|
12
|
+
end
|
13
|
+
cfg.bar # => "Bar for foo=23"
|
14
|
+
|
15
|
+
cfg.configure do
|
16
|
+
baz ->{ bar.reverse }
|
17
|
+
end
|
18
|
+
cfg.baz # => "32=oof rof raB"
|
data/lib/tinyconfig.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require "tinyconfig/version"
|
2
|
+
|
3
|
+
class TinyConfig < BasicObject
|
4
|
+
class << self
|
5
|
+
#
|
6
|
+
# ### Define new option
|
7
|
+
def option(option_name, default=nil, &block)
|
8
|
+
option_name = option_name.to_sym
|
9
|
+
getter_name = "__get__#{option_name}".to_sym
|
10
|
+
validator = block_given? ? block : nil
|
11
|
+
|
12
|
+
# Private getter method for the default
|
13
|
+
# http://www.bofh.org.uk/2007/08/16/a-cunning-evil-trick-with-ruby
|
14
|
+
meth = default.respond_to?(:call) ? default : ->{ default }
|
15
|
+
define_method(getter_name, &meth)
|
16
|
+
private(getter_name)
|
17
|
+
|
18
|
+
define_method option_name do |*args|
|
19
|
+
if args.length.zero?
|
20
|
+
# No args -> get value
|
21
|
+
self.__send__(getter_name)
|
22
|
+
else
|
23
|
+
# Args provided -> set value (i.e. define getter method on the singleton)
|
24
|
+
if validator
|
25
|
+
value = validator.call(*args)
|
26
|
+
elsif args.length == 1
|
27
|
+
value = args.first
|
28
|
+
else
|
29
|
+
value = args
|
30
|
+
end
|
31
|
+
meth = value.respond_to?(:call) ? value : ->{ value }
|
32
|
+
(class << self ; self ; end).send(:define_method, getter_name, &meth)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# make arrow lambdas work on Rubinius
|
39
|
+
if ::RUBY_ENGINE == 'rbx'
|
40
|
+
def lambda(*args, &block)
|
41
|
+
::Kernel.lambda(*args, &block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
@_values = {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def configure(&block)
|
50
|
+
self.instance_eval(&block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def load(glob)
|
54
|
+
# If glob is relative, we want to interpret it relative to the
|
55
|
+
# calling file (directory that contains the ruby source file that
|
56
|
+
# has called the `TinyConfig#load` method) rather than whatever is
|
57
|
+
# the process' `Dir.getwd`.
|
58
|
+
|
59
|
+
glob = ::File.expand_path(glob, ::File.dirname(::Kernel.caller.first))
|
60
|
+
load_helper(glob)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bulk_load
|
64
|
+
caller_path = ::Kernel.caller.first.sub(/(:\d+)?(:in .*)?$/, '')
|
65
|
+
directory_name = ::File.join(
|
66
|
+
::File.dirname(caller_path),
|
67
|
+
::File.basename(caller_path, ".rb"))
|
68
|
+
bulk_glob = ::File.join(directory_name, "*.rb")
|
69
|
+
load_helper(bulk_glob)
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Compat methods
|
74
|
+
# --------------
|
75
|
+
|
76
|
+
def inspect
|
77
|
+
_values = @_values.sort.map { |k,v| " #{k}=#{v.inspect}" }.join
|
78
|
+
"#<#{__realclass__}#{_values}>"
|
79
|
+
end
|
80
|
+
|
81
|
+
alias_method :to_s, :inspect
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def load_helper(source)
|
86
|
+
::Dir.glob(source).sort.each do |path|
|
87
|
+
self.instance_eval(::File.read(path), path, 0)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def __realclass__
|
92
|
+
(class << self; self end).superclass
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
opt 23
|
@@ -0,0 +1 @@
|
|
1
|
+
load 'basic.rb'
|
@@ -0,0 +1 @@
|
|
1
|
+
bulk_load
|
@@ -0,0 +1 @@
|
|
1
|
+
opt 23
|
@@ -0,0 +1 @@
|
|
1
|
+
opt 17
|
@@ -0,0 +1 @@
|
|
1
|
+
opt 23
|
@@ -0,0 +1 @@
|
|
1
|
+
opt 17
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'minitest/spec'
|
6
|
+
require 'mocha/setup'
|
7
|
+
require 'wrong'
|
8
|
+
|
9
|
+
Wrong.config.alias_assert :expect, override: true
|
10
|
+
|
11
|
+
module TinyConfigSpec
|
12
|
+
module WrongHelper
|
13
|
+
include Wrong::Assert
|
14
|
+
include Wrong::Helpers
|
15
|
+
|
16
|
+
def failure_class
|
17
|
+
MiniTest::Assertion
|
18
|
+
end
|
19
|
+
|
20
|
+
def increment_assertion_count
|
21
|
+
self.assertions += 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class MiniTest::Spec
|
27
|
+
include TinyConfigSpec::WrongHelper
|
28
|
+
|
29
|
+
def fixture(filename)
|
30
|
+
File.join(File.dirname(__FILE__), 'fixtures', filename)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if ENV['COVERAGE']
|
35
|
+
require 'simplecov'
|
36
|
+
SimpleCov.start
|
37
|
+
SimpleCov.command_name 'rake spec'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Make TinyConfig pretty-printable.
|
41
|
+
require "tinyconfig"
|
42
|
+
class TinyConfig
|
43
|
+
begin
|
44
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
45
|
+
def object_id ; __id__ ; end
|
46
|
+
ensure
|
47
|
+
$VERBOSE = old_verbose
|
48
|
+
end
|
49
|
+
|
50
|
+
def class
|
51
|
+
__realclass__
|
52
|
+
end
|
53
|
+
|
54
|
+
def pretty_print(pp)
|
55
|
+
pp.object_address_group(self) do
|
56
|
+
pp.breakable
|
57
|
+
pp.pp_hash(@_values)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class LambdaExample < TinyConfig
|
4
|
+
option :foo
|
5
|
+
option :bar, ->{ "Bar for foo=#{foo.inspect}" }
|
6
|
+
option :baz
|
7
|
+
end
|
8
|
+
|
9
|
+
describe TinyConfig do
|
10
|
+
let(:cfg) { LambdaExample.new }
|
11
|
+
|
12
|
+
it "evaluates lambda default in runtime" do
|
13
|
+
expect { cfg.bar == "Bar for foo=nil" }
|
14
|
+
cfg.configure do
|
15
|
+
foo 23
|
16
|
+
end
|
17
|
+
expect { cfg.bar == "Bar for foo=23" }
|
18
|
+
end
|
19
|
+
|
20
|
+
it "evaluates lambda value in runtime" do
|
21
|
+
cfg.configure do
|
22
|
+
baz ->{ bar.reverse }
|
23
|
+
end
|
24
|
+
|
25
|
+
expect { cfg.baz == "lin=oof rof raB" }
|
26
|
+
|
27
|
+
cfg.configure do
|
28
|
+
foo 23
|
29
|
+
end
|
30
|
+
expect { cfg.baz == "32=oof rof raB" }
|
31
|
+
end
|
32
|
+
|
33
|
+
it "sets instance methods rather than class methods" do
|
34
|
+
cfg2 = LambdaExample.new
|
35
|
+
cfg.configure do
|
36
|
+
foo 23
|
37
|
+
end
|
38
|
+
expect { cfg.foo == 23 }
|
39
|
+
expect { cfg.bar == "Bar for foo=23" }
|
40
|
+
expect { cfg2.foo.nil? }
|
41
|
+
expect { cfg2.bar == "Bar for foo=nil" }
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BasicIdea < TinyConfig
|
4
|
+
option :opt
|
5
|
+
option :defopt, 23
|
6
|
+
end
|
7
|
+
|
8
|
+
describe TinyConfig do
|
9
|
+
let(:cfg) { BasicIdea.new }
|
10
|
+
|
11
|
+
describe ".option" do
|
12
|
+
it "defaults options' values to nil" do
|
13
|
+
expect { cfg.opt.nil? }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "sets default to a provided value" do
|
17
|
+
expect { cfg.defopt == 23 }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#configure" do
|
22
|
+
it "configures in a block" do
|
23
|
+
cfg.configure do
|
24
|
+
opt 23
|
25
|
+
end
|
26
|
+
|
27
|
+
expect { cfg.opt == 23 }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#load" do
|
32
|
+
it "loads configuration from file relative to the caller" do
|
33
|
+
cfg.load("fixtures/basic.rb")
|
34
|
+
expect { cfg.opt == 23 }
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can be nested" do
|
38
|
+
cfg.load("fixtures/basic_nested.rb")
|
39
|
+
expect { cfg.opt == 23 }
|
40
|
+
end
|
41
|
+
|
42
|
+
it "can load files by a glob expression" do
|
43
|
+
cfg.load("fixtures/glob*.rb")
|
44
|
+
expect { cfg.opt == 17 }
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'will handle absolute paths/globs correctly' do
|
48
|
+
cfg.load(File.join(File.dirname(__FILE__), 'fixtures/basic.rb'))
|
49
|
+
expect { cfg.opt == 23 }
|
50
|
+
|
51
|
+
cfg.load(File.join(File.dirname(__FILE__), 'fixtures/basic_nested.rb'))
|
52
|
+
expect { cfg.opt == 23 }
|
53
|
+
|
54
|
+
cfg.load(File.join(File.dirname(__FILE__), 'fixtures/glob*.rb'))
|
55
|
+
expect { cfg.opt == 17 }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#bulk_load" do
|
60
|
+
it "loads all files in the directory next to current config file, of the same name as current config" do
|
61
|
+
cfg.load("fixtures/directory.rb")
|
62
|
+
expect { cfg.opt == 17 }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "(configuration block)" do
|
67
|
+
it "raises an exception when somebody tries to set undefined value" do
|
68
|
+
expect { rescuing { cfg.configure { nopt -1 } }.is_a? NoMethodError }
|
69
|
+
end
|
70
|
+
|
71
|
+
it "overrides default values" do
|
72
|
+
cfg.configure { defopt 17 }
|
73
|
+
expect { cfg.defopt == 17 }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ValidatingConfig < TinyConfig
|
4
|
+
option :integer do |value|
|
5
|
+
if value.strip !~ /^[-\d]/
|
6
|
+
raise ::ArgumentError, "Not an integer: #{value.inspect}"
|
7
|
+
else
|
8
|
+
value.to_i
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe TinyConfig do
|
14
|
+
let(:cfg) { ValidatingConfig.new }
|
15
|
+
|
16
|
+
it 'calls provided block to transform and/or validate value' do
|
17
|
+
cfg.configure do
|
18
|
+
integer '23'
|
19
|
+
end
|
20
|
+
expect { cfg.integer == 23 }
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'can raise exception from the validation block' do
|
24
|
+
expect do
|
25
|
+
rescuing do
|
26
|
+
cfg.configure do
|
27
|
+
integer 'dupa'
|
28
|
+
end
|
29
|
+
end.is_a?(ArgumentError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/tinyconfig.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tinyconfig/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "tinyconfig"
|
8
|
+
spec.version = TinyConfig::VERSION
|
9
|
+
spec.authors = ["Maciej Pasternacki"]
|
10
|
+
spec.email = ["maciej@3ofcoins.net"]
|
11
|
+
spec.description = "Library for defining Ruby-based configuration files"
|
12
|
+
spec.summary = "Library for defining Ruby-based configuration files"
|
13
|
+
spec.homepage = "https://github.com/3ofcoins/tinyconfig/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "minitest"
|
23
|
+
spec.add_development_dependency "mocha"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "simplecov"
|
26
|
+
spec.add_development_dependency "thor", "~> 0.18.1"
|
27
|
+
spec.add_development_dependency "wrong", ">= 0.7.0"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tinyconfig
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maciej Pasternacki
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mocha
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: thor
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.18.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.18.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: wrong
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.7.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.7.0
|
111
|
+
description: Library for defining Ruby-based configuration files
|
112
|
+
email:
|
113
|
+
- maciej@3ofcoins.net
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- .gitignore
|
119
|
+
- .travis.yml
|
120
|
+
- CHANGELOG.md
|
121
|
+
- CONTRIBUTING.md
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE
|
124
|
+
- README.md
|
125
|
+
- Thorfile
|
126
|
+
- example/config-invalid.rb
|
127
|
+
- example/config1.rb
|
128
|
+
- example/config2.rb
|
129
|
+
- example/config3.rb
|
130
|
+
- example/hello.rb
|
131
|
+
- example/lambda.rb
|
132
|
+
- lib/tinyconfig.rb
|
133
|
+
- lib/tinyconfig/version.rb
|
134
|
+
- spec/fixtures/basic.rb
|
135
|
+
- spec/fixtures/basic_nested.rb
|
136
|
+
- spec/fixtures/directory.rb
|
137
|
+
- spec/fixtures/directory/config1.rb
|
138
|
+
- spec/fixtures/directory/config2.rb
|
139
|
+
- spec/fixtures/glob1.rb
|
140
|
+
- spec/fixtures/glob2.rb
|
141
|
+
- spec/spec_helper.rb
|
142
|
+
- spec/tinyconfig/version_spec.rb
|
143
|
+
- spec/tinyconfig_lambda_spec.rb
|
144
|
+
- spec/tinyconfig_spec.rb
|
145
|
+
- spec/tinyconfig_validation_spec.rb
|
146
|
+
- tinyconfig.gemspec
|
147
|
+
homepage: https://github.com/3ofcoins/tinyconfig/
|
148
|
+
licenses:
|
149
|
+
- MIT
|
150
|
+
metadata: {}
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ! '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ! '>='
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
requirements: []
|
166
|
+
rubyforge_project:
|
167
|
+
rubygems_version: 2.0.5
|
168
|
+
signing_key:
|
169
|
+
specification_version: 4
|
170
|
+
summary: Library for defining Ruby-based configuration files
|
171
|
+
test_files:
|
172
|
+
- spec/fixtures/basic.rb
|
173
|
+
- spec/fixtures/basic_nested.rb
|
174
|
+
- spec/fixtures/directory.rb
|
175
|
+
- spec/fixtures/directory/config1.rb
|
176
|
+
- spec/fixtures/directory/config2.rb
|
177
|
+
- spec/fixtures/glob1.rb
|
178
|
+
- spec/fixtures/glob2.rb
|
179
|
+
- spec/spec_helper.rb
|
180
|
+
- spec/tinyconfig/version_spec.rb
|
181
|
+
- spec/tinyconfig_lambda_spec.rb
|
182
|
+
- spec/tinyconfig_spec.rb
|
183
|
+
- spec/tinyconfig_validation_spec.rb
|