anyway_config 0.5.1 → 1.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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