rails_config 0.3.4 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -1
- data/LICENSE.md +27 -0
- data/README.md +45 -2
- data/lib/rails_config.rb +7 -4
- data/lib/rails_config/engine.rb +5 -0
- data/lib/rails_config/integration/rails.rb +5 -8
- data/lib/rails_config/options.rb +19 -0
- data/lib/rails_config/railtie.rb +9 -0
- data/lib/rails_config/tasks/heroku.rake +7 -0
- data/lib/rails_config/tasks/rails_config_tasks.rake +4 -0
- data/lib/rails_config/version.rb +1 -1
- data/lib/tasks.rb +59 -0
- metadata +99 -50
- data/.bundle/config +0 -2
- data/.gitignore +0 -5
- data/.ruby-gemset +0 -1
- data/Gemfile +0 -5
- data/LICENSE +0 -23
- data/Rakefile +0 -28
- data/autotest/discover.rb +0 -2
- data/init.rb +0 -1
- data/rails_config.gemspec +0 -25
- data/spec/fixtures/bool_override/config1.yml +0 -2
- data/spec/fixtures/bool_override/config2.yml +0 -2
- data/spec/fixtures/custom_types/hash.yml +0 -7
- data/spec/fixtures/deep_merge/config1.yml +0 -28
- data/spec/fixtures/deep_merge/config2.yml +0 -28
- data/spec/fixtures/deep_merge2/config1.yml +0 -3
- data/spec/fixtures/deep_merge2/config2.yml +0 -2
- data/spec/fixtures/development.yml +0 -4
- data/spec/fixtures/empty1.yml +0 -0
- data/spec/fixtures/empty2.yml +0 -0
- data/spec/fixtures/settings.yml +0 -8
- data/spec/fixtures/settings2.yml +0 -1
- data/spec/fixtures/with_erb.yml +0 -4
- data/spec/rails_config_spec.rb +0 -245
- data/spec/sources/yaml_source_spec.rb +0 -69
- data/spec/spec_helper.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83dec17f82e00cff05d9177c29a6c8d8d96abdbf
|
4
|
+
data.tar.gz: 95d36c359a9c8562ed5a41c91e2994902fb0adf5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4e44bc4cdb6845342c36e4a0da4aaa14983e2f4902bdecf82a92e4b5022c88b87baf592cd95bf30a80b2363499b11f1c55fbf7141bee963a7b8348ea173e5da
|
7
|
+
data.tar.gz: 949e524f41cef5212bfdecb6eb16e6cc940e2072f8c2940d07bccc9c31d23f5886ebfb05261e589baca70d3053601a935afaeba2f25308f97fd2b81075ca1d5a
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
+
# 0.4.1
|
2
|
+
|
3
|
+
* fixed compatibility with Rails 4.1 ([#72](https://github.com/railsjedi/rails_config/issues/72))
|
4
|
+
* testing suite verifies compatibility with Rails 3.2, 4.0 and 4.1
|
5
|
+
|
6
|
+
# 0.4.0
|
7
|
+
|
8
|
+
* compatibility with Heroku ([#64](https://github.com/railsjedi/rails_config/issues/64))
|
9
|
+
|
1
10
|
# 0.3.4
|
2
11
|
|
3
12
|
* expose Settings in application.rb, so you don't have to duplicate configuration for each environment file ([#59](https://github.com/railsjedi/rails_config/issues/59))
|
4
|
-
*
|
13
|
+
* adding support for Rails 4.1.0.rc ([#70](https://github.com/railsjedi/rails_config/issues/70))
|
data/LICENSE.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2010-2014 Jacques Crocker, Fred Wu, Piotr Kuczynski
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
23
|
+
|
24
|
+
Third-party materials and licenses:
|
25
|
+
|
26
|
+
* RailsConfig contains Deep Merge (deep_merge.rb) which is governed by the MIT license
|
27
|
+
Copyright (C) 2008 Steve Midgley
|
data/README.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/rails_config.svg)](http://badge.fury.io/rb/rails_config)
|
2
|
+
[![Dependency Status](https://gemnasium.com/railsjedi/rails_config.svg)](https://gemnasium.com/railsjedi/rails_config)
|
3
|
+
|
1
4
|
# RailsConfig
|
2
5
|
|
3
6
|
## Summary
|
@@ -13,13 +16,13 @@ RailsConfig helps you easily manage environment specific Rails settings in an ea
|
|
13
16
|
|
14
17
|
## Compatibility
|
15
18
|
|
16
|
-
* Rails 3.x
|
19
|
+
* Rails 3.x and 4.x
|
17
20
|
* Padrino
|
18
21
|
* Sinatra
|
19
22
|
|
20
23
|
For older versions of Rails and other Ruby apps, use [AppConfig](http://github.com/fredwu/app_config).
|
21
24
|
|
22
|
-
## Installing on Rails 3
|
25
|
+
## Installing on Rails 3 or 4
|
23
26
|
|
24
27
|
Add this to your `Gemfile`:
|
25
28
|
|
@@ -231,6 +234,46 @@ Settings.section.servers[0].name # => yahoo.com
|
|
231
234
|
Settings.section.servers[1].name # => amazon.com
|
232
235
|
```
|
233
236
|
|
237
|
+
## Working with Heroku
|
238
|
+
|
239
|
+
Heroku uses ENV object to store sensitive settings which are like the local files described above. You cannot upload such files to Heroku because it's ephemeral filesystem gets recreated from the git sources on each instance refresh.
|
240
|
+
|
241
|
+
To use rails_config with Heroku just set the `use_env` var to `true` in your `config/initializers/rails_config.rb` file. Eg:
|
242
|
+
|
243
|
+
```ruby
|
244
|
+
RailsConfig.setup do |config|
|
245
|
+
config.const_name = 'AppSettings'
|
246
|
+
config.use_env = true
|
247
|
+
end
|
248
|
+
```
|
249
|
+
|
250
|
+
Now rails_config would read values from the ENV object to the settings. For the example above it would look for keys starting with 'AppSettings'. Eg:
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
ENV['AppSettings.section.size'] = 1
|
254
|
+
ENV['AppSettings.section.server'] = 'google.com'
|
255
|
+
```
|
256
|
+
|
257
|
+
It won't work with arrays, though.
|
258
|
+
|
259
|
+
To upload your local values to Heroku you could ran `bundle exec rake rails_config:heroku`.
|
260
|
+
|
261
|
+
|
262
|
+
## Contributing
|
263
|
+
|
264
|
+
Bootstrap
|
265
|
+
|
266
|
+
```bash
|
267
|
+
$ appraisal install
|
268
|
+
```
|
269
|
+
|
270
|
+
Running the test suite
|
271
|
+
|
272
|
+
```bash
|
273
|
+
$ appraisal rspec
|
274
|
+
```
|
275
|
+
|
276
|
+
|
234
277
|
## Authors
|
235
278
|
|
236
279
|
* [Jacques Crocker](http://github.com/railsjedi)
|
data/lib/rails_config.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
-
require 'rails_config/options'
|
3
|
-
|
4
|
-
require "rails_config/sources/yaml_source"
|
5
2
|
|
3
|
+
require 'rails_config/options'
|
4
|
+
require 'rails_config/version'
|
5
|
+
require 'rails_config/engine'
|
6
|
+
require 'rails_config/sources/yaml_source'
|
6
7
|
require 'rails_config/vendor/deep_merge' unless defined?(DeepMerge)
|
7
8
|
|
8
9
|
module RailsConfig
|
9
10
|
# ensures the setup only gets run once
|
10
11
|
@@_ran_once = false
|
11
12
|
|
12
|
-
mattr_accessor :const_name
|
13
|
+
mattr_accessor :const_name, :use_env
|
13
14
|
@@const_name = "Settings"
|
15
|
+
@@use_env = false
|
14
16
|
|
15
17
|
def self.setup
|
16
18
|
yield self if @@_ran_once == false
|
@@ -28,6 +30,7 @@ module RailsConfig
|
|
28
30
|
end
|
29
31
|
|
30
32
|
config.load!
|
33
|
+
config.load_env! if @@use_env
|
31
34
|
config
|
32
35
|
end
|
33
36
|
|
@@ -3,16 +3,13 @@ module RailsConfig
|
|
3
3
|
module Rails
|
4
4
|
if defined?(::Rails::Railtie)
|
5
5
|
class Railtie < ::Rails::Railtie
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
init_callback = :before_initialize
|
10
|
-
else
|
11
|
-
init_callback = :before_configuration
|
6
|
+
# Load rake tasks (eg. Heroku)
|
7
|
+
rake_tasks do
|
8
|
+
Dir[File.join(File.dirname(__FILE__),'../tasks/*.rake')].each { |f| load f }
|
12
9
|
end
|
13
10
|
|
14
|
-
ActiveSupport.on_load
|
15
|
-
#
|
11
|
+
ActiveSupport.on_load :before_configuration, :yield => true do
|
12
|
+
# Manually load the custom initializer before everything else
|
16
13
|
initializer = ::Rails.root.join("config", "initializers", "rails_config.rb")
|
17
14
|
require initializer if File.exist?(initializer)
|
18
15
|
|
data/lib/rails_config/options.rb
CHANGED
@@ -16,6 +16,23 @@ module RailsConfig
|
|
16
16
|
@config_sources << source
|
17
17
|
end
|
18
18
|
|
19
|
+
def reload_env!
|
20
|
+
return self if ENV.nil? || ENV.empty?
|
21
|
+
conf = Hash.new
|
22
|
+
ENV.each do |key, value|
|
23
|
+
next unless key.to_s.index(RailsConfig.const_name) == 0
|
24
|
+
hash = value
|
25
|
+
key.to_s.split('.').reverse.each do |element|
|
26
|
+
hash = {element => hash}
|
27
|
+
end
|
28
|
+
DeepMerge.deep_merge!(hash, conf, :preserve_unmergeables => false)
|
29
|
+
end
|
30
|
+
|
31
|
+
merge!(conf[RailsConfig.const_name] || {})
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :load_env! :reload_env!
|
35
|
+
|
19
36
|
# look through all our sources and rebuild the configuration
|
20
37
|
def reload!
|
21
38
|
conf = {}
|
@@ -32,6 +49,8 @@ module RailsConfig
|
|
32
49
|
# swap out the contents of the OStruct with a hash (need to recursively convert)
|
33
50
|
marshal_load(__convert(conf).marshal_dump)
|
34
51
|
|
52
|
+
reload_env! if RailsConfig.use_env
|
53
|
+
|
35
54
|
return self
|
36
55
|
end
|
37
56
|
|
data/lib/rails_config/version.rb
CHANGED
data/lib/tasks.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require "bundler"
|
2
|
+
|
3
|
+
module RailsConfig
|
4
|
+
module Tasks
|
5
|
+
class Heroku < Struct.new(:app)
|
6
|
+
def invoke
|
7
|
+
puts 'Setting vars...'
|
8
|
+
heroku_command = "config:set #{vars}"
|
9
|
+
heroku(heroku_command)
|
10
|
+
puts 'Vars set:'
|
11
|
+
puts heroku_command
|
12
|
+
end
|
13
|
+
|
14
|
+
def vars
|
15
|
+
# Load only local options to Heroku
|
16
|
+
RailsConfig.load_and_set_settings(
|
17
|
+
Rails.root.join("config", "settings.local.yml").to_s,
|
18
|
+
Rails.root.join("config", "settings", "#{environment}.local.yml").to_s,
|
19
|
+
Rails.root.join("config", "environments", "#{environment}.local.yml").to_s
|
20
|
+
)
|
21
|
+
|
22
|
+
out = ''
|
23
|
+
dotted_hash = to_dotted_hash Kernel.const_get(RailsConfig.const_name).to_hash, {}, RailsConfig.const_name
|
24
|
+
dotted_hash.each {|key, value| out += " #{key}=#{value} "}
|
25
|
+
out
|
26
|
+
end
|
27
|
+
|
28
|
+
def environment
|
29
|
+
heroku("run 'echo $RAILS_ENV'").chomp[/(\w+)\z/]
|
30
|
+
end
|
31
|
+
|
32
|
+
def heroku(command)
|
33
|
+
with_app = app ? " --app #{app}" : ""
|
34
|
+
`heroku #{command}#{with_app}`
|
35
|
+
end
|
36
|
+
|
37
|
+
def `(command)
|
38
|
+
Bundler.with_clean_env { super }
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_dotted_hash(source, target = {}, namespace = nil)
|
42
|
+
prefix = "#{namespace}." if namespace
|
43
|
+
case source
|
44
|
+
when Hash
|
45
|
+
source.each do |key, value|
|
46
|
+
to_dotted_hash(value, target, "#{prefix}#{key}")
|
47
|
+
end
|
48
|
+
when Array
|
49
|
+
source.each_with_index do |value, index|
|
50
|
+
to_dotted_hash(value, target, "#{prefix}#{index}")
|
51
|
+
end
|
52
|
+
else
|
53
|
+
target[namespace] = source
|
54
|
+
end
|
55
|
+
target
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacques Crocker
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-04-
|
13
|
+
date: 2014-04-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -26,6 +26,20 @@ dependencies:
|
|
26
26
|
- - '>='
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '3.0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: bundler
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '1.5'
|
36
|
+
type: :development
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1.5'
|
29
43
|
- !ruby/object:Gem::Dependency
|
30
44
|
name: rake
|
31
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -42,6 +56,62 @@ dependencies:
|
|
42
56
|
version: '0'
|
43
57
|
- !ruby/object:Gem::Dependency
|
44
58
|
name: rdoc
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '3.4'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ~>
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '3.4'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rails
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 3.2.17
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ~>
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 3.2.17
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rspec
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ~>
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '2.14'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '2.14'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: rspec-rails
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ~>
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '2.14'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ~>
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '2.14'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: sqlite3
|
45
115
|
requirement: !ruby/object:Gem::Requirement
|
46
116
|
requirements:
|
47
117
|
- - '>='
|
@@ -55,7 +125,7 @@ dependencies:
|
|
55
125
|
- !ruby/object:Gem::Version
|
56
126
|
version: '0'
|
57
127
|
- !ruby/object:Gem::Dependency
|
58
|
-
name:
|
128
|
+
name: rubocop
|
59
129
|
requirement: !ruby/object:Gem::Requirement
|
60
130
|
requirements:
|
61
131
|
- - '>='
|
@@ -69,19 +139,33 @@ dependencies:
|
|
69
139
|
- !ruby/object:Gem::Version
|
70
140
|
version: '0'
|
71
141
|
- !ruby/object:Gem::Dependency
|
72
|
-
name:
|
142
|
+
name: appraisal
|
73
143
|
requirement: !ruby/object:Gem::Requirement
|
74
144
|
requirements:
|
75
|
-
- -
|
145
|
+
- - '>='
|
76
146
|
- !ruby/object:Gem::Version
|
77
|
-
version: '
|
147
|
+
version: '0'
|
78
148
|
type: :development
|
79
149
|
prerelease: false
|
80
150
|
version_requirements: !ruby/object:Gem::Requirement
|
81
151
|
requirements:
|
82
|
-
- -
|
152
|
+
- - '>='
|
83
153
|
- !ruby/object:Gem::Version
|
84
|
-
version: '
|
154
|
+
version: '0'
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: gem-release
|
157
|
+
requirement: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - '>='
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
type: :development
|
163
|
+
prerelease: false
|
164
|
+
version_requirements: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
85
169
|
description: Easy to use Settings helper that loads its data in from config/settings.yml.
|
86
170
|
Handles adding multiple sources, and easy reloading.
|
87
171
|
email:
|
@@ -93,16 +177,9 @@ extensions: []
|
|
93
177
|
extra_rdoc_files:
|
94
178
|
- README.md
|
95
179
|
files:
|
96
|
-
- .bundle/config
|
97
|
-
- .gitignore
|
98
|
-
- .ruby-gemset
|
99
180
|
- CHANGELOG.md
|
100
|
-
-
|
101
|
-
- LICENSE
|
181
|
+
- LICENSE.md
|
102
182
|
- README.md
|
103
|
-
- Rakefile
|
104
|
-
- autotest/discover.rb
|
105
|
-
- init.rb
|
106
183
|
- lib/generators/rails_config/install_generator.rb
|
107
184
|
- lib/generators/rails_config/templates/rails_config.rb
|
108
185
|
- lib/generators/rails_config/templates/settings.local.yml
|
@@ -111,30 +188,18 @@ files:
|
|
111
188
|
- lib/generators/rails_config/templates/settings/production.yml
|
112
189
|
- lib/generators/rails_config/templates/settings/test.yml
|
113
190
|
- lib/rails_config.rb
|
191
|
+
- lib/rails_config/engine.rb
|
114
192
|
- lib/rails_config/integration/rails.rb
|
115
193
|
- lib/rails_config/integration/sinatra.rb
|
116
194
|
- lib/rails_config/options.rb
|
117
195
|
- lib/rails_config/rack/reloader.rb
|
196
|
+
- lib/rails_config/railtie.rb
|
118
197
|
- lib/rails_config/sources/yaml_source.rb
|
198
|
+
- lib/rails_config/tasks/heroku.rake
|
199
|
+
- lib/rails_config/tasks/rails_config_tasks.rake
|
119
200
|
- lib/rails_config/vendor/deep_merge.rb
|
120
201
|
- lib/rails_config/version.rb
|
121
|
-
-
|
122
|
-
- spec/fixtures/bool_override/config1.yml
|
123
|
-
- spec/fixtures/bool_override/config2.yml
|
124
|
-
- spec/fixtures/custom_types/hash.yml
|
125
|
-
- spec/fixtures/deep_merge/config1.yml
|
126
|
-
- spec/fixtures/deep_merge/config2.yml
|
127
|
-
- spec/fixtures/deep_merge2/config1.yml
|
128
|
-
- spec/fixtures/deep_merge2/config2.yml
|
129
|
-
- spec/fixtures/development.yml
|
130
|
-
- spec/fixtures/empty1.yml
|
131
|
-
- spec/fixtures/empty2.yml
|
132
|
-
- spec/fixtures/settings.yml
|
133
|
-
- spec/fixtures/settings2.yml
|
134
|
-
- spec/fixtures/with_erb.yml
|
135
|
-
- spec/rails_config_spec.rb
|
136
|
-
- spec/sources/yaml_source_spec.rb
|
137
|
-
- spec/spec_helper.rb
|
202
|
+
- lib/tasks.rb
|
138
203
|
homepage: http://github.com/railsjedi/rails_config
|
139
204
|
licenses:
|
140
205
|
- MIT
|
@@ -160,20 +225,4 @@ rubygems_version: 2.2.2
|
|
160
225
|
signing_key:
|
161
226
|
specification_version: 4
|
162
227
|
summary: Provides a Settings helper for Rails that reads from config/settings.yml
|
163
|
-
test_files:
|
164
|
-
- spec/fixtures/bool_override/config1.yml
|
165
|
-
- spec/fixtures/bool_override/config2.yml
|
166
|
-
- spec/fixtures/custom_types/hash.yml
|
167
|
-
- spec/fixtures/deep_merge/config1.yml
|
168
|
-
- spec/fixtures/deep_merge/config2.yml
|
169
|
-
- spec/fixtures/deep_merge2/config1.yml
|
170
|
-
- spec/fixtures/deep_merge2/config2.yml
|
171
|
-
- spec/fixtures/development.yml
|
172
|
-
- spec/fixtures/empty1.yml
|
173
|
-
- spec/fixtures/empty2.yml
|
174
|
-
- spec/fixtures/settings.yml
|
175
|
-
- spec/fixtures/settings2.yml
|
176
|
-
- spec/fixtures/with_erb.yml
|
177
|
-
- spec/rails_config_spec.rb
|
178
|
-
- spec/sources/yaml_source_spec.rb
|
179
|
-
- spec/spec_helper.rb
|
228
|
+
test_files: []
|
data/.bundle/config
DELETED
data/.gitignore
DELETED
data/.ruby-gemset
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rails_config
|
data/Gemfile
DELETED
data/LICENSE
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
Copyright (c) 2010 Jacques Crocker
|
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.
|
21
|
-
|
22
|
-
|
23
|
-
Deep Merge (deep_merge.rb) code Copyright (c) 2008 Steve Midgley, released under the MIT license
|
data/Rakefile
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require "bundler"
|
3
|
-
Bundler::GemHelper.install_tasks
|
4
|
-
rescue Exception => e
|
5
|
-
end
|
6
|
-
|
7
|
-
require "rake"
|
8
|
-
require "rspec"
|
9
|
-
require "rspec/core/rake_task"
|
10
|
-
|
11
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
12
|
-
spec.pattern = "spec/**/*_spec.rb"
|
13
|
-
end
|
14
|
-
|
15
|
-
RSpec::Core::RakeTask.new('spec:progress') do |spec|
|
16
|
-
spec.rspec_opts = %w(--format progress)
|
17
|
-
spec.pattern = "spec/**/*_spec.rb"
|
18
|
-
end
|
19
|
-
|
20
|
-
require "rdoc/task"
|
21
|
-
Rake::RDocTask.new do |rdoc|
|
22
|
-
rdoc.rdoc_dir = "rdoc"
|
23
|
-
rdoc.title = "Rails Config #{RailsConfig::VERSION}"
|
24
|
-
rdoc.rdoc_files.include("README*")
|
25
|
-
rdoc.rdoc_files.include("lib/**/*.rb")
|
26
|
-
end
|
27
|
-
|
28
|
-
task :default => :spec
|
data/autotest/discover.rb
DELETED
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/lib/rails_config'
|
data/rails_config.gemspec
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + "/lib/rails_config/version"
|
2
|
-
|
3
|
-
Gem::Specification.new do |s|
|
4
|
-
s.name = "rails_config"
|
5
|
-
s.version = RailsConfig::VERSION
|
6
|
-
s.date = Time.now.strftime '%F'
|
7
|
-
s.authors = ["Jacques Crocker", "Fred Wu", "Piotr Kuczynski"]
|
8
|
-
s.email = ["railsjedi@gmail.com", "ifredwu@gmail.com", "piotr.kuczynski@gmail.com"]
|
9
|
-
s.summary = "Provides a Settings helper for Rails that reads from config/settings.yml"
|
10
|
-
s.description = "Easy to use Settings helper that loads its data in from config/settings.yml. Handles adding multiple sources, and easy reloading."
|
11
|
-
s.homepage = "http://github.com/railsjedi/rails_config"
|
12
|
-
s.license = "MIT"
|
13
|
-
s.extra_rdoc_files = ["README.md"]
|
14
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
15
|
-
s.require_paths = ["lib"]
|
16
|
-
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
|
20
|
-
s.add_dependency "activesupport", ">= 3.0"
|
21
|
-
s.add_development_dependency "rake"
|
22
|
-
s.add_development_dependency "rdoc"
|
23
|
-
s.add_development_dependency "pry"
|
24
|
-
s.add_development_dependency "rspec", "~> 2.0"
|
25
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
size: 1
|
2
|
-
server: google.com
|
3
|
-
inner:
|
4
|
-
something1: "blah1"
|
5
|
-
something2: "blah2"
|
6
|
-
|
7
|
-
inner2:
|
8
|
-
inner2_inner:
|
9
|
-
foo1: "blah1"
|
10
|
-
|
11
|
-
|
12
|
-
arraylist1:
|
13
|
-
- 1
|
14
|
-
- 2
|
15
|
-
- 3
|
16
|
-
|
17
|
-
arraylist2:
|
18
|
-
inner:
|
19
|
-
- 1
|
20
|
-
- 2
|
21
|
-
- 3
|
22
|
-
|
23
|
-
hash_array:
|
24
|
-
- 1
|
25
|
-
- inner:
|
26
|
-
- 1
|
27
|
-
- 2
|
28
|
-
- 3
|
@@ -1,28 +0,0 @@
|
|
1
|
-
server: google.com
|
2
|
-
|
3
|
-
inner:
|
4
|
-
something3: "blah3"
|
5
|
-
|
6
|
-
inner2:
|
7
|
-
inner2_inner:
|
8
|
-
foo2: "blah2"
|
9
|
-
foo3: "blah3"
|
10
|
-
|
11
|
-
arraylist1:
|
12
|
-
- 4
|
13
|
-
- 5
|
14
|
-
- 6
|
15
|
-
|
16
|
-
|
17
|
-
arraylist2:
|
18
|
-
inner:
|
19
|
-
- 4
|
20
|
-
- 5
|
21
|
-
- 6
|
22
|
-
|
23
|
-
hash_array:
|
24
|
-
- 2
|
25
|
-
- inner:
|
26
|
-
- 4
|
27
|
-
- 5
|
28
|
-
- 6
|
data/spec/fixtures/empty1.yml
DELETED
File without changes
|
data/spec/fixtures/empty2.yml
DELETED
File without changes
|
data/spec/fixtures/settings.yml
DELETED
data/spec/fixtures/settings2.yml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
another: "something"
|
data/spec/fixtures/with_erb.yml
DELETED
data/spec/rails_config_spec.rb
DELETED
@@ -1,245 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RailsConfig do
|
4
|
-
|
5
|
-
it "should load a basic config file" do
|
6
|
-
config = RailsConfig.load_files(setting_path("settings.yml"))
|
7
|
-
config.size.should eq 1
|
8
|
-
config.server.should eq "google.com"
|
9
|
-
config['1'].should eq 'one'
|
10
|
-
config.photo_sizes.avatar.should eq [60, 60]
|
11
|
-
config.root['yahoo.com'].should eq 2
|
12
|
-
config.root['google.com'].should eq 3
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should load 2 basic config files" do
|
16
|
-
config = RailsConfig.load_files(setting_path("settings.yml"), setting_path("settings2.yml"))
|
17
|
-
config.size.should eq 1
|
18
|
-
config.server.should eq "google.com"
|
19
|
-
config.another.should eq "something"
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should load empty config for a missing file path" do
|
23
|
-
config = RailsConfig.load_files(setting_path("some_file_that_doesnt_exist.yml"))
|
24
|
-
config.should be_empty
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should load an empty config for multiple missing file paths" do
|
28
|
-
files = [setting_path("doesnt_exist1.yml"), setting_path("doesnt_exist2.yml")]
|
29
|
-
config = RailsConfig.load_files(files)
|
30
|
-
config.should be_empty
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should load empty config for an empty setting file" do
|
34
|
-
config = RailsConfig.load_files(setting_path("empty1.yml"))
|
35
|
-
config.should be_empty
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should convert to a hash" do
|
39
|
-
config = RailsConfig.load_files(setting_path("development.yml")).to_hash
|
40
|
-
config[:section][:servers].should be_a_kind_of(Array)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should convert to a json" do
|
44
|
-
config = RailsConfig.load_files(setting_path("development.yml")).to_json
|
45
|
-
JSON.parse(config)["section"]["servers"].should be_a_kind_of(Array)
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should load an empty config for multiple missing file paths" do
|
49
|
-
files = [setting_path("empty1.yml"), setting_path("empty2.yml")]
|
50
|
-
config = RailsConfig.load_files(files)
|
51
|
-
config.should be_empty
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should allow overrides" do
|
55
|
-
files = [setting_path("settings.yml"), setting_path("development.yml")]
|
56
|
-
config = RailsConfig.load_files(files)
|
57
|
-
config.server.should eq "google.com"
|
58
|
-
config.size.should eq 2
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should allow full reload of the settings files" do
|
62
|
-
files = [setting_path("settings.yml")]
|
63
|
-
RailsConfig.load_and_set_settings(files)
|
64
|
-
Settings.server.should eq "google.com"
|
65
|
-
Settings.size.should eq 1
|
66
|
-
|
67
|
-
files = [setting_path("settings.yml"), setting_path("development.yml")]
|
68
|
-
Settings.reload_from_files(files)
|
69
|
-
Settings.server.should eq "google.com"
|
70
|
-
Settings.size.should eq 2
|
71
|
-
end
|
72
|
-
|
73
|
-
context "Nested Settings" do
|
74
|
-
let(:config) do
|
75
|
-
RailsConfig.load_files(setting_path("development.yml"))
|
76
|
-
end
|
77
|
-
|
78
|
-
it "should allow nested sections" do
|
79
|
-
config.section.size.should eq 3
|
80
|
-
end
|
81
|
-
|
82
|
-
it "should allow configuration collections (arrays)" do
|
83
|
-
config.section.servers[0].name.should eq "yahoo.com"
|
84
|
-
config.section.servers[1].name.should eq "amazon.com"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
context "Settings with ERB tags" do
|
89
|
-
let(:config) do
|
90
|
-
RailsConfig.load_files(setting_path("with_erb.yml"))
|
91
|
-
end
|
92
|
-
|
93
|
-
it "should evaluate ERB tags" do
|
94
|
-
config.computed.should eq 6
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should evaluated nested ERB tags" do
|
98
|
-
config.section.computed1.should eq 1
|
99
|
-
config.section.computed2.should eq 2
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "Deep Merging" do
|
104
|
-
let(:config) do
|
105
|
-
files = [setting_path("deep_merge/config1.yml"), setting_path("deep_merge/config2.yml")]
|
106
|
-
RailsConfig.load_files(files)
|
107
|
-
end
|
108
|
-
|
109
|
-
it "should merge hashes from multiple configs" do
|
110
|
-
config.inner.marshal_dump.keys.size.should eq 3
|
111
|
-
config.inner2.inner2_inner.marshal_dump.keys.size.should eq 3
|
112
|
-
end
|
113
|
-
|
114
|
-
it "should merge arrays from multiple configs" do
|
115
|
-
config.arraylist1.size.should eq 6
|
116
|
-
config.arraylist2.inner.size.should eq 6
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
context "Boolean Overrides" do
|
121
|
-
let(:config) do
|
122
|
-
files = [setting_path("bool_override/config1.yml"), setting_path("bool_override/config2.yml")]
|
123
|
-
RailsConfig.load_files(files)
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should allow overriding of bool settings" do
|
127
|
-
config.override_bool.should eq false
|
128
|
-
config.override_bool_opposite.should eq true
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
context "Custom Configuration" do
|
133
|
-
it "should have the default settings constant as 'Settings'" do
|
134
|
-
RailsConfig.const_name.should eq "Settings"
|
135
|
-
end
|
136
|
-
|
137
|
-
it "should be able to assign a different settings constant" do
|
138
|
-
RailsConfig.setup{ |config| config.const_name = "Settings2" }
|
139
|
-
RailsConfig.const_name.should eq "Settings2"
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
context "Settings with a type value of 'hash'" do
|
144
|
-
let(:config) do
|
145
|
-
files = [setting_path("custom_types/hash.yml")]
|
146
|
-
RailsConfig.load_files(files)
|
147
|
-
end
|
148
|
-
|
149
|
-
it "should turn that setting into a Real Hash" do
|
150
|
-
config.prices.should be_a(Hash)
|
151
|
-
end
|
152
|
-
|
153
|
-
it "should map the hash values correctly" do
|
154
|
-
config.prices[1].should eq 2.99
|
155
|
-
config.prices[5].should eq 9.99
|
156
|
-
config.prices[15].should eq 19.99
|
157
|
-
config.prices[30].should eq 29.99
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
context "Merging hash at runtime" do
|
162
|
-
let(:config) { RailsConfig.load_files(setting_path("settings.yml")) }
|
163
|
-
let(:hash) { {:options => {:suboption => 'value'}, :server => 'amazon.com'} }
|
164
|
-
|
165
|
-
it 'should be chainable' do
|
166
|
-
config.merge!({}).should eq config
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'should preserve existing keys' do
|
170
|
-
expect { config.merge!({}) }.to_not change{ config.keys }
|
171
|
-
end
|
172
|
-
|
173
|
-
it 'should recursively merge keys' do
|
174
|
-
config.merge!(hash)
|
175
|
-
config.options.suboption.should eq 'value'
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'should rewrite a merged value' do
|
179
|
-
expect { config.merge!(hash) }.to change{ config.server }.from('google.com').to('amazon.com')
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
context "Merging nested hash at runtime" do
|
184
|
-
let(:config) { RailsConfig.load_files(setting_path("deep_merge/config1.yml")) }
|
185
|
-
let(:hash) { {:inner => {:something1 => 'changed1', :something3 => 'changed3'} } }
|
186
|
-
|
187
|
-
it 'should preserve first level keys' do
|
188
|
-
expect { config.merge!(hash) }.to_not change{ config.keys }
|
189
|
-
end
|
190
|
-
|
191
|
-
it 'should preserve nested key' do
|
192
|
-
config.merge!(hash)
|
193
|
-
config.inner.something2.should eq 'blah2'
|
194
|
-
end
|
195
|
-
|
196
|
-
it 'should add new nested key' do
|
197
|
-
expect { config.merge!(hash) }.to change { config.inner.something3 }.from(nil).to("changed3")
|
198
|
-
end
|
199
|
-
|
200
|
-
it 'should rewrite a merged value' do
|
201
|
-
expect { config.merge!(hash) }.to change{ config.inner.something1 }.from('blah1').to('changed1')
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
context "[] accessors" do
|
206
|
-
let(:config) do
|
207
|
-
files = [setting_path("development.yml")]
|
208
|
-
RailsConfig.load_files(files)
|
209
|
-
end
|
210
|
-
|
211
|
-
it "should access attributes using []" do
|
212
|
-
config.section['size'].should eq 3
|
213
|
-
config.section[:size].should eq 3
|
214
|
-
config[:section][:size].should eq 3
|
215
|
-
end
|
216
|
-
|
217
|
-
it "should set values using []=" do
|
218
|
-
config.section[:foo] = 'bar'
|
219
|
-
config.section.foo.should eq 'bar'
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
context "enumerable" do
|
224
|
-
let(:config) do
|
225
|
-
files = [setting_path("development.yml")]
|
226
|
-
RailsConfig.load_files(files)
|
227
|
-
end
|
228
|
-
|
229
|
-
it "should enumerate top level parameters" do
|
230
|
-
keys = []
|
231
|
-
config.each { |key, value| keys << key }
|
232
|
-
keys.should eq [:size, :section]
|
233
|
-
end
|
234
|
-
|
235
|
-
it "should enumerate inner parameters" do
|
236
|
-
keys = []
|
237
|
-
config.section.each { |key, value| keys << key }
|
238
|
-
keys.should eq [:size, :servers]
|
239
|
-
end
|
240
|
-
|
241
|
-
it "should have methods defined by Enumerable" do
|
242
|
-
config.map { |key, value| key }.should eq [:size, :section]
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module RailsConfig::Sources
|
4
|
-
describe YAMLSource do
|
5
|
-
|
6
|
-
it "should take a path as initializer" do
|
7
|
-
source = YAMLSource.new "somepath"
|
8
|
-
source.path.should == "somepath"
|
9
|
-
end
|
10
|
-
|
11
|
-
context "basic yml file" do
|
12
|
-
let(:source) do
|
13
|
-
YAMLSource.new setting_path("development.yml")
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should properly read the settings" do
|
17
|
-
results = source.load
|
18
|
-
results["size"].should == 2
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should properly read nested settings" do
|
22
|
-
results = source.load
|
23
|
-
results["section"]["size"].should == 3
|
24
|
-
results["section"]["servers"].should be_an(Array)
|
25
|
-
results["section"]["servers"].size.should == 2
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context "yml file with erb tags" do
|
30
|
-
let(:source) do
|
31
|
-
YAMLSource.new setting_path("with_erb.yml")
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should properly evaluate the erb" do
|
35
|
-
results = source.load
|
36
|
-
results["computed"].should == 6
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should properly evaluate the nested erb settings" do
|
40
|
-
results = source.load
|
41
|
-
results["section"]["computed1"].should == 1
|
42
|
-
results["section"]["computed2"].should == 2
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context "missing yml file" do
|
47
|
-
let(:source) do
|
48
|
-
YAMLSource.new "somewhere_that_doesnt_exist.yml"
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should return an empty hash" do
|
52
|
-
results = source.load
|
53
|
-
results.should == {}
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context "blank yml file" do
|
58
|
-
let(:source) do
|
59
|
-
YAMLSource.new setting_path("empty1.yml")
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should return an empty hash" do
|
63
|
-
results = source.load
|
64
|
-
results.should == {}
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'rails_config'
|
2
|
-
require 'pathname'
|
3
|
-
require 'bundler/setup'
|
4
|
-
|
5
|
-
def in_editor?
|
6
|
-
ENV.has_key?('TM_MODE') || ENV.has_key?('EMACS') || ENV.has_key?('VIM')
|
7
|
-
end
|
8
|
-
|
9
|
-
RSpec.configure do |c|
|
10
|
-
c.color_enabled = !in_editor?
|
11
|
-
c.run_all_when_everything_filtered = true
|
12
|
-
|
13
|
-
# setup fixtures path
|
14
|
-
c.before(:all) do
|
15
|
-
@fixture_path = Pathname.new(File.join(File.dirname(__FILE__), "/fixtures"))
|
16
|
-
raise "Fixture folder not found: #{@fixture_path}" unless @fixture_path.directory?
|
17
|
-
end
|
18
|
-
|
19
|
-
# returns the file path of a fixture setting file
|
20
|
-
def setting_path(filename)
|
21
|
-
@fixture_path.join(filename)
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
|