appsent 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +5 -5
- data/Rakefile +11 -1
- data/features/README.md +5 -5
- data/features/array_with_nested_params.feature +5 -5
- data/features/full_example.feature +13 -13
- data/features/simple_usage.feature +2 -2
- data/features/with_nested_params.feature +3 -3
- data/lib/appsent.rb +2 -2
- data/lib/appsent/config_file.rb +6 -5
- data/lib/appsent/config_value.rb +28 -6
- data/lib/appsent/version.rb +1 -1
- data/spec/{internal_api → appsent}/config_file_spec.rb +71 -1
- data/spec/appsent/config_value_spec.rb +234 -0
- data/spec/appsent_spec.rb +140 -0
- data/spec/old_api/dsl_spec.rb +135 -0
- data/spec/old_api/internal_api/config_file_spec.rb +222 -0
- data/spec/{internal_api → old_api/internal_api}/config_value_spec.rb +65 -17
- metadata +22 -19
- data/spec/dsl_spec.rb +0 -72
data/README.md
CHANGED
@@ -20,13 +20,13 @@ Initialize application with config requirements:
|
|
20
20
|
|
21
21
|
# Hash-based config:
|
22
22
|
mongo_db_config do
|
23
|
-
host
|
24
|
-
port
|
25
|
-
pool_size
|
26
|
-
timeout
|
23
|
+
host String, 'Host to connect to MongoDB' => 'localhost'
|
24
|
+
port Fixnum, 'Port to connect to MongoDB'
|
25
|
+
pool_size Fixnum
|
26
|
+
timeout Fixnum
|
27
27
|
end
|
28
28
|
|
29
|
-
exception_notification_recipients
|
29
|
+
exception_notification_recipients Array
|
30
30
|
|
31
31
|
end
|
32
32
|
|
data/Rakefile
CHANGED
@@ -6,7 +6,17 @@ Bundler::GemHelper.install_tasks
|
|
6
6
|
|
7
7
|
task :default => [:spec, :features]
|
8
8
|
|
9
|
-
RSpec::Core::RakeTask.new(:spec)
|
9
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
10
|
+
t.rspec_opts='--tag ~wip'
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :spec do
|
14
|
+
|
15
|
+
RSpec::Core::RakeTask.new(:wip) do |t|
|
16
|
+
t.rspec_opts='--tag wip'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
10
20
|
|
11
21
|
Cucumber::Rake::Task.new(:features) do |t|
|
12
22
|
t.profile = 'default'
|
data/features/README.md
CHANGED
@@ -20,13 +20,13 @@ Initialize application with config requirements:
|
|
20
20
|
|
21
21
|
# Hash-based config:
|
22
22
|
mongo_db_config do
|
23
|
-
host
|
24
|
-
port
|
25
|
-
pool_size
|
26
|
-
timeout
|
23
|
+
host String, 'Host to connect to MongoDB' => 'localhost'
|
24
|
+
port Fixnum, 'Port to connect to MongoDB'
|
25
|
+
pool_size Fixnum
|
26
|
+
timeout Fixnum
|
27
27
|
end
|
28
28
|
|
29
|
-
exception_notification_recipients
|
29
|
+
exception_notification_recipients Array
|
30
30
|
|
31
31
|
end
|
32
32
|
|
@@ -9,12 +9,12 @@ Feature: Array with nested params
|
|
9
9
|
AppSent.init :path => 'config', :env => 'production' do
|
10
10
|
|
11
11
|
mongodb do
|
12
|
-
host
|
13
|
-
port
|
12
|
+
host String, 'Host to connect to MongoDB' => 'localhost'
|
13
|
+
port Fixnum, 'MongoDB port' => 27017
|
14
14
|
|
15
|
-
slaves
|
16
|
-
host
|
17
|
-
port
|
15
|
+
slaves Array do
|
16
|
+
host String, 'mongo slave host' => 'host.com'
|
17
|
+
port Fixnum, 'mongo slave port' => 27018
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -9,20 +9,20 @@ Feature: Complex usage
|
|
9
9
|
system_config do
|
10
10
|
|
11
11
|
google_analytics do
|
12
|
-
code
|
13
|
-
multiple_domains
|
14
|
-
domain
|
12
|
+
code String, 'Enter your google analytics code here' => 'UA-12345678-1'
|
13
|
+
multiple_domains String, 'has multiple domains?'
|
14
|
+
domain String, 'your domain' => 'example.com'
|
15
15
|
end
|
16
16
|
|
17
|
-
system_email
|
17
|
+
system_email String, :example => 'admin@example.com'
|
18
18
|
|
19
19
|
end
|
20
20
|
|
21
21
|
mongodb do
|
22
|
-
host
|
23
|
-
port
|
24
|
-
pool_size
|
25
|
-
timeout
|
22
|
+
host String, 'Host to connect to MongoDB' => 'localhost'
|
23
|
+
port Fixnum, 'MongoDB port' => 27017
|
24
|
+
pool_size Fixnum
|
25
|
+
timeout Fixnum
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
@@ -31,14 +31,14 @@ Feature: Complex usage
|
|
31
31
|
"""
|
32
32
|
# TODO:
|
33
33
|
#recaptcha :skip_env => true do
|
34
|
-
# recaptcha_public_key
|
35
|
-
# recaptcha_private_key
|
34
|
+
# recaptcha_public_key String, 'Recaptcha public key'
|
35
|
+
# recaptcha_private_key String, 'Recaptcha private key'
|
36
36
|
#end
|
37
|
-
#notification_recipients
|
37
|
+
#notification_recipients Array, :skip_env => true, :each_value => TODO
|
38
38
|
#
|
39
39
|
# slaves :type => Array do
|
40
|
-
# host
|
41
|
-
# port
|
40
|
+
# host String, 'mongo slave host' => 'host.com'
|
41
|
+
# port Fixnum, 'mongo slave port' => 27018
|
42
42
|
# end
|
43
43
|
|
44
44
|
Scenario: All config present and have right values
|
@@ -7,8 +7,8 @@ Feature: Simple usage example
|
|
7
7
|
|
8
8
|
AppSent.init :path => 'config', :env => 'production' do
|
9
9
|
mongodb do
|
10
|
-
host
|
11
|
-
port
|
10
|
+
host String, 'Host to connect to MongoDB' => 'localhost'
|
11
|
+
port Fixnum, 'MongoDB port' => 27017
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -9,9 +9,9 @@ Feature: Usage with nested params example
|
|
9
9
|
system_config do
|
10
10
|
|
11
11
|
google_analytics do
|
12
|
-
code
|
13
|
-
multiple_domains
|
14
|
-
domain
|
12
|
+
code String, 'Enter your google analytics code here' => 'UA-12345678-1'
|
13
|
+
multiple_domains String, 'has multiple domains?'
|
14
|
+
domain String, 'your domain' => 'example.com'
|
15
15
|
end
|
16
16
|
|
17
17
|
end
|
data/lib/appsent.rb
CHANGED
@@ -63,10 +63,10 @@ class AppSent
|
|
63
63
|
|
64
64
|
private
|
65
65
|
|
66
|
-
def method_missing config, args
|
66
|
+
def method_missing config, *args, &block
|
67
67
|
config = config.to_s
|
68
68
|
@@config_files << config
|
69
|
-
@configs << ConfigFile.new(@@config_path,config,@@environment
|
69
|
+
@configs << ConfigFile.new(@@config_path,config,@@environment,*args,&block)
|
70
70
|
end
|
71
71
|
|
72
72
|
end
|
data/lib/appsent/config_file.rb
CHANGED
@@ -6,10 +6,11 @@ class AppSent
|
|
6
6
|
ENVIRONMENT_NOT_FOUND_ERROR_MSG = "config file '%s' has no '%s' environment"
|
7
7
|
WRONG_CONFIG_ERROR_MSG = "wrong config file '%s':\n"
|
8
8
|
|
9
|
-
def initialize config_dir, config_file_name, environment,
|
10
|
-
@config_dir, @config_file_name, @environment, @
|
9
|
+
def initialize config_dir, config_file_name, environment, *opts, &block
|
10
|
+
@config_dir, @config_file_name, @environment, @block = config_dir, config_file_name, (environment && environment.to_sym), block
|
11
11
|
|
12
|
-
@type
|
12
|
+
@type = opts.empty? ? Hash : opts.first
|
13
|
+
@type = @type[:type] if @type.is_a?(Hash)
|
13
14
|
raise "params #{@type} and block given" if block_given? and not @type==Hash
|
14
15
|
@path_to_config = File.join(@config_dir,@config_file_name+'.yml')
|
15
16
|
@self_error_msg = ''
|
@@ -65,8 +66,8 @@ class AppSent
|
|
65
66
|
@path_to_config.gsub(Dir.pwd+File::SEPARATOR,'')
|
66
67
|
end
|
67
68
|
|
68
|
-
def method_missing option,
|
69
|
-
self.options << ConfigValue.new(option.to_s,
|
69
|
+
def method_missing option, *args, &block
|
70
|
+
self.options << ConfigValue.new(option.to_s, @data[option.to_sym], *args, &block)
|
70
71
|
end
|
71
72
|
|
72
73
|
end
|
data/lib/appsent/config_value.rb
CHANGED
@@ -10,8 +10,31 @@ class AppSent
|
|
10
10
|
WRONG_CHILD_OPTIONS_MSG = "wrong nested parameters"
|
11
11
|
|
12
12
|
# data => it's an actual data of parameter
|
13
|
-
def initialize parameter,
|
14
|
-
@parameter, @
|
13
|
+
def initialize parameter, data, *opts, &block
|
14
|
+
@parameter, @data = (parameter and parameter.to_sym), data
|
15
|
+
|
16
|
+
if opts.size==1
|
17
|
+
opts = opts.first
|
18
|
+
begin
|
19
|
+
%w( type desc example ).each do |deprecated_key|
|
20
|
+
warn("AppSent DEPRECATION WARNING: :#{deprecated_key} is deprecated and will be removed in a future major release, go to online documentation and see how to define config values") if opts.has_key?(deprecated_key.to_sym)
|
21
|
+
end
|
22
|
+
|
23
|
+
@data_type, @description, @example = opts[:type], opts[:desc], opts[:example]
|
24
|
+
rescue NoMethodError# opts is a [String]
|
25
|
+
@data_type = opts
|
26
|
+
end
|
27
|
+
else
|
28
|
+
@data_type = opts.delete_at(0)
|
29
|
+
description_and_example = opts.delete_at(0)
|
30
|
+
case description_and_example
|
31
|
+
when String
|
32
|
+
@description = description_and_example
|
33
|
+
when Hash
|
34
|
+
@description = description_and_example.keys.first
|
35
|
+
@example = description_and_example.values.first
|
36
|
+
end
|
37
|
+
end
|
15
38
|
|
16
39
|
@data_type ||= Hash
|
17
40
|
raise WRONG_DATA_TYPE_PASSED_MSG unless @data_type.is_a?(Class)
|
@@ -83,13 +106,12 @@ class AppSent
|
|
83
106
|
|
84
107
|
private
|
85
108
|
|
86
|
-
def method_missing option, opts
|
109
|
+
def method_missing option, *opts, &block
|
87
110
|
self.child_options << self.class.new(
|
88
111
|
option.to_s,
|
89
|
-
opts[:type],
|
90
112
|
data[option.to_sym],
|
91
|
-
opts
|
92
|
-
|
113
|
+
*opts,
|
114
|
+
&block
|
93
115
|
)
|
94
116
|
self.child_options.last.nesting+=(self.nesting+1)
|
95
117
|
end
|
data/lib/appsent/version.rb
CHANGED
@@ -30,6 +30,76 @@ describe AppSent::ConfigFile do
|
|
30
30
|
it { subject.new(*params).should respond_to(method)}
|
31
31
|
end
|
32
32
|
|
33
|
+
context "should send right variables to AppSent::ConfigValue" do
|
34
|
+
|
35
|
+
let(:mock_config_value) { mock(AppSent::ConfigValue, :valid? => true) }
|
36
|
+
|
37
|
+
it "in a simple case" do
|
38
|
+
AppSent::ConfigValue.should_receive(:new).once.with(
|
39
|
+
'username',
|
40
|
+
'user', # data
|
41
|
+
String
|
42
|
+
).and_return(mock_config_value)
|
43
|
+
|
44
|
+
AppSent.init(:path => '../fixtures', :env => 'test') do
|
45
|
+
database do
|
46
|
+
username String
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "with a &block" do
|
52
|
+
block = lambda {}
|
53
|
+
AppSent::ConfigValue.should_receive(:new).once.with(
|
54
|
+
'username',
|
55
|
+
'user', # data
|
56
|
+
String,
|
57
|
+
&block
|
58
|
+
).and_return(mock_config_value)
|
59
|
+
|
60
|
+
AppSent.init(:path => '../fixtures', :env => 'test') do
|
61
|
+
database do
|
62
|
+
username String, &block
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "with description" do
|
68
|
+
AppSent::ConfigValue.should_receive(:new).once.with(
|
69
|
+
'username',
|
70
|
+
'user', # data
|
71
|
+
String,
|
72
|
+
'description'
|
73
|
+
).and_return(mock_config_value)
|
74
|
+
|
75
|
+
AppSent.init(:path => '../fixtures', :env => 'test') do
|
76
|
+
database do
|
77
|
+
username String, 'description'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "with description and example" do
|
83
|
+
AppSent::ConfigValue.should_receive(:new).once.with(
|
84
|
+
'username',
|
85
|
+
'user', # data
|
86
|
+
String,
|
87
|
+
'description' => 'user'
|
88
|
+
).and_return(mock_config_value)
|
89
|
+
|
90
|
+
AppSent.init(:path => '../fixtures', :env => 'test') do
|
91
|
+
database do
|
92
|
+
username String, 'description' => 'user'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
after :each do
|
100
|
+
AppSent.send :remove_const, 'DATABASE' if AppSent.const_defined?("DATABASE")
|
101
|
+
end
|
102
|
+
|
33
103
|
end
|
34
104
|
|
35
105
|
context "#valid?" do
|
@@ -49,7 +119,7 @@ describe AppSent::ConfigFile do
|
|
49
119
|
|
50
120
|
it "if config exists and environment presence(with values)" do
|
51
121
|
values_block = lambda {
|
52
|
-
value
|
122
|
+
value String
|
53
123
|
}
|
54
124
|
YAML.should_receive(:load_file).once.with(fake_config_filename).and_return('environment' => {:value=>'100500'})
|
55
125
|
subject.new(*params,&values_block).should be_valid
|
@@ -0,0 +1,234 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AppSent::ConfigValue do
|
4
|
+
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@params = {
|
9
|
+
'name' => 'param_name',
|
10
|
+
'type' => String,
|
11
|
+
'value' => 'some string',
|
12
|
+
'desc' => 'description string',
|
13
|
+
'example' => 'example'
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:params) do
|
18
|
+
result = [
|
19
|
+
@params['name'],
|
20
|
+
@params['value'],
|
21
|
+
@params['type']
|
22
|
+
]
|
23
|
+
if @params.has_key?('example')
|
24
|
+
result << { @params['desc'] => @params['example'] }
|
25
|
+
else
|
26
|
+
result << @params['desc']
|
27
|
+
end
|
28
|
+
result
|
29
|
+
end
|
30
|
+
|
31
|
+
context ".new" do
|
32
|
+
|
33
|
+
%w(valid? child_options error_message).each do |method|
|
34
|
+
it { subject.new(*params).should respond_to(method)}
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should raise exception if unsupported type passed" do
|
38
|
+
@params['type'] = 'asd'
|
39
|
+
expect { subject.new(*params) }.to raise_exception(/data type should be ruby class!/)
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with &block given" do
|
43
|
+
|
44
|
+
let(:block) do
|
45
|
+
lambda { value String }
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should not raise exception if data type is Array" do
|
49
|
+
@params['type'] = Array
|
50
|
+
expect { subject.new(*params,&block) }.to_not raise_exception(/params Array and block given/)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not raise exception if data type is Hash" do
|
54
|
+
@params['type'] = Hash
|
55
|
+
expect { subject.new(*params,&block) }.to_not raise_exception(/params Hash and block given/)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should raise exception if data type is not Hash" do
|
59
|
+
@params['type'] = Fixnum
|
60
|
+
expect { subject.new(*params,&block) }.to raise_exception(/params Fixnum and block given/)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
context "#valid?" do
|
68
|
+
|
69
|
+
context "should return false" do
|
70
|
+
|
71
|
+
it "if entry does not presence in config file" do
|
72
|
+
@params['value']=nil
|
73
|
+
subject.new(*params).should_not be_valid
|
74
|
+
end
|
75
|
+
|
76
|
+
it "if data in config file has wrong type" do
|
77
|
+
@params['type']=Array
|
78
|
+
@params['value']='string'
|
79
|
+
subject.new(*params).should_not be_valid
|
80
|
+
end
|
81
|
+
|
82
|
+
it "if child value is not valid" do
|
83
|
+
@params['type']=Hash
|
84
|
+
@params['value']={:value => 100500}
|
85
|
+
values_block = lambda {
|
86
|
+
value String
|
87
|
+
}
|
88
|
+
subject.new(*params,&values_block).should_not be_valid
|
89
|
+
end
|
90
|
+
|
91
|
+
context "with type => Array", :wip => true do
|
92
|
+
|
93
|
+
it "if actual data is not array" do
|
94
|
+
@params['type']=Array
|
95
|
+
@params['value']=123
|
96
|
+
subject.new(*params).should_not be_valid
|
97
|
+
end
|
98
|
+
|
99
|
+
it "if actual data is an array of wrong hashes" do
|
100
|
+
@params['type']=Array
|
101
|
+
@params['value']=[1,2]
|
102
|
+
values_block = lambda {
|
103
|
+
value1 String
|
104
|
+
value2 Fixnum
|
105
|
+
}
|
106
|
+
subject.new(*params,&values_block).should_not be_valid
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
context "should return true" do
|
114
|
+
|
115
|
+
it "if entry presence and has right type" do
|
116
|
+
subject.new(*params).should be_valid
|
117
|
+
end
|
118
|
+
|
119
|
+
it "if valid itself and child values valid too" do
|
120
|
+
@params['type']=Hash
|
121
|
+
@params['value']={'value' => 'some data'}
|
122
|
+
values_block = lambda {
|
123
|
+
value String
|
124
|
+
}
|
125
|
+
subject.new(*params,&values_block).should be_valid
|
126
|
+
end
|
127
|
+
|
128
|
+
context "with type => Array", :wip => true do
|
129
|
+
|
130
|
+
it "if actual data is an array of right hashes" do
|
131
|
+
@params['type']=Array
|
132
|
+
@params['value']=[
|
133
|
+
{'value1' =>'qwe', 'value2' => 123 },
|
134
|
+
{'value1' =>'rty', 'value2' => 456 }
|
135
|
+
]
|
136
|
+
values_block = lambda {
|
137
|
+
value1 String
|
138
|
+
value2 Fixnum
|
139
|
+
}
|
140
|
+
subject.new(*params,&values_block).should be_valid
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
context "#error_message" do
|
150
|
+
|
151
|
+
subject { described_class.new(*params) }
|
152
|
+
|
153
|
+
context "should generate correct error message when no data" do
|
154
|
+
|
155
|
+
it "with full description" do
|
156
|
+
@params['name'] = 'database'
|
157
|
+
@params['value'] = nil
|
158
|
+
@params['type'] = String
|
159
|
+
@params['desc'] = 'Database name'
|
160
|
+
@params['example'] = 'localhost'
|
161
|
+
subject.error_message.should eq(" database: localhost # does not exists(Database name), String")
|
162
|
+
end
|
163
|
+
|
164
|
+
it "without example value" do
|
165
|
+
@params['name'] = 'database'
|
166
|
+
@params['value'] = nil
|
167
|
+
@params['type'] = String
|
168
|
+
@params['desc'] = 'Database name'
|
169
|
+
@params.delete('example')
|
170
|
+
subject.error_message.should eq(" database: # does not exists(Database name), String")
|
171
|
+
end
|
172
|
+
|
173
|
+
it "without description" do
|
174
|
+
@params['name'] = 'database'
|
175
|
+
@params['value'] = nil
|
176
|
+
@params['type'] = String
|
177
|
+
@params.delete('desc')
|
178
|
+
@params['example'] = 'localhost'
|
179
|
+
subject.error_message.should eq(" database: localhost # does not exists, String")
|
180
|
+
end
|
181
|
+
|
182
|
+
it "without example and description" do
|
183
|
+
@params['name'] = 'database'
|
184
|
+
@params['value'] = nil
|
185
|
+
@params['type'] = String
|
186
|
+
@params.delete('desc')
|
187
|
+
@params.delete('example')
|
188
|
+
subject.error_message.should eq(" database: # does not exists, String")
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
context "should generate correct error message when data is of wrong type" do
|
194
|
+
|
195
|
+
it "with full description" do
|
196
|
+
@params['name'] = 'database'
|
197
|
+
@params['value'] = 20
|
198
|
+
@params['type'] = String
|
199
|
+
@params['desc'] = 'Database name'
|
200
|
+
@params['example'] = 'localhost'
|
201
|
+
subject.error_message.should eq(" database: 20 # wrong type,should be String(Database name)")
|
202
|
+
end
|
203
|
+
|
204
|
+
it "without example value" do
|
205
|
+
@params['name'] = 'database'
|
206
|
+
@params['value'] = 20
|
207
|
+
@params['type'] = String
|
208
|
+
@params['desc'] = 'Database name'
|
209
|
+
@params.delete('example')
|
210
|
+
subject.error_message.should eq(" database: 20 # wrong type,should be String(Database name)")
|
211
|
+
end
|
212
|
+
|
213
|
+
it "without description" do
|
214
|
+
@params['name'] = 'database'
|
215
|
+
@params['value'] = 20
|
216
|
+
@params['type'] = String
|
217
|
+
@params.delete('desc')
|
218
|
+
@params['example'] = 'localhost'
|
219
|
+
subject.error_message.should eq(" database: 20 # wrong type,should be String")
|
220
|
+
end
|
221
|
+
|
222
|
+
it "without example and description" do
|
223
|
+
@params['name'] = 'database'
|
224
|
+
@params['value'] = 20
|
225
|
+
@params['type'] = String
|
226
|
+
@params.delete('desc')
|
227
|
+
@params.delete('example')
|
228
|
+
subject.error_message.should eq(" database: 20 # wrong type,should be String")
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
end
|