configurator2 0.1.2
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.
- data/.rspec +3 -0
- data/Guardfile +24 -0
- data/README.md +100 -0
- data/Rakefile +14 -0
- data/VERSION +1 -0
- data/configurator2.gemspec +45 -0
- data/lib/configurator/configuration.rb +59 -0
- data/lib/configurator/option.rb +16 -0
- data/lib/configurator.rb +18 -0
- data/spec/lib/configurator_spec.rb +141 -0
- data/spec/spec_helper.rb +1 -0
- metadata +56 -0
data/.rspec
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2 do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
+
|
17
|
+
# Capybara request specs
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
19
|
+
|
20
|
+
# Turnip features and steps
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
23
|
+
end
|
24
|
+
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# Configurator
|
2
|
+
## Add simple configuration to any Ruby class
|
3
|
+
|
4
|
+
### Installation
|
5
|
+
1. Add `gem 'configurator2'` to your Gemfile
|
6
|
+
2. Run `bundle`
|
7
|
+
3. Profit
|
8
|
+
|
9
|
+
### Usage
|
10
|
+
|
11
|
+
#### Mix into any Ruby class and add options
|
12
|
+
```ruby
|
13
|
+
class Application
|
14
|
+
extend Configurator
|
15
|
+
option :api_url, "https://www.myapp.com/api/v1"
|
16
|
+
options :format, :mode, :whatevs
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
This will add `Application.config.api_url`, which will be overridable but default
|
21
|
+
to `https://www.myapp.com/api/v1`. It also adds a number of options without
|
22
|
+
defaults, namely `format`, `mode`, and `whatevs`.
|
23
|
+
|
24
|
+
Every call to `option` or `options` adds getters and setters for these options,
|
25
|
+
but you can also use the alternate syntax by ommitting the equals sign when setting
|
26
|
+
an option.
|
27
|
+
|
28
|
+
#### Configure your class
|
29
|
+
Configurator supports three different interfaces and two setter methods:
|
30
|
+
|
31
|
+
##### Block configuration with implicit configuration object
|
32
|
+
```ruby
|
33
|
+
Application.config do
|
34
|
+
api_url "https://www.some.other.app/api/v2"
|
35
|
+
format :json
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
##### Block configuration with passed configuration object
|
40
|
+
```ruby
|
41
|
+
Application.config do |config|
|
42
|
+
config.api_url = "https://www.some.other.app/api/v2"
|
43
|
+
config.format = :json
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
##### Direct configuration
|
48
|
+
```ruby
|
49
|
+
Application.config.api_url = "https://www.some.other.app/api/v2"
|
50
|
+
Application.config.format = :json
|
51
|
+
```
|
52
|
+
|
53
|
+
OR omit the equals operators:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
Application.config.mode :production
|
57
|
+
```
|
58
|
+
|
59
|
+
#### Sub-configurations
|
60
|
+
Adding a sub-configuration is simple, too, like so:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
class Application
|
64
|
+
extend Configurator
|
65
|
+
option :smtp_server do
|
66
|
+
options :host, :port, :password, :username
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
Now, you can refer to an Application's smtp_server configuration like so:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
Application.config.smtp_server.host
|
75
|
+
Application.config.smtp_server.port
|
76
|
+
# etc
|
77
|
+
```
|
78
|
+
|
79
|
+
You can also configure a group of configuration options as a hash:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
Application.config.smtp_server = {
|
83
|
+
host: "smtp.host.com",
|
84
|
+
port: "3306",
|
85
|
+
username: "user",
|
86
|
+
password: "pass"
|
87
|
+
}
|
88
|
+
```
|
89
|
+
|
90
|
+
#### Observe your users' configuration choices later
|
91
|
+
|
92
|
+
Just refer to a class or module's configuration setting later, pretty simply:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
if Application.config.smtp_server.host
|
96
|
+
Mailer.send_email_with_options(Application.config.smtp_server)
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
100
|
+
Or whatever.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gemspec|
|
6
|
+
gemspec.name = "configurator2"
|
7
|
+
gemspec.summary = "A mixin to add a .config method and options with defaults to any library"
|
8
|
+
gemspec.description = %{}
|
9
|
+
gemspec.email = "flip@getplinq.com"
|
10
|
+
gemspec.homepage = "http://github.com/Plinq/configurator"
|
11
|
+
gemspec.authors = ["Flip Sasser"]
|
12
|
+
end
|
13
|
+
rescue LoadError
|
14
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.2
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "configurator2"
|
8
|
+
s.version = "0.1.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Flip Sasser"]
|
12
|
+
s.date = "2013-01-02"
|
13
|
+
s.description = ""
|
14
|
+
s.email = "flip@getplinq.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".rspec",
|
20
|
+
"Guardfile",
|
21
|
+
"README.md",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"configurator2.gemspec",
|
25
|
+
"lib/configurator.rb",
|
26
|
+
"lib/configurator/configuration.rb",
|
27
|
+
"lib/configurator/option.rb",
|
28
|
+
"spec/lib/configurator_spec.rb",
|
29
|
+
"spec/spec_helper.rb"
|
30
|
+
]
|
31
|
+
s.homepage = "http://github.com/Plinq/configurator"
|
32
|
+
s.require_paths = ["lib"]
|
33
|
+
s.rubygems_version = "1.8.24"
|
34
|
+
s.summary = "A mixin to add a .config method and options with defaults to any library"
|
35
|
+
|
36
|
+
if s.respond_to? :specification_version then
|
37
|
+
s.specification_version = 3
|
38
|
+
|
39
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
40
|
+
else
|
41
|
+
end
|
42
|
+
else
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'configurator/option'
|
2
|
+
|
3
|
+
module Configurator
|
4
|
+
class Configuration < Hash
|
5
|
+
include Option
|
6
|
+
|
7
|
+
def add_option(name, default, &block)
|
8
|
+
defaults[name.to_sym] = default || block
|
9
|
+
end
|
10
|
+
|
11
|
+
def config
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def defaults
|
16
|
+
@defaults ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(options = {})
|
20
|
+
options.each do |key, value|
|
21
|
+
set(key, value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def get(name)
|
26
|
+
name = name.to_sym
|
27
|
+
value = self.key?(name) ? self[name] : defaults[name]
|
28
|
+
if value.respond_to? :call
|
29
|
+
value = value.call
|
30
|
+
end
|
31
|
+
value
|
32
|
+
end
|
33
|
+
|
34
|
+
def set(name, value, &block)
|
35
|
+
name = name.to_sym
|
36
|
+
if block_given?
|
37
|
+
self[name] = block
|
38
|
+
elsif value.is_a?(Hash)
|
39
|
+
self[name] = defaults[name] || self.class.new
|
40
|
+
value.each do |key, value_two|
|
41
|
+
self[name].send("#{key}=", value_two)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
self[name] = value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def method_missing(method, *args, &block)
|
50
|
+
method_name = method.to_s
|
51
|
+
setter = method_name.chomp!('=') || !args.empty? || block_given?
|
52
|
+
if setter
|
53
|
+
set(method_name, args.first, &block)
|
54
|
+
else
|
55
|
+
get(method)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Configurator
|
2
|
+
module Option
|
3
|
+
def option(name, default = nil, &block)
|
4
|
+
config.add_option(name, block_given? ? Configuration.new : default)
|
5
|
+
if block_given?
|
6
|
+
config.get(name).instance_exec(config.get(name), &block)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
private :option
|
10
|
+
|
11
|
+
def options(*names)
|
12
|
+
names.each {|name| option(name) }
|
13
|
+
end
|
14
|
+
private :options
|
15
|
+
end
|
16
|
+
end
|
data/lib/configurator.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'configurator/option'
|
2
|
+
|
3
|
+
module Configurator
|
4
|
+
autoload :Configuration, 'configurator/configuration'
|
5
|
+
include Option
|
6
|
+
|
7
|
+
def self.extended(base)
|
8
|
+
base.class_eval { remove_instance_variable(:@configuration) if defined? @configuration }
|
9
|
+
end
|
10
|
+
|
11
|
+
def config(&block)
|
12
|
+
@configuration ||= Configuration.new
|
13
|
+
if block_given?
|
14
|
+
@configuration.instance_exec(@configuration, &block)
|
15
|
+
end
|
16
|
+
@configuration
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'configurator'
|
2
|
+
|
3
|
+
describe Configurator do
|
4
|
+
it "extends objects without exploding" do
|
5
|
+
lambda {
|
6
|
+
class FooBar
|
7
|
+
extend Configurator
|
8
|
+
end
|
9
|
+
}.should_not raise_error
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "mixed into a class" do
|
13
|
+
before do
|
14
|
+
class TestClass
|
15
|
+
extend Configurator
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "defines a `config` method" do
|
20
|
+
TestClass.should respond_to(:config)
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "adds a `config` method that" do
|
24
|
+
it "accepts a block" do
|
25
|
+
lambda {
|
26
|
+
TestClass.config { inspect }
|
27
|
+
}.should_not raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it "executes the block in the context of the configured class' new configuration instance" do
|
31
|
+
TestClass.config.should_receive(:puts).and_return(nil)
|
32
|
+
TestClass.config { puts "ohai" }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "adds an `option` method that" do
|
37
|
+
it "allows developers to declare class-level options" do
|
38
|
+
TestClass.send(:option, :do_something)
|
39
|
+
TestClass.config.defaults.key?(:do_something).should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "allows developers to declare defaults on options" do
|
43
|
+
TestClass.send(:option, :do_something, true)
|
44
|
+
TestClass.config.defaults[:do_something].should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "defines getter methods on the config class method" do
|
48
|
+
TestClass.send(:option, :do_something)
|
49
|
+
TestClass.config.do_something.should be_nil
|
50
|
+
end
|
51
|
+
|
52
|
+
it "defines setter methods on the class" do
|
53
|
+
TestClass.send(:option, :do_something)
|
54
|
+
lambda { TestClass.config.do_something = "ohai" }.should_not raise_error
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "that adds a class-level accessor that" do
|
58
|
+
it "returns default values when a developer has not overriden it" do
|
59
|
+
TestClass.send(:option, :do_something, "now!")
|
60
|
+
TestClass.config.do_something.should == "now!"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns overriden values when a developer has overriden them" do
|
64
|
+
TestClass.send(:option, :do_something, "now!")
|
65
|
+
TestClass.config do
|
66
|
+
do_something "later..."
|
67
|
+
end
|
68
|
+
TestClass.config.do_something.should == "later..."
|
69
|
+
end
|
70
|
+
|
71
|
+
it "uses a lambda to defer processing until it's called" do
|
72
|
+
TestClass.send(:option, :payment_method, lambda {
|
73
|
+
defined?(Paypal) ? :paypal : :plinq
|
74
|
+
})
|
75
|
+
TestClass.config.payment_method.should == :plinq
|
76
|
+
end
|
77
|
+
|
78
|
+
it "returns nil when a value is explicitly nil" do
|
79
|
+
TestClass.send(:option, :current_user_method, :current_user)
|
80
|
+
TestClass.config.current_user_method.should == :current_user
|
81
|
+
#TestClass.config.current_user_method = nil
|
82
|
+
TestClass.config do
|
83
|
+
current_user_method nil
|
84
|
+
end
|
85
|
+
TestClass.config.current_user_method.should be_nil
|
86
|
+
end
|
87
|
+
it "accepts a setter format" do
|
88
|
+
TestClass.send(:option, :do_something, "now!")
|
89
|
+
TestClass.config.do_something = "later..."
|
90
|
+
TestClass.config.do_something.should == "later..."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#option with sub-options' do
|
96
|
+
before :each do
|
97
|
+
TestClass.send(:option, :advanced_options) do
|
98
|
+
option :bitrate, 1024
|
99
|
+
option :fps, 30
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it "accepts a block that creates a sub-configuration" do
|
104
|
+
TestClass.config.advanced_options.bitrate.should == 1024
|
105
|
+
TestClass.config.advanced_options.fps.should == 30
|
106
|
+
end
|
107
|
+
|
108
|
+
it "accepts a hash that for a sub-configuration" do
|
109
|
+
TestClass.config.advanced_options = {
|
110
|
+
bitrate: 2000,
|
111
|
+
fps: 60
|
112
|
+
}
|
113
|
+
TestClass.config.advanced_options.bitrate.should == 2000
|
114
|
+
TestClass.config.advanced_options.fps.should == 60
|
115
|
+
end
|
116
|
+
|
117
|
+
it "doesn't overwrite a defaults hash if you set one value but not the other" do
|
118
|
+
TestClass.config.advanced_options = {bitrate: 2000}
|
119
|
+
TestClass.config.advanced_options.bitrate.should == 2000
|
120
|
+
TestClass.config.advanced_options.fps.should == 30
|
121
|
+
end
|
122
|
+
|
123
|
+
it "accepts even MORE options below the other ones, yo" do
|
124
|
+
TestClass.send(:option, :sub) do
|
125
|
+
option(:name, :face)
|
126
|
+
option(:sub) do
|
127
|
+
option(:name, :fiz)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
TestClass.config.sub.name.should == :face
|
131
|
+
TestClass.config.sub.sub.name.should == :fiz
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it "adds an `options` method that defines many options with default nil values" do
|
136
|
+
TestClass.should_receive(:option).once.with(:host)
|
137
|
+
TestClass.should_receive(:option).once.with(:api_key)
|
138
|
+
TestClass.send :options, :host, :api_key
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: configurator2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Flip Sasser
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-02 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ''
|
15
|
+
email: flip@getplinq.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- README.md
|
20
|
+
files:
|
21
|
+
- .rspec
|
22
|
+
- Guardfile
|
23
|
+
- README.md
|
24
|
+
- Rakefile
|
25
|
+
- VERSION
|
26
|
+
- configurator2.gemspec
|
27
|
+
- lib/configurator.rb
|
28
|
+
- lib/configurator/configuration.rb
|
29
|
+
- lib/configurator/option.rb
|
30
|
+
- spec/lib/configurator_spec.rb
|
31
|
+
- spec/spec_helper.rb
|
32
|
+
homepage: http://github.com/Plinq/configurator
|
33
|
+
licenses: []
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.8.24
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: A mixin to add a .config method and options with defaults to any library
|
56
|
+
test_files: []
|