ultra_settings 0.0.1.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a4bf1774f001f4b527b419e5c1f19ed05556a86ecf8f88b0b07df9f828ca3c7b
4
+ data.tar.gz: a204f002cc7a2a5d0747cd00abd6d64f9b7facb899475a4f9d96c15eeaa8814e
5
+ SHA512:
6
+ metadata.gz: 1a9a7d61e85e0c0a3cd406535f33e978b1455cfcecb66cf8376ec3d76255540b35e950e39566c86b758004e3d80491d9267c4cccb6b5a889cd964d3b3119afe9
7
+ data.tar.gz: e6f32cbc8d56496a7486ed05bd388e8ab93229b1df2ac016e56c9fac610dbc39ddd29c89967ae5f2ca1029f8d34919b1bbde451b31c4262adde44adde68dfa8f
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## 1.0.0
8
+
9
+ ### Added
10
+ - Initial release.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2023 Brian Durand
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.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Unified Rails Configuration :construction:
2
+
3
+ [![Continuous Integration](https://github.com/bdurand/ultra_settings/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/bdurand/ultra_settings/actions/workflows/continuous_integration.yml)
4
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
5
+
6
+ TODO
7
+
8
+ ## Usage
9
+
10
+ ```ruby
11
+ UltraSettings.my_service.host
12
+
13
+ Rails.application.settings.my_service.host
14
+ ```
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem "ultra_settings"
22
+ ```
23
+
24
+ Then execute:
25
+ ```bash
26
+ $ bundle
27
+ ```
28
+
29
+ Or install it yourself as:
30
+ ```bash
31
+ $ gem install ultra_settings
32
+ ```
33
+
34
+ ## Contributing
35
+
36
+ Open a pull request on [GitHub](https://github.com/bdurand/ultra_settings).
37
+
38
+ Please use the [standardrb](https://github.com/testdouble/standard) syntax and lint your code with `standardrb --fix` before submitting.
39
+
40
+ ## License
41
+
42
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1.rc1
@@ -0,0 +1,216 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module UltraSettings
6
+ class Configuration
7
+ include Singleton
8
+
9
+ ALLOWED_NAME_PATTERN = /\A[a-z_][a-zA-Z0-9_]*\z/
10
+ ALLOWED_TYPES = [:string, :symbol, :integer, :float, :boolean, :datetime, :array].freeze
11
+
12
+ class_attribute :environment_variables_disabled, instance_accessor: false, default: false
13
+
14
+ class_attribute :runtime_settings_disabled, instance_accessor: false, default: false
15
+
16
+ class_attribute :yaml_config_disabled, instance_accessor: false, default: false
17
+
18
+ class_attribute :env_var_delimiter, instance_accessor: false, default: "_"
19
+
20
+ class_attribute :setting_delimiter, instance_accessor: false, default: "."
21
+
22
+ class_attribute :env_var_upcase, instance_accessor: false, default: true
23
+
24
+ class_attribute :setting_upcase, instance_accessor: false, default: false
25
+
26
+ class_attribute :yaml_config_directory, instance_accessor: false, default: "config"
27
+
28
+ class << self
29
+ def define(name, type: :string, default: nil, default_if: nil, static: false, setting: nil, env_var: nil, yaml_key: nil)
30
+ name = name.to_s
31
+ type = type.to_sym
32
+ static = !!static
33
+
34
+ unless name.match?(ALLOWED_NAME_PATTERN)
35
+ raise ArgumentError.new("Invalid name: #{name.inspect}")
36
+ end
37
+
38
+ unless ALLOWED_TYPES.include?(type)
39
+ raise ArgumentError.new("Invalid type: #{type.inspect}")
40
+ end
41
+
42
+ unless default_if.nil? || default_if.is_a?(Proc)
43
+ raise ArgumentError.new("default_if must be a Proc")
44
+ end
45
+
46
+ defined_fields[name] = Field.new(
47
+ name: name,
48
+ type: type,
49
+ default: default,
50
+ default_if: default_if,
51
+ env_var: env_var,
52
+ setting_name: setting,
53
+ yaml_key: yaml_key,
54
+ env_var_prefix: env_var_prefix,
55
+ env_var_upcase: env_var_upcase,
56
+ setting_prefix: setting_prefix,
57
+ setting_upcase: setting_upcase
58
+ )
59
+
60
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1 # rubocop:disable Security/Eval
61
+ def #{name}
62
+ __get_value__(#{name.inspect}, #{static.inspect})
63
+ end
64
+ RUBY
65
+
66
+ if type == :boolean
67
+ alias_method "#{name}?", name
68
+ end
69
+ end
70
+
71
+ def env_var_prefix=(value)
72
+ @env_var_prefix = value&.to_s
73
+ end
74
+
75
+ def env_var_prefix
76
+ unless defined?(@env_var_prefix)
77
+ @env_var_prefix = default_env_var_prefix
78
+ end
79
+ @env_var_prefix
80
+ end
81
+
82
+ def setting_prefix=(value)
83
+ @setting_prefix = value&.to_s
84
+ end
85
+
86
+ def setting_prefix
87
+ unless defined?(@setting_prefix)
88
+ @setting_prefix = default_setting_prefix
89
+ end
90
+ @setting_prefix
91
+ end
92
+
93
+ def configuration_file=(value)
94
+ value = Pathname.new(value) if value.is_a?(String)
95
+ value = Rails.root + value if value && !value.absolute?
96
+ @configuration_file = value
97
+ end
98
+
99
+ def configuration_file
100
+ unless defined?(@configuration_file)
101
+ @configuration_file = default_configuration_file
102
+ end
103
+ @configuration_file
104
+ end
105
+
106
+ def load_yaml_config
107
+ return nil unless configuration_file
108
+ return nil unless configuration_file.exist?
109
+
110
+ Rails.application.config_for(configuration_file)
111
+ end
112
+
113
+ private
114
+
115
+ def defined_fields
116
+ unless defined?(@defined_fields)
117
+ @defined_fields = {}
118
+ if superclass < Configuration
119
+ superclass.send(:defined_fields).each do |name, field|
120
+ @defined_fields[name] = Field.new(
121
+ name: field.name,
122
+ type: field.type,
123
+ default: field.default,
124
+ default_if: field.default_if,
125
+ env_var: field.env_var,
126
+ setting_name: field.setting_name,
127
+ yaml_key: field.yaml_key,
128
+ env_var_prefix: env_var_prefix,
129
+ env_var_upcase: env_var_upcase,
130
+ setting_prefix: setting_prefix,
131
+ setting_upcase: setting_upcase
132
+ )
133
+ end
134
+ end
135
+ end
136
+ @defined_fields
137
+ end
138
+
139
+ def root_name
140
+ name.sub(/Configuration\z/, "")
141
+ end
142
+
143
+ def default_configuration_file
144
+ path = Pathname.new(yaml_config_directory)
145
+ path = Rails.root + path if defined?(Rails) && !path.absolute?
146
+ path.join(*"#{root_name.underscore}.yml".split("/"))
147
+ end
148
+
149
+ def default_env_var_prefix
150
+ prefix = root_name.underscore.gsub("/", env_var_delimiter) + env_var_delimiter
151
+ prefix = prefix.upcase if env_var_upcase
152
+ prefix
153
+ end
154
+
155
+ def default_setting_prefix
156
+ prefix = root_name.underscore.gsub("/", setting_delimiter) + setting_delimiter
157
+ prefix = prefix.upcase if setting_upcase
158
+ prefix
159
+ end
160
+ end
161
+
162
+ def initialize
163
+ @mutex = Mutex.new
164
+ @memoized_values = {}
165
+ end
166
+
167
+ def [](name)
168
+ send(name.to_s) if include?(name)
169
+ end
170
+
171
+ def include?(name)
172
+ self.class.send(:defined_fields).include?(name.to_s)
173
+ end
174
+
175
+ private
176
+
177
+ def __get_value__(name, static)
178
+ if static && @memoized_values.include?(name)
179
+ return @memoized_values[name]
180
+ end
181
+
182
+ field = self.class.send(:defined_fields)[name]
183
+ return nil unless field
184
+
185
+ if !Rails.application.initialized? && !static
186
+ raise UltraSettings::NonStaticValueError.new("Cannot access non-static field #{name} during initialization")
187
+ end
188
+
189
+ env = ENV unless self.class.environment_variables_disabled?
190
+ settings = __runtime_settings__ unless static || self.class.runtime_settings_disabled?
191
+ yaml_config = __yaml_config__ unless self.class.yaml_config_disabled?
192
+
193
+ value = field.value(yaml_config: yaml_config, env: env, settings: settings)
194
+
195
+ if static
196
+ @mutex.synchronize do
197
+ if @memoized_values.include?(name)
198
+ value = @memoized_values[name]
199
+ else
200
+ @memoized_values[name] = value
201
+ end
202
+ end
203
+ end
204
+
205
+ value
206
+ end
207
+
208
+ def __runtime_settings__
209
+ SuperSettings
210
+ end
211
+
212
+ def __yaml_config__
213
+ @yaml_config ||= (self.class.load_yaml_config || {})
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UltraSettings
4
+ # Definition for a field on a configuration.
5
+ class Field
6
+ attr_reader :name
7
+ attr_reader :type
8
+ attr_reader :default
9
+ attr_reader :default_if
10
+ attr_reader :env_var
11
+ attr_reader :setting_name
12
+ attr_reader :yaml_key
13
+ attr_reader :env_var_prefix
14
+ attr_reader :env_var_upcase
15
+ attr_reader :setting_prefix
16
+ attr_reader :setting_upcase
17
+
18
+ # @param name [String, Symbol] The name of the field.
19
+ # @param type [Symbol] The type of the field.
20
+ # @param default [Object] The default value of the field.
21
+ # @param default_if [Proc] A proc that returns true if the default value should be used.
22
+ # @param env_var [String, Symbol] The name of the environment variable to use for the field.
23
+ # @param setting_name [String, Symbol] The name of the setting to use for the field.
24
+ # @param yaml_key [String, Symbol] The name of the YAML key to use for the field.
25
+ # @param env_var_prefix [String, Symbol] The prefix to use for the environment variable name.
26
+ # @param env_var_upcase [Boolean] Whether or not to upcase the environment variable name.
27
+ # @param setting_prefix [String, Symbol] The prefix to use for the setting name.
28
+ # @param setting_upcase [Boolean] Whether or not to upcase the setting name.
29
+ def initialize(
30
+ name:,
31
+ type: :string,
32
+ default: nil,
33
+ default_if: nil,
34
+ env_var: nil,
35
+ setting_name: nil,
36
+ yaml_key: nil,
37
+ env_var_prefix: nil,
38
+ env_var_upcase: true,
39
+ setting_prefix: nil,
40
+ setting_upcase: false
41
+ )
42
+ @name = frozen_string(name)
43
+ @type = type.to_sym
44
+ @default = coerce_value(default).freeze
45
+ @default_if = default_if
46
+ @env_var = frozen_string(env_var)
47
+ @setting_name = frozen_string(setting_name)
48
+ @yaml_key = frozen_string(yaml_key)
49
+ @env_var_prefix = frozen_string(env_var_prefix)
50
+ @env_var_upcase = !!env_var_upcase
51
+ @setting_prefix = frozen_string(setting_prefix)
52
+ @setting_upcase = !!setting_upcase
53
+ end
54
+
55
+ # Get the value for the field from the passed in state.
56
+ #
57
+ # @param env [#[]] The environment variables.
58
+ # @param settings [#[]] The runtime settings.
59
+ # @param yaml_config [#[]] The YAML configuration.
60
+ def value(env: nil, settings: nil, yaml_config: nil)
61
+ val = fetch_value(env: env, settings: settings, yaml_config: yaml_config)
62
+ val = coerce_value(val).freeze
63
+ val = @default if use_default?(val)
64
+ val
65
+ end
66
+
67
+ private
68
+
69
+ def fetch_value(env:, settings:, yaml_config:)
70
+ value = env_value(env) if env
71
+ value = nil if value == ""
72
+
73
+ if value.nil? && settings
74
+ value = runtime_value(settings)
75
+ value = nil if value == ""
76
+ end
77
+
78
+ if value.nil? && yaml_config
79
+ value = yaml_value(yaml_config)
80
+ value = nil if value == ""
81
+ end
82
+
83
+ value
84
+ end
85
+
86
+ def coerce_value(value)
87
+ return nil if value.nil?
88
+
89
+ case type
90
+ when :integer
91
+ value.is_a?(Integer) ? value : value.to_s&.to_i
92
+ when :float
93
+ value.is_a?(Float) ? value : value.to_s&.to_f
94
+ when :boolean
95
+ SuperSettings::Coerce.boolean(value)
96
+ when :datetime
97
+ SuperSettings::Coerce.time(value)
98
+ when :array
99
+ Array(value).map(&:to_s)
100
+ when :symbol
101
+ value.to_s.to_sym
102
+ else
103
+ value.to_s
104
+ end
105
+ end
106
+
107
+ def env_value(env)
108
+ var_name = env_var
109
+ if var_name.nil?
110
+ var_name = "#{env_var_prefix}#{name}"
111
+ var_name = var_name.upcase if env_var_upcase
112
+ end
113
+ env[var_name.to_s]
114
+ end
115
+
116
+ def runtime_value(settings)
117
+ var_name = setting_name
118
+ if var_name.nil?
119
+ var_name = "#{setting_prefix}#{name}"
120
+ var_name = var_name.upcase if setting_upcase
121
+ end
122
+ settings[var_name.to_s]
123
+ end
124
+
125
+ def yaml_value(yaml_config)
126
+ key = (yaml_key || name)
127
+ yaml_config[key.to_s]
128
+ end
129
+
130
+ def use_default?(value)
131
+ if value && @default_if
132
+ @default_if.call(value)
133
+ else
134
+ value.nil?
135
+ end
136
+ end
137
+
138
+ def frozen_string(value)
139
+ value&.to_s&.dup&.freeze
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "super_settings"
4
+
5
+ require_relative "ultra_settings/configuration"
6
+ require_relative "ultra_settings/field"
7
+
8
+ # This is the root namespace for UltraSettings. You can add configurations to
9
+ # this namespace using the add method.
10
+ #
11
+ # @example
12
+ # UltraSettings.add(:test)
13
+ # UltraSettings.test # => TestConfiguration.instance
14
+ module UltraSettings
15
+ @configurations = {}
16
+ @mutex = Mutex.new
17
+
18
+ class NonStaticValueError < StandardError
19
+ end
20
+
21
+ class << self
22
+ # Adds a configuration to the root namespace. The configuration will be
23
+ # available as a method on the UltraSettings module with the provide name.
24
+ #
25
+ # @param name [Symbol, String] The name of the configuration.
26
+ # @param klass [Class, String] The class of the configuration. If this is not
27
+ # provided then the class will be inferred from the name by camelizing the
28
+ # name and appending "Configuration" to get the class name.
29
+ # @return [void]
30
+ def add(name, klass = nil)
31
+ name = name.to_s
32
+ unless name.match?(/\A[a-z_][a-zA-Z0-9_]*\z/)
33
+ raise ArgementError.new("Invalid configuration name: #{name.inspect}")
34
+ end
35
+
36
+ class_name = klass&.to_s
37
+ class_name ||= "#{name.classify}Configuration"
38
+
39
+ @mutex.synchronize do
40
+ @configurations.delete(name)
41
+
42
+ eval <<-RUBY, binding, __FILE__, __LINE__ + 1 # rubocop:disable Security/Eval
43
+ def #{name}
44
+ __load_config__(#{name.inspect}, #{class_name.inspect})
45
+ end
46
+ RUBY
47
+ end
48
+
49
+ # Control if settings can be loaded from environment variables. By default
50
+ # environment variables are enabled. This can also be disabled on
51
+ # individual Configuration classes.
52
+ #
53
+ # @param value [Boolean] Whether or not to load settings from environment variables.
54
+ # @return [void]
55
+ def environment_variables_disabled=(value)
56
+ Configuration.environment_variables_disabled = !!value
57
+ end
58
+
59
+ # Control if settings can be loaded from runtime settings. By default
60
+ # runtime settings are enabled. This can also be disabled on individual
61
+ # Configuration classes.
62
+ #
63
+ # @param value [Boolean] Whether or not to load settings from runtime settings.
64
+ # @return [void]
65
+ def runtime_settings_disabled=(value)
66
+ Configuration.runtime_settings_disabled = !!value
67
+ end
68
+
69
+ # Control if settings can be loaded from YAML configuration files. By
70
+ # default YAML configuration is enabled. This can also be disabled on
71
+ # individual Configuration classes.
72
+ #
73
+ # @param value [Boolean] Whether or not to load settings from YAML configuration.
74
+ # @return [void]
75
+ def yaml_config_disabled=(value)
76
+ Configuration.yaml_config_disabled = !!value
77
+ end
78
+
79
+ # Set the delimiter to use when determining environment variable names.
80
+ # By default this is an underscore.
81
+ #
82
+ # @param value [String] The delimiter to use.
83
+ # @return [void]
84
+ def env_var_delimiter=(value)
85
+ Configuration.env_var_delimiter = value.to_s
86
+ end
87
+
88
+ # Set the delimiter to use when determining setting names. By default
89
+ # this is a period.
90
+ #
91
+ # @param value [String] The delimiter to use.
92
+ def setting_delimiter=(value)
93
+ Configuration.setting_delimiter = value.to_s
94
+ end
95
+
96
+ # Control if environment variable names should be upcased. By default
97
+ # this is true.
98
+ #
99
+ # @param value [Boolean] Whether or not to upcase environment variable names.
100
+ # @return [void]
101
+ def env_var_upcase=(value)
102
+ Configuration.env_var_upcase = !!value
103
+ end
104
+
105
+ # Control if setting names should be upcased. By default this is false.
106
+ #
107
+ # @param value [Boolean] Whether or not to upcase setting names.
108
+ # @return [void]
109
+ def setting_upcase=(value)
110
+ Configuration.setting_upcase = !!value
111
+ end
112
+
113
+ # Set the directory to use when loading YAML configuration files. By
114
+ # default this is the config directory in the Rails root.
115
+ #
116
+ # @param value [String, Pathname] The directory to use.
117
+ # @return [void]
118
+ def yaml_config_directory=(value)
119
+ Configuration.yaml_config_directory = value.to_s
120
+ end
121
+ end
122
+
123
+ private
124
+
125
+ # Load a configuration class.
126
+ def __load_config__(name, class_name)
127
+ klass = @configurations[name]
128
+
129
+ if klass && !Rails.configuration.cache_classes
130
+ klass = nil if klass != class_name.constantize
131
+ end
132
+
133
+ unless klass
134
+ klass = class_name.constantize
135
+ @mutex.synchronize do
136
+ unless klass < Configuration
137
+ raise TypeError.new("Configuration class #{class_name} does not inherit from UltraSettings::Configuration")
138
+ end
139
+ @configurations[name] = klass
140
+ end
141
+ end
142
+
143
+ klass.instance
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,36 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "ultra_settings"
3
+ spec.version = File.read(File.expand_path("../VERSION", __FILE__)).strip
4
+ spec.authors = ["Brian Durand"]
5
+ spec.email = ["bbdurand@gmail.com"]
6
+
7
+ spec.summary = "Unified configuration for Rails applications that allows for configuration via environment variables, YAML files, and dynamic runtime setting."
8
+
9
+ spec.homepage = "https://github.com/bdurand/ultra_settings"
10
+ spec.license = "MIT"
11
+
12
+ # Specify which files should be added to the gem when it is released.
13
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
14
+ ignore_files = %w[
15
+ .
16
+ Appraisals
17
+ Gemfile
18
+ Gemfile.lock
19
+ Rakefile
20
+ bin/
21
+ gemfiles/
22
+ spec/
23
+ ]
24
+ spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| ignore_files.any? { |path| f.start_with?(path) } }
26
+ end
27
+
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.required_ruby_version = ">= 2.5"
31
+
32
+ spec.add_dependency "rails", ">= 5"
33
+ spec.add_dependency "super_settings"
34
+
35
+ spec.add_development_dependency "bundler"
36
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ultra_settings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.rc1
5
+ platform: ruby
6
+ authors:
7
+ - Brian Durand
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-06-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: super_settings
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - bbdurand@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - CHANGELOG.md
63
+ - MIT-LICENSE
64
+ - README.md
65
+ - VERSION
66
+ - lib/ultra_settings.rb
67
+ - lib/ultra_settings/configuration.rb
68
+ - lib/ultra_settings/field.rb
69
+ - ultra_settings.gemspec
70
+ homepage: https://github.com/bdurand/ultra_settings
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '2.5'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">"
86
+ - !ruby/object:Gem::Version
87
+ version: 1.3.1
88
+ requirements: []
89
+ rubygems_version: 3.2.22
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Unified configuration for Rails applications that allows for configuration
93
+ via environment variables, YAML files, and dynamic runtime setting.
94
+ test_files: []