ultra_settings 0.0.1.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 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: []