super_settings 2.3.1 → 2.4.1
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 +4 -4
- data/ARCHITECTURE.md +0 -0
- data/CHANGELOG.md +16 -0
- data/README.md +6 -2
- data/VERSION +1 -1
- data/lib/super_settings/application/helper.rb +14 -0
- data/lib/super_settings/application/index.html.erb +95 -98
- data/lib/super_settings/application/layout.html.erb +1 -1
- data/lib/super_settings/application/scripts.js +177 -139
- data/lib/super_settings/application/style_vars.css.erb +22 -4
- data/lib/super_settings/application/styles.css +294 -75
- data/lib/super_settings/application.rb +1 -1
- data/lib/super_settings/coerce.rb +1 -0
- data/lib/super_settings/context/current.rb +23 -0
- data/lib/super_settings/context.rb +3 -0
- data/lib/super_settings/local_cache.rb +14 -0
- data/lib/super_settings/rack_application.rb +3 -1
- data/lib/super_settings/rest_api.rb +22 -3
- data/lib/super_settings/setting.rb +4 -0
- data/lib/super_settings/storage/http_storage.rb +2 -4
- data/lib/super_settings/storage/redis_storage.rb +3 -0
- data/lib/super_settings/storage/test_storage.rb +1 -0
- data/lib/super_settings/time_precision.rb +18 -0
- data/lib/super_settings.rb +3 -1
- metadata +3 -2
@@ -16,12 +16,14 @@ module SuperSettings
|
|
16
16
|
# key: string,
|
17
17
|
# value: object,
|
18
18
|
# value_type: string,
|
19
|
-
# description string,
|
19
|
+
# description: string,
|
20
20
|
# created_at: iso8601 string,
|
21
21
|
# updated_at: iso8601 string
|
22
22
|
# },
|
23
23
|
# ...
|
24
24
|
# ]
|
25
|
+
#
|
26
|
+
# @return [Hash] hash with settings array
|
25
27
|
def index
|
26
28
|
settings = Setting.active.reject(&:deleted?).sort_by(&:key)
|
27
29
|
{settings: settings.collect(&:as_json)}
|
@@ -29,6 +31,7 @@ module SuperSettings
|
|
29
31
|
|
30
32
|
# Get a setting by id.
|
31
33
|
#
|
34
|
+
# @param key [String] setting key
|
32
35
|
# @example
|
33
36
|
# GET /setting
|
34
37
|
#
|
@@ -41,10 +44,12 @@ module SuperSettings
|
|
41
44
|
# key: string,
|
42
45
|
# value: object,
|
43
46
|
# value_type: string,
|
44
|
-
# description string,
|
47
|
+
# description: string,
|
45
48
|
# created_at: iso8601 string,
|
46
49
|
# updated_at: iso8601 string
|
47
50
|
# }
|
51
|
+
#
|
52
|
+
# @return [Hash, nil] setting hash or nil if not found
|
48
53
|
def show(key)
|
49
54
|
setting = Setting.find_by_key(key)
|
50
55
|
setting.as_json if setting && !setting.deleted?
|
@@ -52,6 +57,8 @@ module SuperSettings
|
|
52
57
|
|
53
58
|
# The update operation uses a transaction to atomically update all settings.
|
54
59
|
#
|
60
|
+
# @param settings_params [Array] array of setting parameter hashes
|
61
|
+
# @param changed_by [String] identifier for who made the changes
|
55
62
|
# @example
|
56
63
|
# POST /settings
|
57
64
|
#
|
@@ -81,6 +88,8 @@ module SuperSettings
|
|
81
88
|
# or
|
82
89
|
#
|
83
90
|
# {success: false, errors: {key => [string], ...}}
|
91
|
+
#
|
92
|
+
# @return [Hash] result hash with success status and any errors
|
84
93
|
def update(settings_params, changed_by = nil)
|
85
94
|
all_valid, settings = Setting.bulk_update(Array(settings_params), changed_by)
|
86
95
|
if all_valid
|
@@ -98,6 +107,9 @@ module SuperSettings
|
|
98
107
|
|
99
108
|
# Return the history of the setting.
|
100
109
|
#
|
110
|
+
# @param key [String] setting key
|
111
|
+
# @param limit [Integer] number of history items to return
|
112
|
+
# @param offset [Integer] index to start fetching items from (most recent items are first)
|
101
113
|
# @example
|
102
114
|
# GET /setting/history
|
103
115
|
#
|
@@ -121,6 +133,8 @@ module SuperSettings
|
|
121
133
|
# previous_page_params: hash,
|
122
134
|
# next_page_params: hash
|
123
135
|
# }
|
136
|
+
#
|
137
|
+
# @return [Hash, nil] history hash or nil if setting not found
|
124
138
|
def history(key, limit: nil, offset: 0)
|
125
139
|
setting = Setting.find_by_key(key)
|
126
140
|
return nil unless setting
|
@@ -162,12 +176,15 @@ module SuperSettings
|
|
162
176
|
# {
|
163
177
|
# last_updated_at: iso8601 string
|
164
178
|
# }
|
179
|
+
#
|
180
|
+
# @return [Hash] hash with the last updated timestamp
|
165
181
|
def last_updated_at
|
166
182
|
{last_updated_at: Setting.last_updated_at.utc.iso8601(6)}
|
167
183
|
end
|
168
184
|
|
169
185
|
# Return settings that have been updated since a specified timestamp.
|
170
186
|
#
|
187
|
+
# @param time [Time, String] timestamp to check for updates since
|
171
188
|
# @example
|
172
189
|
# GET /updated_since
|
173
190
|
#
|
@@ -181,12 +198,14 @@ module SuperSettings
|
|
181
198
|
# key: string,
|
182
199
|
# value: object,
|
183
200
|
# value_type: string,
|
184
|
-
# description string,
|
201
|
+
# description: string,
|
185
202
|
# created_at: iso8601 string,
|
186
203
|
# updated_at: iso8601 string
|
187
204
|
# },
|
188
205
|
# ...
|
189
206
|
# ]
|
207
|
+
#
|
208
|
+
# @return [Hash] hash with settings array
|
190
209
|
def updated_since(time)
|
191
210
|
time = Coerce.time(time)
|
192
211
|
settings = Setting.updated_since(time).reject(&:deleted?)
|
@@ -9,6 +9,7 @@ module SuperSettings
|
|
9
9
|
# ships with storage engines for ActiveRecord, Redis, and HTTP (microservice). See the SuperSettings::Storage
|
10
10
|
# class for more details.
|
11
11
|
class Setting
|
12
|
+
# Cache key used for storing the last updated timestamp.
|
12
13
|
LAST_UPDATED_CACHE_KEY = "SuperSettings.last_updated_at"
|
13
14
|
|
14
15
|
STRING = "string"
|
@@ -266,6 +267,7 @@ module SuperSettings
|
|
266
267
|
setting = changed[key] || Setting.find_by_key(key)
|
267
268
|
unless setting
|
268
269
|
next if Coerce.present?(setting_params["delete"])
|
270
|
+
|
269
271
|
setting = Setting.new(key: setting_params["key"])
|
270
272
|
end
|
271
273
|
|
@@ -545,6 +547,7 @@ module SuperSettings
|
|
545
547
|
|
546
548
|
# Serialize to a hash that is used for rendering JSON responses.
|
547
549
|
#
|
550
|
+
# @param options [Hash] options for JSON serialization (unused but maintained for compatibility)
|
548
551
|
# @return [Hash]
|
549
552
|
def as_json(options = nil)
|
550
553
|
attributes = {
|
@@ -561,6 +564,7 @@ module SuperSettings
|
|
561
564
|
|
562
565
|
# Serialize to a JSON string.
|
563
566
|
#
|
567
|
+
# @param options [Hash] options to pass to JSON generation
|
564
568
|
# @return [String]
|
565
569
|
def to_json(options = nil)
|
566
570
|
as_json.to_json(options)
|
@@ -35,15 +35,13 @@ module SuperSettings
|
|
35
35
|
# Add headers to this hash to add them to all requests to the SuperSettings REST API.
|
36
36
|
#
|
37
37
|
# @example
|
38
|
-
#
|
39
|
-
# SuperSettings::HttpStorage.headers["Authorization"] = "Bearer 12345"
|
38
|
+
# SuperSettings::HttpStorage.headers["Authorization"] = "Bearer 12345"
|
40
39
|
attr_reader :headers
|
41
40
|
|
42
41
|
# Add query parameters to this hash to add them to all requests to the SuperSettings REST API.
|
43
42
|
#
|
44
43
|
# @example
|
45
|
-
#
|
46
|
-
# SuperSettings::HttpStorage.query_params["access_token"] = "12345"
|
44
|
+
# SuperSettings::HttpStorage.query_params["access_token"] = "12345"
|
47
45
|
attr_reader :query_params
|
48
46
|
|
49
47
|
def all
|
@@ -35,6 +35,7 @@ module SuperSettings
|
|
35
35
|
def find_all_by_key(key:, offset: 0, limit: nil)
|
36
36
|
end_index = (limit.nil? ? -1 : offset + limit - 1)
|
37
37
|
return [] unless end_index >= -1
|
38
|
+
|
38
39
|
payloads = RedisStorage.with_redis { |redis| redis.lrange("#{HISTORY_KEY_PREFIX}.#{key}", offset, end_index) }
|
39
40
|
payloads.collect do |json|
|
40
41
|
record = new(JSON.parse(json))
|
@@ -112,6 +113,7 @@ module SuperSettings
|
|
112
113
|
def find_by_key(key)
|
113
114
|
json = with_redis { |redis| redis.hget(SETTINGS_KEY, key) }
|
114
115
|
return nil unless json
|
116
|
+
|
115
117
|
record = load_from_json(json)
|
116
118
|
record unless record.deleted?
|
117
119
|
end
|
@@ -123,6 +125,7 @@ module SuperSettings
|
|
123
125
|
def last_updated_at
|
124
126
|
result = with_redis { |redis| redis.zrevrange(UPDATED_KEY, 0, 1, withscores: true).first }
|
125
127
|
return nil unless result
|
128
|
+
|
126
129
|
time_at_microseconds(result[1])
|
127
130
|
end
|
128
131
|
|
@@ -4,24 +4,42 @@ module SuperSettings
|
|
4
4
|
# Helper class for truncating timestamps to a specific precision. This is used by storage engines
|
5
5
|
# to ensure that timestamps are stored and compared with the same precision.
|
6
6
|
class TimePrecision
|
7
|
+
# The time value with applied precision.
|
7
8
|
attr_reader :time
|
8
9
|
|
10
|
+
# Create a new TimePrecision object.
|
11
|
+
#
|
12
|
+
# @param time [Time, Numeric] the time to apply precision to
|
13
|
+
# @param precision [Symbol] the precision level (:microsecond or :millisecond)
|
14
|
+
# @raise [ArgumentError] if precision is not valid
|
9
15
|
def initialize(time, precision = :microsecond)
|
10
16
|
raise ArgumentError.new("Invalid precision: #{precision}") unless valid_precision?(precision)
|
11
17
|
|
12
18
|
@time = time_with_precision(time.to_f, precision) if time
|
13
19
|
end
|
14
20
|
|
21
|
+
# Convert the time to a float.
|
22
|
+
#
|
23
|
+
# @return [Float] the time as a floating point number
|
15
24
|
def to_f
|
16
25
|
@time.to_f
|
17
26
|
end
|
18
27
|
|
19
28
|
private
|
20
29
|
|
30
|
+
# Check if the precision value is valid.
|
31
|
+
#
|
32
|
+
# @param precision [Symbol] the precision to validate
|
33
|
+
# @return [Boolean] true if precision is valid
|
21
34
|
def valid_precision?(precision)
|
22
35
|
[:microsecond, :millisecond].include?(precision)
|
23
36
|
end
|
24
37
|
|
38
|
+
# Apply the specified precision to a timestamp.
|
39
|
+
#
|
40
|
+
# @param timestamp [Float] the timestamp to apply precision to
|
41
|
+
# @param precision [Symbol] the precision level
|
42
|
+
# @return [Time] the time with applied precision
|
25
43
|
def time_with_precision(timestamp, precision)
|
26
44
|
usec = (timestamp % 1) * 1_000_000.0
|
27
45
|
if precision == :millisecond
|
data/lib/super_settings.rb
CHANGED
@@ -23,6 +23,7 @@ module SuperSettings
|
|
23
23
|
autoload :HttpClient, "super_settings/http_client"
|
24
24
|
autoload :VERSION, "super_settings/version"
|
25
25
|
|
26
|
+
# Default number of seconds between cache refresh checks.
|
26
27
|
DEFAULT_REFRESH_INTERVAL = 5.0
|
27
28
|
|
28
29
|
@local_cache = LocalCache.new(refresh_interval: DEFAULT_REFRESH_INTERVAL)
|
@@ -41,7 +42,7 @@ module SuperSettings
|
|
41
42
|
Coerce.string(val)
|
42
43
|
end
|
43
44
|
|
44
|
-
# Alias for {
|
45
|
+
# Alias for {.get} to allow using the [] operator to get a setting value.
|
45
46
|
#
|
46
47
|
# @param key [String, Symbol]
|
47
48
|
# @return [String]
|
@@ -107,6 +108,7 @@ module SuperSettings
|
|
107
108
|
val = context_setting(key)
|
108
109
|
val = default if val.nil?
|
109
110
|
return nil if val.nil?
|
111
|
+
|
110
112
|
Array(val).collect { |v| v&.to_s }
|
111
113
|
end
|
112
114
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: super_settings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Durand
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -31,6 +31,7 @@ executables: []
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
|
+
- ARCHITECTURE.md
|
34
35
|
- CHANGELOG.md
|
35
36
|
- MIT-LICENSE.txt
|
36
37
|
- README.md
|