smart_config 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2916bd8a506f8c74af2f8b00729d7ba04241159b7ea993090b0010b82657b62e
4
- data.tar.gz: 55d1eadaf37c20f76de2ff01e21b23aba1448eedae035404c739d0a7b2d74cff
3
+ metadata.gz: 79021decd1e8da1ca164f03eb52d4e4291516844c5142ae38c11d1ba88f967f7
4
+ data.tar.gz: 728aaac6723424090f3c5b53cbb0289ac003fb40b1429b7ed5c7ebef71f3690b
5
5
  SHA512:
6
- metadata.gz: 04f2a8e1094f315d3afe3e47d0dc42fbd305d079abd11024b0f8b2762c4f0154f23a5deda724c6223b4b08cd784f0e4836777354595f401102cc59d573a0276e
7
- data.tar.gz: 59ee036cb4a4253af357017db22662e01c6765d589282939e2638e422e303f5e97213ee91395fe009e9b1a11f8e795c15f86adb11130a59d862f6c08a65e3917
6
+ metadata.gz: 3e4754d90251092a7ae9d31b8a16ab855ce4630f2e1595e23b0b532bec60c383e5d1a26c08319bf2f72683ff5147681eb4549ad880a1e2cf764be302965be0cc
7
+ data.tar.gz: ad94e8af908a5a4cd9da816552af14374187a6d18c643fad444a893b5a87319e845b993af1fbb4326f08b61f36b0434c399b7f062678e7b9a9179baaf2fd3971
data/README.md CHANGED
@@ -17,20 +17,22 @@ Add the `smart_gem` dependency to you Gemfile:
17
17
  gem 'smart_gem'
18
18
  ```
19
19
 
20
+ ### Usage
21
+
20
22
  Then, create a new config class that, and define the configuration you need:
21
23
 
22
- ```
24
+ ```ruby
23
25
  class Config
24
26
  extend SmartConfig::Config
25
27
 
26
28
  # Optional. Will default to `config/config.yml`
27
29
  config_path 'config/app_config.yml'
28
30
 
29
- value :app_name
31
+ value :app_name, default: 'My App'
30
32
 
31
33
  group :smtp do
32
34
  value :hostname
33
- value :port
35
+ value :port, format: :integer
34
36
  value :username
35
37
  value :password
36
38
  end
@@ -54,4 +56,31 @@ Then, within your application, you can call:
54
56
  Config.redis.connection.hostname
55
57
  ```
56
58
 
57
- To access the configuration value.
59
+ To access the configuration value, from the following YAML file for example:
60
+
61
+ ```yaml
62
+ redis:
63
+ connection:
64
+ hostname: 'localhost'
65
+ ```
66
+
67
+ For values that are not in the YAML config, the tool will try reading it from environment variables, such as (from the previous configuration):
68
+
69
+ ```
70
+ REDIS_CONNECTION_PASSWORD
71
+ ```
72
+
73
+ #### Value Options
74
+
75
+ Values can use options, which can be set after the value name. For example:
76
+
77
+ ```ruby
78
+ value :hostname, default: 'localhost'
79
+ ```
80
+
81
+ All available options are:
82
+
83
+ | name | description |
84
+ |-----------|----------------------------------------------------------------------------------------------------------------------------------------------------|
85
+ | default | Sets a default value for the field, if no configuration could be found. If this option is not set, getting an unset field will raise an exception. |
86
+ | format | Sets the format of the field. If this option is not set, the field will be formatted as string. |
@@ -22,11 +22,17 @@ module SmartConfig
22
22
  @config_path
23
23
  end
24
24
 
25
- def data
26
- @data ||= [
27
- YAML.load_file(config_file_path),
28
- ENV.to_h.transform_keys(&:downcase)
29
- ]
25
+ def walker
26
+ @walker ||= SmartConfig::Walker.new([
27
+ {
28
+ data: config_file_path,
29
+ strategy: :nested
30
+ },
31
+ {
32
+ data: ENV.to_h.transform_keys(&:downcase),
33
+ strategy: :flat
34
+ }
35
+ ])
30
36
  end
31
37
  end
