anyway_config 0.5.1 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 809092685f06ffac464aa29746797c1fec47f899
4
- data.tar.gz: 37855a5237e91c0a0958ce89c7cd4772af85689a
3
+ metadata.gz: 429f99711260e7eb7c57d207d1c9b5df66663a3f
4
+ data.tar.gz: 79e50e810078aa95ba472587b04fc2929af1c641
5
5
  SHA512:
6
- metadata.gz: c818eacf91c5364efe0df64de0ee36b8dacaab2ed7df2594265fac8bdc29f02d5f0a72fa82131f46324332c7a84d170e260cba6fb91cea378b70e91963132b2e
7
- data.tar.gz: eb0806e2ad07292ef47a363fd212c5b41f16b3f51dbf4d7a4957e51438351eef4c4c9bd06ede20042395ddd13bbb04edd1dfe578652212c2f1adf839a346071b
6
+ metadata.gz: 5b2ac6da8c645a45a70cc3f5a0958c12a7097da8b6a79ae5732656b3ad15d4d7e6ec360be0da47b8d496c84ba187d3a6de9ea465eaa727fec68cac713cf6ece2
7
+ data.tar.gz: 1afa0ed9d11219ef5036ad399795ce5a431c9673492eea9cf4971bf717c5165c4469198d8a7f58b0e85b8b58d3f1f679a639fc45d61c48f47d6fb297420b4170
data/.gitignore CHANGED
@@ -34,4 +34,6 @@ spec/dummy/tmp/
34
34
  Gemfile.lock
35
35
  Gemfile.local
36
36
  .rspec
37
- *.gem
37
+ *.gem
38
+
39
+ tmp/
data/.rubocop.yml CHANGED
@@ -1,15 +1,19 @@
1
1
  AllCops:
2
- # Include gemspec and Rakefile
3
2
  Include:
4
3
  - 'lib/**/*.rb'
5
4
  - 'lib/**/*.rake'
6
5
  - 'spec/**/*.rb'
6
+ - 'Gemfile'
7
+ - 'Rakefile'
7
8
  Exclude:
8
9
  - 'bin/**/*'
9
10
  - 'spec/dummy/**/*'
10
- RunRailsCops: true
11
+ - 'tmp/**/*'
12
+ - 'gemfiles/vendor/**/*'
13
+ - 'vendor/**/*'
11
14
  DisplayCopNames: true
12
15
  StyleGuideCopsOnly: false
16
+ TargetRubyVersion: 2.3
13
17
 
14
18
  Style/Documentation:
15
19
  Exclude:
@@ -26,11 +30,9 @@ Metrics/MethodLength:
26
30
  Exclude:
27
31
  - 'spec/**/*.rb'
28
32
 
33
+ Metrics/BlockLength:
34
+ Exclude:
35
+ - 'spec/**/*.rb'
36
+
29
37
  Metrics/LineLength:
30
38
  Max: 100
31
-
32
- Rails/Date:
33
- Enabled: false
34
-
35
- Rails/TimeZone:
36
- Enabled: false
data/.travis.yml CHANGED
@@ -1,6 +1,9 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
 
4
+ dist: trusty
5
+ sudo: false
6
+
4
7
  notifications:
5
8
  email: false
6
9
 
@@ -10,8 +13,14 @@ before_install:
10
13
 
11
14
  matrix:
12
15
  include:
16
+ - rvm: ruby-head
17
+ gemfile: gemfiles/railsmaster.gemfile
18
+ - rvm: 2.4.1
19
+ gemfile: gemfiles/rails5.gemfile
13
20
  - rvm: 2.3.1
14
21
  gemfile: gemfiles/rails42.gemfile
