ultra_settings 0.0.1.rc1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +320 -2
- data/VERSION +1 -1
- data/app/application.css +85 -0
- data/app/application.js +19 -0
- data/app/index.html.erb +93 -0
- data/app/layout.css +27 -0
- data/app/layout.html.erb +21 -0
- data/lib/ultra_settings/coerce.rb +98 -0
- data/lib/ultra_settings/configuration.rb +378 -79
- data/lib/ultra_settings/field.rb +57 -88
- data/lib/ultra_settings/rack_app.rb +21 -0
- data/lib/ultra_settings/railtie.rb +33 -0
- data/lib/ultra_settings/version.rb +5 -0
- data/lib/ultra_settings/web_view.rb +38 -0
- data/lib/ultra_settings/yaml_config.rb +78 -0
- data/lib/ultra_settings.rb +167 -74
- data/ultra_settings.gemspec +3 -4
- metadata +18 -35
data/lib/ultra_settings/field.rb
CHANGED
@@ -5,51 +5,41 @@ module UltraSettings
|
|
5
5
|
class Field
|
6
6
|
attr_reader :name
|
7
7
|
attr_reader :type
|
8
|
+
attr_reader :description
|
8
9
|
attr_reader :default
|
9
10
|
attr_reader :default_if
|
10
11
|
attr_reader :env_var
|
11
|
-
attr_reader :
|
12
|
+
attr_reader :runtime_setting
|
12
13
|
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
14
|
|
18
15
|
# @param name [String, Symbol] The name of the field.
|
19
16
|
# @param type [Symbol] The type of the field.
|
17
|
+
# @param description [String] The description of the field.
|
20
18
|
# @param default [Object] The default value of the field.
|
21
19
|
# @param default_if [Proc] A proc that returns true if the default value should be used.
|
22
20
|
# @param env_var [String, Symbol] The name of the environment variable to use for the field.
|
23
|
-
# @param
|
21
|
+
# @param runtime_setting [String, Symbol] The name of the setting to use for the field.
|
24
22
|
# @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
23
|
def initialize(
|
30
24
|
name:,
|
31
25
|
type: :string,
|
26
|
+
description: nil,
|
32
27
|
default: nil,
|
33
28
|
default_if: nil,
|
34
29
|
env_var: nil,
|
35
|
-
|
30
|
+
runtime_setting: nil,
|
36
31
|
yaml_key: nil,
|
37
|
-
|
38
|
-
env_var_upcase: true,
|
39
|
-
setting_prefix: nil,
|
40
|
-
setting_upcase: false
|
32
|
+
static: false
|
41
33
|
)
|
42
|
-
@name =
|
34
|
+
@name = name.to_s.freeze
|
43
35
|
@type = type.to_sym
|
44
|
-
@
|
36
|
+
@description = description&.to_s&.freeze
|
37
|
+
@default = Coerce.coerce_value(default, @type).freeze
|
45
38
|
@default_if = default_if
|
46
|
-
@env_var =
|
47
|
-
@
|
48
|
-
@yaml_key =
|
49
|
-
@
|
50
|
-
@env_var_upcase = !!env_var_upcase
|
51
|
-
@setting_prefix = frozen_string(setting_prefix)
|
52
|
-
@setting_upcase = !!setting_upcase
|
39
|
+
@env_var = env_var&.to_s&.freeze
|
40
|
+
@runtime_setting = runtime_setting&.to_s&.freeze
|
41
|
+
@yaml_key = yaml_key&.to_s&.freeze
|
42
|
+
@static = !!static
|
53
43
|
end
|
54
44
|
|
55
45
|
# Get the value for the field from the passed in state.
|
@@ -58,85 +48,64 @@ module UltraSettings
|
|
58
48
|
# @param settings [#[]] The runtime settings.
|
59
49
|
# @param yaml_config [#[]] The YAML configuration.
|
60
50
|
def value(env: nil, settings: nil, yaml_config: nil)
|
61
|
-
|
62
|
-
val = coerce_value(val).freeze
|
63
|
-
val = @default if use_default?(val)
|
64
|
-
val
|
51
|
+
fetch_value_and_source(env: env, settings: settings, yaml_config: yaml_config).first
|
65
52
|
end
|
66
53
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
54
|
+
# Get the source for the field from the passed in state.
|
55
|
+
#
|
56
|
+
# @param env [Hash] The environment variables.
|
57
|
+
# @param settings [Hash] The runtime settings.
|
58
|
+
# @param yaml_config [Hash] The YAML configuration.
|
59
|
+
# @return [Symbol, nil] The source of the value (:env, :settings, or :yaml).
|
60
|
+
def source(env: nil, settings: nil, yaml_config: nil)
|
61
|
+
fetch_value_and_source(env: env, settings: settings, yaml_config: yaml_config).last
|
62
|
+
end
|
77
63
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
64
|
+
# Coerce the passed in value to the type of the field.
|
65
|
+
#
|
66
|
+
# @param value [Object] The value to coerce.
|
67
|
+
# @return [Object] The coerced value.
|
68
|
+
def coerce(value)
|
69
|
+
Coerce.coerce_value(value, @type)
|
70
|
+
end
|
82
71
|
|
83
|
-
|
72
|
+
# Returns true if the field is static.
|
73
|
+
#
|
74
|
+
# @return [Boolean]
|
75
|
+
def static?
|
76
|
+
@static
|
84
77
|
end
|
85
78
|
|
86
|
-
|
87
|
-
|
79
|
+
private
|
80
|
+
|
81
|
+
def fetch_value_and_source(env:, settings:, yaml_config:)
|
82
|
+
source = nil
|
88
83
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
value
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
value.to_s.to_sym
|
84
|
+
value = env[env_var] if env && env_var
|
85
|
+
value = nil if value == ""
|
86
|
+
if value.nil?
|
87
|
+
value = settings[runtime_setting] if settings && runtime_setting
|
88
|
+
value = nil if value == ""
|
89
|
+
if value.nil?
|
90
|
+
value = yaml_value(yaml_config)
|
91
|
+
value = nil if value == ""
|
92
|
+
source = :yaml unless value.nil?
|
93
|
+
else
|
94
|
+
source = :settings
|
95
|
+
end
|
102
96
|
else
|
103
|
-
|
97
|
+
source = :env
|
104
98
|
end
|
105
|
-
end
|
106
99
|
|
107
|
-
|
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
|
100
|
+
value = coerce(value).freeze
|
115
101
|
|
116
|
-
|
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]
|
102
|
+
[value, source]
|
123
103
|
end
|
124
104
|
|
125
105
|
def yaml_value(yaml_config)
|
126
|
-
|
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
|
106
|
+
return nil unless yaml_config && yaml_key
|
137
107
|
|
138
|
-
|
139
|
-
value&.to_s&.dup&.freeze
|
108
|
+
yaml_config[yaml_key]
|
140
109
|
end
|
141
110
|
end
|
142
111
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UltraSettings
|
4
|
+
# Rack application for displaying the current settings in an HTML page.
|
5
|
+
# No setting values are displayed, but you should still add some
|
6
|
+
# sort of authentication if you want to use this in production.
|
7
|
+
class RackApp
|
8
|
+
def call(env)
|
9
|
+
[200, {"content-type" => "text/html; charset=utf8"}, [webview.render_settings]]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def webview
|
15
|
+
if ENV.fetch("RAILS_ENV", ENV.fetch("RACK_ENV", "development")) == "development"
|
16
|
+
@webview = nil
|
17
|
+
end
|
18
|
+
@webview ||= WebView.new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UltraSettings
|
4
|
+
# Railtie to automatically configure settings for Rails applications.
|
5
|
+
# By default this will automatically load any configuration classes in the
|
6
|
+
# app/configurations directory. This can be customized by setting the
|
7
|
+
# `config.ultra_settings.auto_load_directories` option.
|
8
|
+
class Railtie < Rails::Railtie
|
9
|
+
config.ultra_settings = ActiveSupport::OrderedOptions.new
|
10
|
+
config.ultra_settings.auto_load_directories = [File.join("app", "configurations")]
|
11
|
+
|
12
|
+
config.before_configuration do
|
13
|
+
UltraSettings.yaml_config_env = Rails.env
|
14
|
+
UltraSettings.yaml_config_path = Rails.root.join("config")
|
15
|
+
end
|
16
|
+
|
17
|
+
# Automatically register any configuration classes in the app/configurations
|
18
|
+
# directory. The path to load can be customized by setting the
|
19
|
+
# `config.ultra_settings.auto_load_directory` option.
|
20
|
+
config.after_initialize do
|
21
|
+
Array(Rails.application.config.ultra_settings.auto_load_directories).each do |directory|
|
22
|
+
next unless directory
|
23
|
+
|
24
|
+
app_config_dir = Rails.root.join(directory)
|
25
|
+
app_config_dir.glob("**/*_configuration.rb").each do |file_path|
|
26
|
+
config_name = file_path.basename("_configuration.rb")
|
27
|
+
class_name = file_path.relative_path_from(app_config_dir).to_s.chomp(".rb").classify
|
28
|
+
UltraSettings.add(config_name, class_name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UltraSettings
|
4
|
+
# Helper class for rendering the settings information in an HTML page.
|
5
|
+
class WebView
|
6
|
+
attr_reader :css
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@index_template = erb_template("index.html.erb")
|
10
|
+
@layout_template = erb_template("layout.html.erb")
|
11
|
+
@layout_css = read_app_file("layout.css")
|
12
|
+
@css = read_app_file("application.css")
|
13
|
+
@javascript = read_app_file("application.js")
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_settings
|
17
|
+
@layout_template.result(binding)
|
18
|
+
end
|
19
|
+
|
20
|
+
def content
|
21
|
+
@index_template.result(binding)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def erb_template(path)
|
27
|
+
ERB.new(read_app_file(path))
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_app_file(path)
|
31
|
+
File.read(File.join(app_dir, path))
|
32
|
+
end
|
33
|
+
|
34
|
+
def app_dir
|
35
|
+
File.expand_path(File.join("..", "..", "app"), __dir__)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UltraSettings
|
4
|
+
# Helper class to load YAML configuration files. Any ERB markup in the YAML
|
5
|
+
# file will be evaluated. The YAML file should be structured like this:
|
6
|
+
#
|
7
|
+
# ```yaml
|
8
|
+
# shared:
|
9
|
+
# foo: bar
|
10
|
+
# bar: baz
|
11
|
+
#
|
12
|
+
# development:
|
13
|
+
# bar: qux
|
14
|
+
# biz: buz
|
15
|
+
#
|
16
|
+
# test:
|
17
|
+
# bar: qix
|
18
|
+
# biz: biz
|
19
|
+
# ```
|
20
|
+
#
|
21
|
+
# The section with the key matching the environment name is merged into
|
22
|
+
# the shared section. In this example, the development environment would
|
23
|
+
# have the following configuration:
|
24
|
+
#
|
25
|
+
# ```ruby
|
26
|
+
# {
|
27
|
+
# "foo" => "bar",
|
28
|
+
# "bar" => "qux",
|
29
|
+
# "biz" => "buz"
|
30
|
+
# }
|
31
|
+
# ```
|
32
|
+
#
|
33
|
+
# In addition, the keys are flattened into a one level deep hash with dots
|
34
|
+
# separating the keys.
|
35
|
+
class YamlConfig
|
36
|
+
def initialize(path, environment)
|
37
|
+
yaml = load_yaml(path)
|
38
|
+
@config = environment_config(yaml, environment)
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_h
|
42
|
+
@config
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def load_yaml(path)
|
48
|
+
yaml = File.read(path)
|
49
|
+
|
50
|
+
if yaml.include?("<%")
|
51
|
+
yaml = ERB.new(yaml).result
|
52
|
+
end
|
53
|
+
|
54
|
+
hash = YAML.load(yaml) # rubocop:disable Security/YAMLLoad
|
55
|
+
hash = {} unless hash.is_a?(Hash)
|
56
|
+
hash
|
57
|
+
end
|
58
|
+
|
59
|
+
def environment_config(yaml, environment)
|
60
|
+
shared = flatten_hash(yaml.fetch("shared", {}))
|
61
|
+
env = flatten_hash(yaml.fetch(environment, {}))
|
62
|
+
shared.merge(env)
|
63
|
+
end
|
64
|
+
|
65
|
+
def flatten_hash(hash, prefix = nil)
|
66
|
+
hash.each_with_object({}) do |(key, value), result|
|
67
|
+
key = key.to_s
|
68
|
+
key = "#{prefix}.#{key}" if prefix
|
69
|
+
|
70
|
+
if value.is_a?(Hash)
|
71
|
+
result.merge!(flatten_hash(value, key))
|
72
|
+
else
|
73
|
+
result[key] = value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/ultra_settings.rb
CHANGED
@@ -1,9 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "erb"
|
4
|
+
require "yaml"
|
5
|
+
require "time"
|
6
|
+
require "pathname"
|
7
|
+
require "singleton"
|
4
8
|
|
5
9
|
require_relative "ultra_settings/configuration"
|
10
|
+
require_relative "ultra_settings/coerce"
|
6
11
|
require_relative "ultra_settings/field"
|
12
|
+
require_relative "ultra_settings/rack_app"
|
13
|
+
require_relative "ultra_settings/web_view"
|
14
|
+
require_relative "ultra_settings/yaml_config"
|
15
|
+
require_relative "ultra_settings/version"
|
16
|
+
|
17
|
+
if defined?(Rails::Railtie)
|
18
|
+
require_relative "ultra_settings/railtie"
|
19
|
+
end
|
7
20
|
|
8
21
|
# This is the root namespace for UltraSettings. You can add configurations to
|
9
22
|
# this namespace using the add method.
|
@@ -12,12 +25,11 @@ require_relative "ultra_settings/field"
|
|
12
25
|
# UltraSettings.add(:test)
|
13
26
|
# UltraSettings.test # => TestConfiguration.instance
|
14
27
|
module UltraSettings
|
28
|
+
VALID_NAME__PATTERN = /\A[a-z_][a-zA-Z0-9_]*\z/
|
29
|
+
|
15
30
|
@configurations = {}
|
16
31
|
@mutex = Mutex.new
|
17
32
|
|
18
|
-
class NonStaticValueError < StandardError
|
19
|
-
end
|
20
|
-
|
21
33
|
class << self
|
22
34
|
# Adds a configuration to the root namespace. The configuration will be
|
23
35
|
# available as a method on the UltraSettings module with the provide name.
|
@@ -29,15 +41,15 @@ module UltraSettings
|
|
29
41
|
# @return [void]
|
30
42
|
def add(name, klass = nil)
|
31
43
|
name = name.to_s
|
32
|
-
unless name.match?(
|
44
|
+
unless name.match?(VALID_NAME__PATTERN)
|
33
45
|
raise ArgementError.new("Invalid configuration name: #{name.inspect}")
|
34
46
|
end
|
35
47
|
|
36
48
|
class_name = klass&.to_s
|
37
|
-
class_name ||= "#{name
|
49
|
+
class_name ||= "#{classify(name)}Configuration"
|
38
50
|
|
39
51
|
@mutex.synchronize do
|
40
|
-
@configurations
|
52
|
+
@configurations[name] = class_name
|
41
53
|
|
42
54
|
eval <<-RUBY, binding, __FILE__, __LINE__ + 1 # rubocop:disable Security/Eval
|
43
55
|
def #{name}
|
@@ -45,93 +57,158 @@ module UltraSettings
|
|
45
57
|
end
|
46
58
|
RUBY
|
47
59
|
end
|
60
|
+
end
|
48
61
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
Configuration.environment_variables_disabled = !!value
|
57
|
-
end
|
62
|
+
# Returns true if the provided class has been added as a configuration.
|
63
|
+
#
|
64
|
+
# @param class_name [Class, String] The name of the configuration class.
|
65
|
+
# @return [Boolean]
|
66
|
+
def include?(class_name)
|
67
|
+
@configurations.values.collect(&:to_s).include?(class_name.to_s)
|
68
|
+
end
|
58
69
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
70
|
+
# Control if settings can be loaded from environment variables. By default
|
71
|
+
# environment variables are enabled. This can also be disabled on
|
72
|
+
# individual Configuration classes.
|
73
|
+
#
|
74
|
+
# @param value [Boolean] Whether or not to load settings from environment variables.
|
75
|
+
# @return [void]
|
76
|
+
def environment_variables_disabled=(value)
|
77
|
+
Configuration.environment_variables_disabled = !!value
|
78
|
+
end
|
68
79
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
80
|
+
# Control if settings can be loaded from runtime settings. By default
|
81
|
+
# runtime settings are enabled. This can also be disabled on individual
|
82
|
+
# Configuration classes.
|
83
|
+
#
|
84
|
+
# @param value [Boolean] Whether or not to load settings from runtime settings.
|
85
|
+
# @return [void]
|
86
|
+
def runtime_settings_disabled=(value)
|
87
|
+
Configuration.runtime_settings_disabled = !!value
|
88
|
+
end
|
78
89
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
90
|
+
# Control if settings can be loaded from YAML configuration files. By
|
91
|
+
# default YAML configuration is enabled. This can also be disabled on
|
92
|
+
# individual Configuration classes.
|
93
|
+
#
|
94
|
+
# @param value [Boolean] Whether or not to load settings from YAML configuration.
|
95
|
+
# @return [void]
|
96
|
+
def yaml_config_disabled=(value)
|
97
|
+
Configuration.yaml_config_disabled = !!value
|
98
|
+
end
|
87
99
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
100
|
+
# Set the environment to use when loading YAML configuration files.
|
101
|
+
# In a Rails application this will be the current Rails environment.
|
102
|
+
# Defaults to "development".
|
103
|
+
#
|
104
|
+
# @param value [String] The environment name to use.
|
105
|
+
def yaml_config_env=(value)
|
106
|
+
Configuration.yaml_config_env = value
|
107
|
+
end
|
95
108
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
109
|
+
# Set the delimiter to use when determining environment variable names.
|
110
|
+
# By default this is an underscore.
|
111
|
+
#
|
112
|
+
# @param value [String] The delimiter to use.
|
113
|
+
# @return [void]
|
114
|
+
def env_var_delimiter=(value)
|
115
|
+
Configuration.env_var_delimiter = value.to_s
|
116
|
+
end
|
117
|
+
|
118
|
+
# Set the delimiter to use when determining setting names. By default
|
119
|
+
# this is a period.
|
120
|
+
#
|
121
|
+
# @param value [String] The delimiter to use.
|
122
|
+
def runtime_setting_delimiter=(value)
|
123
|
+
Configuration.runtime_setting_delimiter = value.to_s
|
124
|
+
end
|
125
|
+
|
126
|
+
# Control if environment variable names should be upcased. By default
|
127
|
+
# this is true.
|
128
|
+
#
|
129
|
+
# @param value [Boolean] Whether or not to upcase environment variable names.
|
130
|
+
# @return [void]
|
131
|
+
def env_var_upcase=(value)
|
132
|
+
Configuration.env_var_upcase = !!value
|
133
|
+
end
|
134
|
+
|
135
|
+
# Control if setting names should be upcased. By default this is false.
|
136
|
+
#
|
137
|
+
# @param value [Boolean] Whether or not to upcase setting names.
|
138
|
+
# @return [void]
|
139
|
+
def runtime_setting_upcase=(value)
|
140
|
+
Configuration.runtime_setting_upcase = !!value
|
141
|
+
end
|
142
|
+
|
143
|
+
# Set the directory to use when loading YAML configuration files.
|
144
|
+
# In a Rails application this will be the config directory.
|
145
|
+
# Otherwise it will be the current working directory.
|
146
|
+
#
|
147
|
+
# @param value [String, Pathname] The directory to use.
|
148
|
+
# @return [void]
|
149
|
+
def yaml_config_path=(value)
|
150
|
+
Configuration.yaml_config_path = value.to_s
|
151
|
+
end
|
152
|
+
|
153
|
+
# Set the object to use for runtime settings. This can be any object that
|
154
|
+
# responds to the [] method. If you are using the `super_settings` gem,
|
155
|
+
# you can set this to `SuperSettings`.
|
156
|
+
attr_writer :runtime_settings
|
104
157
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
158
|
+
# Get the object to use for runtime settings.
|
159
|
+
#
|
160
|
+
# @return [Object, nil]
|
161
|
+
# @api private
|
162
|
+
def __runtime_settings__
|
163
|
+
@runtime_settings ||= nil
|
164
|
+
end
|
165
|
+
|
166
|
+
# Explicitly set setting values within a block. This is useful for testing
|
167
|
+
# or other situations where you want hard code a specific set of values.
|
168
|
+
#
|
169
|
+
# @param settings [Hash] The settings to set.
|
170
|
+
# @return [Object] The result of the block.
|
171
|
+
def override!(settings, &block)
|
172
|
+
settings = settings.to_a
|
173
|
+
config_name, values = settings.first
|
174
|
+
config_name = config_name.to_s
|
175
|
+
other_settings = settings[1..-1]
|
176
|
+
|
177
|
+
unless @configurations.include?(config_name)
|
178
|
+
raise ArgumentError.new("Unknown configuration: #{config_name.inspect}")
|
111
179
|
end
|
112
180
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
181
|
+
config = send(config_name)
|
182
|
+
config.override!(values) do
|
183
|
+
if other_settings.empty?
|
184
|
+
yield
|
185
|
+
else
|
186
|
+
override!(other_settings, &block)
|
187
|
+
end
|
120
188
|
end
|
121
189
|
end
|
122
190
|
|
191
|
+
# Get the names of all of the configurations that have been added.
|
192
|
+
#
|
193
|
+
# @return [Array<String>] The names of the configurations.
|
194
|
+
# @api private
|
195
|
+
def __configuration_names__
|
196
|
+
@configurations.keys
|
197
|
+
end
|
198
|
+
|
123
199
|
private
|
124
200
|
|
125
201
|
# Load a configuration class.
|
126
202
|
def __load_config__(name, class_name)
|
127
203
|
klass = @configurations[name]
|
128
204
|
|
129
|
-
|
130
|
-
|
205
|
+
# Hook for Rails development mode to reload the configuration class.
|
206
|
+
if klass && defined?(Rails.configuration.cache_classes) && !Rails.configuration.cache_classes
|
207
|
+
klass = class_name if klass != constantize(class_name)
|
131
208
|
end
|
132
209
|
|
133
|
-
|
134
|
-
klass = class_name
|
210
|
+
if klass.is_a?(String)
|
211
|
+
klass = constantize(class_name)
|
135
212
|
@mutex.synchronize do
|
136
213
|
unless klass < Configuration
|
137
214
|
raise TypeError.new("Configuration class #{class_name} does not inherit from UltraSettings::Configuration")
|
@@ -142,5 +219,21 @@ module UltraSettings
|
|
142
219
|
|
143
220
|
klass.instance
|
144
221
|
end
|
222
|
+
|
223
|
+
def classify(name)
|
224
|
+
# Use the Rails classify method if it is available since it will
|
225
|
+
# handle custom inflections.
|
226
|
+
if name.respond_to?(:classify)
|
227
|
+
name.classify
|
228
|
+
else
|
229
|
+
name.split("_").map(&:capitalize).join.gsub("/", "::")
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def constantize(class_name)
|
234
|
+
class_name.split("::").reduce(Object) do |mod, name|
|
235
|
+
mod.const_get(name)
|
236
|
+
end
|
237
|
+
end
|
145
238
|
end
|
146
239
|
end
|