32
38
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartConfig
4
+ module Formatters
5
+ #
6
+ # Boolean formats the value into a boolean
7
+ class Boolean
8
+ def self.format(value)
9
+ ['true', '1', 1, true].include?(value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartConfig
4
+ module Formatters
5
+ #
6
+ # Float formats the value into a float
7
+ class Float
8
+ def self.format(value)
9
+ return nil if value.nil?
10
+
11
+ value.to_f
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartConfig
4
+ module Formatters
5
+ #
6
+ # Integer formats the value into an integer
7
+ class Integer
8
+ def self.format(value)
9
+ return nil if value.nil?
10
+
11
+ value.to_i
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartConfig
4
+ module Formatters
5
+ #
6
+ # String formats the value into a string
7
+ class String
8
+ def self.format(value)
9
+ value
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartConfig
4
+ #
5
+ # Formatters define behaviors to format values into another type
6
+ # This is especially useful for environment variables, which are always strings
7
+ #
8
+ module Formatters
9
+ def self.find(format)
10
+ SmartConfig::Formatters.const_get(camelize(format))
11
+ end
12
+
13
+ def self.camelize(format)
14
+ format.to_s.split('_').collect(&:capitalize).join
15
+ end
16
+ end
17
+ end
18
+
19
+ require 'smart_config/formatters/string'
20
+ require 'smart_config/formatters/integer'
21
+ require 'smart_config/formatters/float'
22
+ require 'smart_config/formatters/boolean'
@@ -9,16 +9,14 @@ module SmartConfig
9
9
  class Group
10
10
  include SmartConfig::Values
11
11
 
12
- def initialize(name, parent, &)
13
- @name = name
14
- @parent = parent
12
+ def initialize(namespace, walker, &)
13
+ @namespace = namespace
14
+ @walker = walker
15
15
  instance_exec(&)
16
16
  end
17
17
 
18
18
  private
19
19
 
20
- def data
21
- @data ||= @parent.get_path(@name)
22
- end
20
+ attr_reader :walker
23
21
  end
24
22
  end
@@ -7,14 +7,17 @@ module SmartConfig
7
7
  # Handles the retrieval of values, but with already provided data.
8
8
  #
9
9
  module Values
10
- def value(name)
10
+ attr_reader :namespace
11
+
12
+ def value(name, *opts)
11
13
  @config ||= {}
12
- @config[name.to_sym] = {}
14
+ @config[name.to_sym] = opts.reduce({}, :merge)
13
15
  end
14
16
 
15
17
  def group(name, &)
16
18
  @config ||= {}
17
- @config[name.to_sym] = SmartConfig::Group.new(name, self, &)
19
+ @config[name.to_sym] ||= {}
20
+ @config[name.to_sym][:group] = SmartConfig::Group.new([namespace, name].compact.flatten, walker, &)
18
21
  end
19
22
 
20
23
  def keys
@@ -22,7 +25,7 @@ module SmartConfig
22
25
  end
23
26
 
24
27
  def method_missing(name, *args, &)
25
- return get_value(name) if keys.include?(name)
28
+ return format_value(name, get_value(name)) if keys.include?(name)
26
29
 
27
30
  super
28
31
  end
@@ -34,26 +37,31 @@ module SmartConfig
34
37
  end
35
38
 
36
39
  def get_value(name)
37
- path = get_path(name)
40
+ return @config[name][:group] if @config[name].key?(:group)
41
+
42
+ path = walker.walk(full_name(name))
43
+ return path.first unless path.first.nil?
44
+ return @config[name][:default] if @config[name].key?(:default)
38
45
 
39
- case @config[name]
40
- when SmartConfig::Group
41
- @config[name]
42
- else
43
- path.first
44
- end
46
+ raise SmartConfig::MissingConfigValue, full_name(name)
45
47
  end
46
48
 
47
- def get_path(name)
48
- name = name.to_s
49
- data.map { |a| a[name] }.compact
49
+ def format_value(name, value)
50
+ @formatters ||= {}
51
+
52
+ @formatters[name] ||= SmartConfig::Formatters.find(@config[name].fetch(:format, :string))
53
+ @formatters[name].format(value)
50
54
  end
51
55
 
52
56
  private
53
57
 
54
- # Getting the data needs to be implemented by a lateral module
55
- def data
58
+ # Getting the data through a walker needs to be implemented by a lateral module
59
+ def walker
56
60
  raise NotImplementedError
57
61
  end
62
+
63
+ def full_name(name)
64
+ [namespace, name.to_s].compact.flatten.join('.')
65
+ end
58
66
  end
59
67
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SmartConfig
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.2'
5
5
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module SmartConfig
6
+ #
7
+ # Loads the data from any configured source and walks through it to find
8
+ # values
9
+ #
10
+ class Walker
11
+ def initialize(sources)
12
+ @sources = sources
13
+ end
14
+
15
+ def walk(path)
16
+ data.filter_map do |d|
17
+ next if d[:data].nil?
18
+
19
+ case d[:strategy]
20
+ when :nested
21
+ d[:data].dig(*path.split('.'))
22
+ when :flat
23
+ d[:data][path.tr('.', '_')]
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def data
31
+ @data ||= @sources.filter_map do |s|
32
+ {
33
+ data: load_source(s[:data]),
34
+ strategy: s[:strategy]
35
+ }
36
+ end
37
+ end
38
+
39
+ def load_source(name)
40
+ case name
41
+ when Hash
42
+ name
43
+ when /\.(yml|yaml)$/
44
+ YAML.load_file(name)
45
+ end
46
+ rescue Errno::ENOENT
47
+ nil
48
+ end
49
+ end
50
+ end
data/lib/smart_config.rb CHANGED
@@ -3,8 +3,12 @@
3
3
  #
4
4
  # The main SmartConfig module. See documentation for the sub modules.
5
5
  #
6
- module SmartConfig; end
6
+ module SmartConfig
7
+ class MissingConfigValue < StandardError; end
8
+ end
7
9
 
10
+ require 'smart_config/formatters'
11
+ require 'smart_config/walker'
8
12
  require 'smart_config/values'
9
13
  require 'smart_config/group'
10
14
  require 'smart_config/config'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien MATHIEU
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-28 00:00:00.000000000 Z
11
+ date: 2024-03-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Define and access static configuration, from a YAML config file, or environment
14
14
  variables
@@ -22,9 +22,15 @@ files:
22
22
  - README.md
23
23
  - lib/smart_config.rb
24
24
  - lib/smart_config/config.rb
25
+ - lib/smart_config/formatters.rb
26
+ - lib/smart_config/formatters/boolean.rb
27
+ - lib/smart_config/formatters/float.rb
28
+ - lib/smart_config/formatters/integer.rb
29
+ - lib/smart_config/formatters/string.rb
25
30
  - lib/smart_config/group.rb
26
31
  - lib/smart_config/values.rb
27
32
  - lib/smart_config/version.rb
33
+ - lib/smart_config/walker.rb
28
34
  homepage: https://github.com/dmathieu/smart_config
29
35
  licenses:
30
36
  - MIT