15
-
16
- - rvm: 2.4.0
17
- gemfile: gemfiles/rails5.gemfile
22
+ - rvm: 2.2.3
23
+ gemfile: gemfiles/rails42.gemfile
24
+ allow_failures:
25
+ - rvm: ruby-head
26
+ gemfile: gemfiles/railsmaster.gemfile
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Change log
2
+
3
+ ## 1.0.0 (2017-06-20)
4
+
5
+ - Lazy load and parse ENV configurtaion (https://github.com/palkan/anyway_config/commit/5fe407c75fefec8994ca201ea7b4691b5ddd96e5). ([@palkan][])
6
+
7
+ - Add support for ERB in YML configuration (https://github.com/palkan/anyway_config/commit/8d8a47dbda6858a43ff509aaa4cddf4f938dd660). ([@palkan][])
8
+
9
+ ## 0.5.0 (2017-01-20)
10
+
11
+ - Drop `active_support` dependency. ([@palkan][])
12
+
13
+ Use custom refinements instead of requiring `active_support`.
14
+
15
+ No we're dependency-free!
16
+
17
+ ## 0.1.0 (2015-01-20)
18
+
19
+ Initial version.
20
+
21
+ [@palkan]: https://github.com/palkan
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in anyway_config.gemspec
@@ -7,7 +9,7 @@ gemspec
7
9
  local_gemfile = "#{File.dirname(__FILE__)}/Gemfile.local"
8
10
 
9
11
  if File.exist?(local_gemfile)
10
- eval(File.read(local_gemfile)) # rubocop:disable Lint/Eval
12
+ eval(File.read(local_gemfile)) # rubocop:disable Security/Eval
11
13
  else
12
14
  gem 'rails', '~> 5.0'
13
15
  end
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 palkan
1
+ Copyright (c) 2017 palkan
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -2,34 +2,45 @@
2
2
 
3
3
  # Anyway Config
4
4
 
5
- Rails/Ruby plugin/application configuration using any source: YAML, _secrets_, environment.
5
+ Rails/Ruby plugin/application configuration tool which allows you to load parameters from different sources: YAML, Rails secrets, environment.
6
6
 
7
+ Apps using AnywayConfig:
7
8
 
8
- Apps using Anyway Config:
9
9
  - [Influxer](https://github.com/palkan/influxer)
10
- - [AnyCable](https://github.com/anycable/anycable).
11
10
 
12
- ## Using with Gem
11
+ - [AnyCable](https://github.com/anycable/anycable)
13
12
 
14
- Configure your gemspec:
13
+ - [and others](https://github.com/palkan/anyway_config/network/dependents).
14
+
15
+ ## Installation
16
+
17
+ 1) Adding to a gem:
15
18
 
16
19
  ```ruby
17
- Gem::Specification.new do |s|
20
+ # my-cool-gem.gemspec
21
+ Gem::Specification.new do |spec|
18
22
  ...
19
- s.add_dependancy 'anyway_config', "~>0.5"
23
+ spec.add_dependancy "anyway_config", "~> 1.0"
20
24
  ...
21
25
  end
22
26
  ```
23
27
 
24
- And then execute:
28
+ 2) Adding to your project:
25
29
 
26
- $ bundle
30
+ ```ruby
31
+ # Gemfile
32
+ gem "anyway_config", "~> 1.0"
33
+ ```
27
34
 
28
- Or install it yourself as:
35
+ 3) Install globally:
29
36
 
30
- $ gem install anyway_config
37
+ ```sh
38
+ $ gem install anyway_config
39
+ ```
31
40
 
32
- ### Usage
41
+ ## Usage
42
+
43
+ ### Pre-defined configuration
33
44
 
34
45
  Create configuration class:
35
46
 
@@ -49,11 +60,21 @@ end
49
60
  attr_config :user, :password, host: 'localhost'
50
61
  ```
51
62
 
52
- Your config will be filled up with values from `RAILS_ROOT/config/my_cool_gem.yml`, `Rails.application.secrets.my_cool_gem` (if using Rails) and `ENV['MYCOOLGEM_*']`.
63
+ Then create an instance of the config class and use it:
53
64
 
54
- ### Customize name
65
+ ```ruby
66
+ module MyCoolGem
67
+ def self.config
68
+ @config ||= Config.new
69
+ end
70
+ end
71
+
72
+ MyCoolGem.config.user #=> 'root'
73
+ ```
74
+
75
+ #### Customize name
55
76
 
56
- If you want to load config params from, for example, "cool.yml" (secrets, env), just add one line:
77
+ By default, AnywayConfig uses the namespace (the outer module name) as the config name, but you can set it manually:
57
78
 
58
79
  ```ruby
59
80
  module MyCoolGem
@@ -64,30 +85,41 @@ module MyCoolGem
64
85
  end
65
86
  ```
66
87
 
67
- ### Config clear and reload
88
+ ### Dynamic configuration
68
89
 
69
- You can use `clear` and `reload` functions on your config (which do exactly what they state).
90
+ You can also create configuration objects without pre-defined schema (just like `Rails.application.config_for` but more [powerful](#railsapplicationconfig_for-vs-anywayconfigfor)):
70
91
 
92
+ ```ruby
93
+ # load data from config/my_app.yml, secrets.my_app (if using Rails), ENV["MYAPP_*"]
94
+ config = Anyway::Config.for(:my_app)
95
+ ```
71
96
 
72
- ## Using with Rails app
97
+ ### Using with Rails
73
98
 
74
- In your Gemfile
99
+ Your config will be filled up with values from the following sources (ordered by priority from low to high):
75
100
 
76
- ```ruby
77
- require 'anyway_config', "~>0.5", require: 'anyway'
78
- ```
101
+ - `RAILS_ROOT/config/my_cool_gem.yml` (for the current `RAILS_ENV`, supports `ERB`)
79
102
 
80
- In your code
103
+ - `Rails.application.secrets.my_cool_gem`
81
104
 
82
- ```ruby
105
+ - `ENV['MYCOOLGEM_*']`.
83
106
 
84
- config = Anyway::Config.for(:my_app) # load data from config/my_app.yml, secrets.my_app, ENV["MYAPP_*"]
107
+ ### Using with Ruby
108
+
109
+ By default AnywayConfig is looking for a config YAML at `./config/<config-name>.yml`. You can override this setting
110
+ through special environment variable – 'MYGEM_CONF' – containing the path to the YAML file.
111
+
112
+ Environmental variables work the same way as with Rails.
113
+
114
+
115
+ ### Config clear and reload
116
+
117
+ There are `#clear` and `#reload` functions on your config (which do exactly what they state).
85
118
 
86
- ```
87
119
 
88
120
  ## `Rails.application.config_for` vs `Anyway::Config.for`
89
121
 
90
- Rails 4.2 introduces new feature: `Rails.application.config_for`. It looks very similar to
122
+ Rails 4.2 introduced new feature: `Rails.application.config_for`. It looks very similar to
91
123
  `Anyway::Config.for`, but there are some differences:
92
124
 
93
125
  | Feature | Rails | Anyway |
@@ -96,26 +128,33 @@ Rails 4.2 introduces new feature: `Rails.application.config_for`. It looks very
96
128
  | load data from `secrets` | no | yes |
97
129
  | load data from environment | no | yes |
98
130
  | return Hash with indifferent access | no | yes |
99
- | support ERB within `config/app.yml` | yes | no |
131
+ | support ERB within `config/app.yml` | yes | yes* |
100
132
  | raise errors if file doesn't exist | yes | no |
101
133
 
102
- But the main advantage of Anyway::Config is that it can be used [without Rails](#using-without-rails)!
134
+ <sub><sup>*</sup>make sure that ERB is loaded</sub>
135
+
136
+ But the main advantage of Anyway::Config is that it can be used [without Rails](#using-with-ruby)!)
103
137
 
104
138
  ## How to set env vars
105
139
 
106
- Environmental variables for your config should start with your module name (or config name if any), uppercased and underscore-free.
140
+ Environmental variables for your config should start with your config name, uppercased and underscore-free.
141
+
142
+ For example, if your module is called "MyCoolGem" then the env var "MYCOOLGEM_PASSWORD" is used as `config.password`.
107
143
 
108
- For example, if your module is called "MyCoolGem" then your env var "MYCOOLGEM_PASSWORD" is used as `config.password`.
144
+ Environment variables are type-casted (case-insensitive).
109
145
 
110
- Environment variables are type-casted (case-insensitive).
111
146
  Examples:
112
- - "True", "T" and "yes" to `true`;
113
- - "False", "f" and "no" to `false`;
114
- - "nil" and "null" to `nil` (do you really need it?);
115
- - "123" to 123 and "3.14" to 3.14.
116
147
 
117
- *Anyway Config* supports nested (_hashed_) environmental variables. Just separate keys with double-underscore.
118
- For example, "MYCOOLGEM_OPTIONS__VERBOSE" is transformed to `config.options.verbose`.
148
+ - `"True"`, `"t"` and `"yes"` to `true`;
149
+
150
+ - `"False"`, `"f"` and `"no"` to `false`;
151
+
152
+ - `"nil"` and `"null"` to `nil` (do you really need it?);
153
+
154
+ - `"123"` to 123 and `"3.14"` to 3.14.
155
+
156
+ *Anyway Config* supports nested (_hashed_) env variables. Just separate keys with double-underscore.
157
+ For example, "MYCOOLGEM_OPTIONS__VERBOSE" is parsed as `config.options.verbose`.
119
158
 
120
159
  Array values are also supported:
121
160
 
@@ -124,21 +163,16 @@ Array values are also supported:
124
163
  config.ids #=> [1,2,3]
125
164
  ```
126
165
 
127
- If you want to provide text-like env variable which contain commas then wrap it into quotes:
166
+ If you want to provide a text-like env variable which contains commas then wrap it into quotes:
128
167
 
129
168
  ```ruby
130
169
  MYCOOLGEM="Nif-Nif, Naf-Naf and Nouf-Nouf"
131
170
  ```
132
171
 
133
- ## Using without Rails
134
-
135
- AnywayConfig can be used without Rails too.
136
- Environmental variables remain the same. To load config from YAML add special environment variable 'MYGEM_CONF' containing path to config. But you cannot use one file for different environments (unless you do it yourself).
137
-
138
172
  ## Contributing
139
173
 
140
174
  1. Fork it
141
175
  2. Create your feature branch (`git checkout -b my-new-feature`)
142
176
  3. Commit your changes (`git commit -am 'Add some feature'`)
143
177
  4. Push to the branch (`git push origin my-new-feature`)
144
- 5. Create a new Pull Request
178
+ 5. Create a new Pull Request
data/Rakefile CHANGED
@@ -1,6 +1,10 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
2
 
3
+ require "bundler/gem_tasks"
3
4
  require 'rspec/core/rake_task'
5
+ require "rubocop/rake_task"
6
+
7
+ RuboCop::RakeTask.new
4
8
 
5
9
  task(:spec).clear
6
10
  desc "Run specs with Rails app"
@@ -15,5 +19,5 @@ RSpec::Core::RakeTask.new("spec:norails") do |task|
15
19
  task.verbose = false
16
20
  end
17
21
 
18
- desc "Run the all specs"
19
- task default: %w(spec:norails spec)
22
+ desc "Run the all specs and linters"
23
+ task default: %w[spec:norails spec rubocop]
@@ -1,4 +1,6 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  lib = File.expand_path('../lib', __FILE__)
3
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
6
  require 'anyway/version'
@@ -6,17 +8,23 @@ require 'anyway/version'
6
8
  Gem::Specification.new do |s|
7
9
  s.name = "anyway_config"
8
10
  s.version = Anyway::VERSION
9
- s.authors = ["Vlad Dem"]
11
+ s.authors = ["Vladimir Dementyev"]
10
12
  s.email = ["dementiev.vm@gmail.com"]
11
13
  s.homepage = "http://github.com/palkan/anyway_config"
12
- s.summary = "Configuration for Ruby plugins and applications"
13
- s.description = "Configuration for Ruby plugins and applications"
14
- s.license = "MIT"
14
+ s.summary = "Configuration DSL for Ruby libraries and applications"
15
+ s.description = %{
16
+ Configuration DSL for Ruby libraries and applications.
17
+
18
+ Allows you to easily follow the twevle factor application principles (https://12factor.net/config).
19
+ }
20
+
21
+ s.license = "MIT"
15
22
 
16
- s.files = `git ls-files`.split($/)
23
+ s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
24
  s.require_paths = ["lib"]
18
25
  s.required_ruby_version = '>= 2'
19
26
 
20
27
  s.add_development_dependency "simplecov", ">= 0.3.8"
21
28
  s.add_development_dependency "rspec", "~> 3.5.0"
29
+ s.add_development_dependency "rubocop", "~> 0.49"
22
30
  end
data/config/cool.yml ADDED
@@ -0,0 +1,5 @@
1
+ host: "test.host"
2
+ user:
3
+ name: "root"
4
+ password: "root"
5
+ port: <%= ENV['ANYWAY_COOL_PORT'] || 9292 %>
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'arel', github: 'rails/arel'
4
+ gem 'rails', github: 'rails/rails'
5
+
6
+ gemspec path: '..'
data/lib/anyway/config.rb CHANGED
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'anyway/ext/class'
2
4
  require 'anyway/ext/deep_dup'
3
5
  require 'anyway/ext/hash'
4
6
 
5
- module Anyway
7
+ module Anyway # :nodoc:
6
8
  using Anyway::Ext::Class
7
9
  using Anyway::Ext::DeepDup
8
10
  using Anyway::Ext::Hash
@@ -73,16 +75,16 @@ module Anyway
73
75
  end
74
76
 
75
77
  def load_from_file(config)
76
- config_path = (Anyway.env.send(config_name) || {}).delete('conf')
78
+ config_path = Anyway.env.fetch(config_name).delete('conf') ||
79
+ "./config/#{config_name}.yml"
77
80
  if config_path && File.file?(config_path)
78
- require 'yaml'
79
- config.deep_merge!(YAML.load_file(config_path) || {})
81
+ config.deep_merge!(parse_yml(config_path) || {})
80
82
  end
81
83
  config
82
84
  end
83
85
 
84
86
  def load_from_env(config)
85
- config.deep_merge!(Anyway.env.send(config_name) || {})
87
+ config.deep_merge!(Anyway.env.fetch(config_name))
86
88
  config
87
89
  end
88
90
 
@@ -91,5 +93,14 @@ module Anyway
91
93
  def set_value(key, val)
92
94
  send("#{key}=", val) if respond_to?(key)
93
95
  end
96
+
97
+ def parse_yml(path)
98
+ require 'yaml'
99
+ if defined?(ERB)
100
+ YAML.safe_load(ERB.new(File.read(path)).result)
101
+ else
102
+ YAML.load_file(path)
103
+ end
104
+ end
94
105
  end
95
106
  end
data/lib/anyway/env.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Anyway
2
4
  # Parses environment variables and provides
3
5
  # method-like access
@@ -9,34 +11,29 @@ module Anyway
9
11
 
10
12
  def initialize
11
13
  @data = {}
12
- load
13
- end
14
-
15
- def reload
16
- clear
17
- load
18
- self
19
14
  end
20
15
 
21
16
  def clear
22
17
  @data.clear
23
- self
24
18
  end
25
19
 
26
- def method_missing(method_name, *args, &_block)
27
- method_name = method_name.to_s.gsub(/\_/, '')
28
- return @data[method_name] if args.empty? && @data.key?(method_name)
20
+ def fetch(config_name)
21
+ @data[config_name] ||= parse_env(config_name)
29
22
  end
30
23
 
31
24
  private
32
25
 
33
- def load
26
+ def parse_env(config_name)
27
+ config_env_name = config_name.to_s.delete("_")
28
+ config_env_name.upcase!
29
+ data = {}
34
30
  ENV.each_pair do |key, val|
35
- if config_key?(key)
36
- mod, path = extract_module_path(key)
37
- set_by_path(get_hash(@data, mod), path, serialize_val(val))
31
+ if key.start_with?(config_env_name)
32
+ _mod, path = extract_module_path(key)
33
+ set_by_path(data, path, serialize_val(val))
38
34
  end
39
35
  end
36
+ data
40
37
  end
41
38
 
42
39
  def config_key?(key)
@@ -61,6 +58,8 @@ module Anyway
61
58
  (from[name] ||= {})
62
59
  end
63
60
 
61
+ # rubocop:disable Metrics/MethodLength
62
+ # rubocop:disable Metrics/CyclomaticComplexity
64
63
  def serialize_val(value)
65
64
  case value
66
65
  when ARRAY_RXP
@@ -81,5 +80,7 @@ module Anyway
81
80
  value
82
81
  end
83
82
  end
83
+ # rubocop:enable Metrics/MethodLength
84
+ # rubocop:enable Metrics/CyclomaticComplexity
84
85
  end
85
86
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Anyway
2
4
  module Ext
3
5
  # Extend String through refinements
@@ -6,7 +8,7 @@ module Anyway
6
8
  def underscore_name
7
9
  return unless name
8
10
  word = name[/^(\w+)/]
9
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
11
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
10
12
  word.downcase!
11
13
  word
12
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Anyway
2
4
  module Ext
3
5
  # Extend Object through refinements
@@ -6,7 +8,11 @@ module Anyway
6
8
  # Based on ActiveSupport http://api.rubyonrails.org/classes/Hash.html#method-i-deep_dup
7
9
  def deep_dup
8
10
  each_with_object(dup) do |(key, value), hash|
9
- hash[key] = value.respond_to?(:deep_dup) ? value.deep_dup : value
11
+ hash[key] = if value.is_a?(::Hash) || value.is_a?(::Array)
12
+ value.deep_dup
13
+ else
14
+ value
15
+ end
10
16
  end
11
17
  end
12
18
  end
@@ -14,7 +20,13 @@ module Anyway
14
20
  refine ::Array do
15
21
  # From ActiveSupport http://api.rubyonrails.org/classes/Array.html#method-i-deep_dup
16
22
  def deep_dup
17
- map { |el| el.respond_to?(:deep_dup) ? el.deep_dup : el }
23
+ map do |value|
24
+ if value.is_a?(::Hash) || value.is_a?(::Array)
25
+ value.deep_dup
26
+ else
27
+ value
28
+ end
29
+ end
18
30
  end
19
31
  end
20
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Anyway
2
4
  module Ext
3
5
  # Extend Hash through refinements
@@ -20,7 +22,7 @@ module Anyway
20
22
  end
21
23
 
22
24
  def stringify_keys!
23
- self.keys.each do |key|
25
+ keys.each do |key|
24
26
  value = delete(key)
25
27
  value.stringify_keys! if value.is_a?(::Hash)
26
28
  self[key.to_s] = value
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Anyway
2
4
  class Config # :nodoc:
3
5
  class << self
@@ -17,8 +19,7 @@ module Anyway
17
19
  def load_from_file(config)
18
20
  config_path = Rails.root.join("config", "#{@config_name}.yml")
19
21
  if File.file? config_path
20
- require 'yaml'
21
- config.deep_merge!(YAML.load_file(config_path)[Rails.env] || {})
22
+ config.deep_merge!(parse_yml(config_path)[Rails.env] || {})
22
23
  end
23
24
  config
24
25
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Anyway # :nodoc:
2
- VERSION = "0.5.1"
4
+ VERSION = "1.0.0.rc1"
3
5
  end
data/lib/anyway.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Anyway # :nodoc:
2
4
  require "anyway/version"
3
5
  require "anyway/config"
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "anyway"
data/spec/config_spec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Anyway::Config do
@@ -5,6 +7,10 @@ describe Anyway::Config do
5
7
  let(:test_conf) { Anyway::TestConfig.new }
6
8
 
7
9
  describe "config with name" do
10
+ before(:each) do
11
+ ENV.delete_if { |var| var =~ /^(cool|anyway)_/i }
12
+ end
13
+
8
14
  specify { expect(CoolConfig.config_name).to eq "cool" }
9
15
 
10
16
  describe "defaults" do
@@ -21,21 +27,20 @@ describe Anyway::Config do
21
27
  end
22
28
 
23
29
  describe "load from files" do
24
- it "should set defauls" do
30
+ it "set defaults" do
25
31
  expect(conf.port).to eq 8080
26
32
  end
27
33
 
28
- it "should load config from YAML" do
34
+ it "load config from YAML" do
29
35
  expect(conf.host).to eq "test.host"
30
36
  end
31
37
 
32
38
  if Rails.application.respond_to?(:secrets)
33
- it "should load config from secrets" do
39
+ it "load config from secrets" do
34
40
  expect(conf.user[:name]).to eq "test"
35
- expect(conf.user[:password]).to eq "test"
36
41
  end
37
42
  else
38
- it "should load config from file if no secrets" do
43
+ it "load config from file if no secrets" do
39
44
  expect(conf.user[:name]).to eq "root"
40
45
  expect(conf.user[:password]).to eq "root"
41
46
  end
@@ -43,14 +48,18 @@ describe Anyway::Config do
43
48
  end
44
49
 
45
50
  describe "load from env" do
46
- after(:each) { Anyway.env.clear }
47
- it "should work" do
51
+ it "work" do
48
52
  ENV['COOL_PORT'] = '80'
49
53
  ENV['COOL_USER__NAME'] = 'john'
50
- Anyway.env.reload
54
+ Anyway.env.clear
51
55
  expect(conf.port).to eq 80
52
56
  expect(conf.user[:name]).to eq 'john'
53
57
  end
58
+
59
+ it "handle ENV in YML thru ERB" do
60
+ ENV['ANYWAY_SECRET_PASSWORD'] = 'my_pass'
61
+ expect(conf.user[:password]).to eq 'my_pass'
62
+ end
54
63
  end
55
64
 
56
65
  describe "clear" do
@@ -66,12 +75,11 @@ describe Anyway::Config do
66
75
  end
67
76
 
68
77
  describe "reload" do
69
- after(:each) { Anyway.env.clear }
70
78
  it do
71
79
  expect(conf.port).to eq 8080
72
80
  ENV['COOL_PORT'] = '80'
73
81
  ENV['COOL_USER__NAME'] = 'john'
74
- Anyway.env.reload
82
+ Anyway.env.clear
75
83
  conf.reload
76
84
  expect(conf.port).to eq 80
77
85
  expect(conf.user[:name]).to eq 'john'
@@ -80,11 +88,14 @@ describe Anyway::Config do
80
88
  end
81
89
 
82
90
  describe "config for name" do
83
- after(:each) { Anyway.env.clear }
84
- it "should load data by config name", :aggregate_failures do
91
+ before(:each) do
92
+ ENV.delete_if { |var| var =~ /^myapp_/i }
93
+ end
94
+
95
+ it "load data by config name", :aggregate_failures do
85
96
  ENV['MYAPP_TEST'] = '1'
86
97
  ENV['MYAPP_NAME'] = 'my_app'
87
- Anyway.env.reload
98
+ Anyway.env.clear
88
99
  data = Anyway::Config.for(:my_app)
89
100
  expect(data[:test]).to eq 1
90
101
  expect(data[:name]).to eq 'my_app'
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_norails_helper'
2
4
 
3
5
  describe Anyway::Config do
4
6
  let(:conf) { Anyway::TestConfig.new }
5
7
 
6
8
  describe "config without Rails" do
7
- after(:each) do
8
- Anyway.env.clear
9
+ before(:each) do
9
10
  ENV.delete_if { |var| var =~ /^anyway_/i }
10
11
  end
11
12
 
@@ -25,26 +26,27 @@ describe Anyway::Config do
25
26
  ENV['ANYWAY_LOG__FORMAT__COLOR'] = 't'
26
27
  ENV['ANYWAY_LOG_LEVELS'] = 'debug,warning,info'
27
28
 
28
- Anyway.env.reload
29
+ Anyway.env.clear
29
30
  expect(conf.api['key']).to eq "test1"
30
31
  expect(conf.api['endpoint']).to eq "localhost"
31
32
  expect(conf.test).to eq "test"
32
33
  expect(conf.log['format']['color']).to eq true
33
- expect(conf.log_levels).to eq(%w(debug warning info))
34
+ expect(conf.log_levels).to eq(%w[debug warning info])
34
35
  end
35
36
 
36
37
  it "reloads config", :aggregate_failures do
38
+ ENV['ANYWAY_CONF'] = File.join(File.dirname(__FILE__), "anyway.yml")
39
+
37
40
  expect(conf.api['key']).to eq ""
38
- expect(conf.api['endpoint']).to be_nil
41
+ expect(conf.api['endpoint']).to eq 'localhost'
39
42
  expect(conf.test).to be_nil
40
43
  expect(conf.log['format']['color']).to eq false
41
44
 
42
- ENV['ANYWAY_CONF'] = File.join(File.dirname(__FILE__), "anyway.yml")
43
45
  ENV['ANYWAY_API__KEY'] = 'test1'
44
46
  ENV['ANYWAY_API__SSL'] = 'yes'
45
47
  ENV['ANYWAY_TEST'] = 'test'
46
48
  ENV['ANYWAY_LOG__FORMAT__COLOR'] = 't'
47
- Anyway.env.reload
49
+ Anyway.env.clear
48
50
 
49
51
  conf.reload
50
52
  expect(conf.api['key']).to eq "test1"
@@ -61,5 +63,24 @@ describe Anyway::Config do
61
63
 
62
64
  specify { expect(conf.config_name).to be_nil }
63
65
  end
66
+
67
+ context "loading from default path" do
68
+ let(:conf) { CoolConfig.new }
69
+
70
+ before(:each) do
71
+ ENV.delete_if { |var| var =~ /^cool_/i }
72
+ end
73
+
74
+ it "loads from ./config", :aggregate_failures do
75
+ expect(conf.user).to eq("name" => "root", "password" => "root")
76
+ expect(conf.host).to eq "test.host"
77
+ expect(conf.port).to eq 9292
78
+ end
79
+
80
+ it "handle ENV in YML thru ERB" do
81
+ ENV["ANYWAY_COOL_PORT"] = "1957"
82
+ expect(conf.port).to eq 1957
83
+ end
84
+ end
64
85
  end
65
86
  end
@@ -2,4 +2,4 @@ test:
2
2
  host: "test.host"
3
3
  user:
4
4
  name: "root"
5
- password: "root"
5
+ password: <%= ENV['ANYWAY_SECRET_PASSWORD'] || "root" %>
@@ -18,7 +18,6 @@ test:
18
18
  cool:
19
19
  user:
20
20
  name: test
21
- password: test
22
21
  bullshit: 'mooo'
23
22
  my_app:
24
23
  name: 'app'
data/spec/env_spec.rb CHANGED
@@ -1,32 +1,36 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Anyway::Env do
4
- let(:env) { Anyway.env.reload }
6
+ let(:env) { Anyway.env }
5
7
 
6
- it "should load simple key/values by module", :aggregate_failures do
8
+ it "loads simple key/values by module", :aggregate_failures do
7
9
  ENV['TESTO_KEY'] = 'a'
8
10
  ENV['MYTEST_KEY'] = 'b'
9
- expect(env.testo['key']).to eq 'a'
10
- expect(env.my_test['key']).to eq 'b'
11
+ expect(env.fetch('testo')['key']).to eq 'a'
12
+ expect(env.fetch('my_test')['key']).to eq 'b'
11
13
  end
12
14
 
13
- it "should load hash values", :aggregate_failures do
15
+ it "loads hash values", :aggregate_failures do
14
16
  ENV['TESTO_DATA__ID'] = '1'
15
17
  ENV['TESTO_DATA__META__NAME'] = 'meta'
16
18
  ENV['TESTO_DATA__META__VAL'] = 'true'
17
- expect(env.testo['data']['id']).to eq 1
18
- expect(env.testo['data']['meta']['name']).to eq 'meta'
19
- expect(env.testo['data']['meta']['val']).to be_truthy
19
+ testo_config = env.fetch('testo')
20
+ expect(testo_config['data']['id']).to eq 1
21
+ expect(testo_config['data']['meta']['name']).to eq 'meta'
22
+ expect(testo_config['data']['meta']['val']).to be_truthy
20
23
  end
21
24
 
22
- it "should load array values", :aggregate_failures do
25
+ it "loads array values", :aggregate_failures do
23
26
  ENV['TESTO_DATA__IDS'] = '1,2, 3'
24
27
  ENV['TESTO_DATA__META__NAMES'] = 'meta, kotleta'
25
28
  ENV['TESTO_DATA__META__SIZE'] = '2'
26
29
  ENV['TESTO_DATA__TEXT'] = '"C\'mon, everybody"'
27
- expect(env.testo['data']['ids']).to include(1, 2, 3)
28
- expect(env.testo['data']['meta']['names']).to include('meta', 'kotleta')
29
- expect(env.testo['data']['meta']['size']).to eq 2
30
- expect(env.testo['data']['text']).to eq "C'mon, everybody"
30
+ testo_config = env.fetch('testo')
31
+ expect(testo_config['data']['ids']).to include(1, 2, 3)
32
+ expect(testo_config['data']['meta']['names']).to include('meta', 'kotleta')
33
+ expect(testo_config['data']['meta']['size']).to eq 2
34
+ expect(testo_config['data']['text']).to eq "C'mon, everybody"
31
35
  end
32
36
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Anyway::Ext::DeepDup do
6
+ using Anyway::Ext::DeepDup
7
+
8
+ it "duplicates nested arrays and hashes", :aggregate_failures do
9
+ source = {
10
+ a: 1,
11
+ b: 'hello',
12
+ c: {
13
+ id: 1,
14
+ list: [1, 2, { name: 'John' }]
15
+ },
16
+ d: [{ id: 1 }, { id: 2 }]
17
+ }
18
+
19
+ dup = source.deep_dup
20
+
21
+ expect(dup[:a]).to eq 1
22
+ expect(dup[:b]).to eq 'hello'
23
+ expect(dup[:c]).to eq(
24
+ id: 1,
25
+ list: [1, 2, { name: 'John' }]
26
+ )
27
+ expect(dup[:d]).to eq(
28
+ [{ id: 1 }, { id: 2 }]
29
+ )
30
+
31
+ expect(dup[:c]).not_to be_equal(source[:c])
32
+ expect(dup[:c][:list]).not_to be_equal(source[:c][:list])
33
+ expect(dup[:c][:list].last).not_to be_equal(source[:c][:list].last)
34
+
35
+ expect(dup[:d].first).not_to be_equal(source[:d].first)
36
+ expect(dup[:d].last).not_to be_equal(source[:d].last)
37
+ end
38
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
5
 
4
6
  begin
5
7
  require "pry-byebug"
6
- rescue LoadError
8
+ rescue LoadError # rubocop:disable all
7
9
  end
8
10
 
9
11
  ENV["RAILS_ENV"] = 'test'
10
12
 
11
13
  require File.expand_path("../dummy/config/environment", __FILE__)
12
- require 'anyway'
14
+ require 'anyway_config'
13
15
 
14
16
  Rails.application.eager_load!
15
17
 
@@ -17,4 +19,13 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
17
19
 
18
20
  RSpec.configure do |config|
19
21
  config.mock_with :rspec
22
+
23
+ config.example_status_persistence_file_path = "tmp/rspec_examples.txt"
24
+ config.filter_run :focus
25
+ config.run_all_when_everything_filtered = true
26
+
27
+ config.order = :random
28
+ Kernel.srand config.seed
29
+
30
+ config.before(:each) { Anyway.env.clear }
20
31
  end
@@ -1,15 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
5
 
4
6
  begin
5
7
  require "pry-byebug"
6
- rescue LoadError
8
+ rescue LoadError # rubocop:disable all
7
9
  end
8
10
 
9
- require 'anyway'
11
+ require 'anyway_config'
12
+ require 'erb'
10
13
 
11
14
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
12
15
 
13
16
  RSpec.configure do |config|
14
17
  config.mock_with :rspec
18
+
19
+ config.filter_run :focus
20
+ config.run_all_when_everything_filtered = true
21
+
22
+ config.order = :random
23
+ Kernel.srand config.seed
24
+
25
+ config.before(:each) { Anyway.env.clear }
15
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CoolConfig < Anyway::Config # :nodoc:
2
4
  config_name :cool
3
5
  attr_config :meta,
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Anyway
2
4
  class TestConfig < Anyway::Config # :nodoc:
3
- attr_config :test,
5
+ attr_config :test,
4
6
  api: { key: '' },
5
7
  log: {
6
8
  format: {
@@ -9,6 +11,6 @@ module Anyway
9
11
  },
10
12
  level: :info
11
13
  },
12
- log_levels: [:info, :fatal]
14
+ log_levels: %i[info fatal]
13
15
  end
14
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anyway_config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
- - Vlad Dem
7
+ - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-22 00:00:00.000000000 Z
11
+ date: 2017-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simplecov
@@ -38,7 +38,23 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 3.5.0
41
- description: Configuration for Ruby plugins and applications
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.49'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.49'
55
+ description: "\n Configuration DSL for Ruby libraries and applications.\n\n Allows
56
+ you to easily follow the twevle factor application principles (https://12factor.net/config).\n
57
+ \ "
42
58
  email:
43
59
  - dementiev.vm@gmail.com
44
60
  executables: []
@@ -46,16 +62,18 @@ extensions: []
46
62
  extra_rdoc_files: []
47
63
  files:
48
64
  - ".gitignore"
49
- - ".hound.yml"
50
65
  - ".rubocop.yml"
51
66
  - ".travis.yml"
67
+ - CHANGELOG.md
52
68
  - Gemfile
53
69
  - LICENSE.txt
54
70
  - README.md
55
71
  - Rakefile
56
72
  - anyway_config.gemspec
73
+ - config/cool.yml
57
74
  - gemfiles/rails42.gemfile
58
75
  - gemfiles/rails5.gemfile
76
+ - gemfiles/railsmaster.gemfile
59
77
  - lib/anyway.rb
60
78
  - lib/anyway/config.rb
61
79
  - lib/anyway/env.rb
@@ -64,10 +82,10 @@ files:
64
82
  - lib/anyway/ext/hash.rb
65
83
  - lib/anyway/rails/config.rb
66
84
  - lib/anyway/version.rb
85
+ - lib/anyway_config.rb
67
86
  - spec/anyway.yml
68
87
  - spec/config_spec.rb
69
88
  - spec/config_spec_norails.rb
70
- - spec/dummy.yml
71
89
  - spec/dummy/config.ru
72
90
  - spec/dummy/config/application.rb
73
91
  - spec/dummy/config/boot.rb
@@ -78,6 +96,7 @@ files:
78
96
  - spec/dummy/config/routes.rb
79
97
  - spec/dummy/config/secrets.yml
80
98
  - spec/env_spec.rb
99
+ - spec/ext/deep_dup_spec.rb
81
100
  - spec/spec_helper.rb
82
101
  - spec/spec_norails_helper.rb
83
102
  - spec/support/cool_config.rb
@@ -97,13 +116,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
116
  version: '2'
98
117
  required_rubygems_version: !ruby/object:Gem::Requirement
99
118
  requirements:
100
- - - ">="
119
+ - - ">"
101
120
  - !ruby/object:Gem::Version
102
- version: '0'
121
+ version: 1.3.1
103
122
  requirements: []
104
123
  rubyforge_project:
105
124
  rubygems_version: 2.6.4
106
125
  signing_key:
107
126
  specification_version: 4
108
- summary: Configuration for Ruby plugins and applications
127
+ summary: Configuration DSL for Ruby libraries and applications
109
128
  test_files: []
data/.hound.yml DELETED
@@ -1,12 +0,0 @@
1
- ruby:
2
- enabled: true
3
- config_file: .rubocop.yml
4
-
5
- javascript:
6
- enabled: false
7
-
8
- coffeescript:
9
- enabled: false
10
-
11
- sass:
12
- enabled: false
data/spec/dummy.yml DELETED
File without changes