toggly 1.0.0 → 1.1.0
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/CHANGELOG.md +14 -0
- data/README.md +8 -2
- data/lib/toggly/client.rb +45 -1
- data/lib/toggly/config.rb +30 -0
- data/lib/toggly/version.rb +1 -1
- data/lib/toggly.rb +23 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d728557cdb56574a22377e85047ec649a801532f9cea3574ae66ccba703e320e
|
|
4
|
+
data.tar.gz: 5054b15ad5ad1b48fde5c6fb174698c701bd8fa38b6054cc8afd6ff015e196ce
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8871e715209c606026d37367ec46522c3bbcc7925633f9f511bad51179f141924cb4b7e123978212e1a1697050072d0bfacff0463e53cf02510012cb28531db1
|
|
7
|
+
data.tar.gz: c3536488d775b49aeefa375f72f3c6b88a993fb4b6464a19e8c5ae73bde75222c310bc820e563f94039509bd6dbbc698ddb04c33cd89de6beba2e7c1ac29dd56
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.0] - 2026-09-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Ambient targeting identity for catalog-local variants: `Config#identity`,
|
|
13
|
+
`Client#identity` / `Client#set_identity`. When `get_variant` /
|
|
14
|
+
`get_variant_value` are called with a nil context or a blank
|
|
15
|
+
`context.identity`, the client identity is used as the allocator
|
|
16
|
+
`userId`. Groups still come only from the per-call context (never Config).
|
|
17
|
+
Prefer config / `set_identity` (or Rails ambient context) over building
|
|
18
|
+
`Context.new(identity: …)` at every call site.
|
|
19
|
+
`Config#identity=` is configuration-time only (`Toggly.configure` /
|
|
20
|
+
`Config.new`); after `Client` is built, use `Client#set_identity`.
|
|
21
|
+
|
|
8
22
|
## [1.0.0] - 2026-09-23
|
|
9
23
|
|
|
10
24
|
### Changed (Breaking)
|
data/README.md
CHANGED
|
@@ -47,13 +47,19 @@ bit-for-bit — verified against the shared
|
|
|
47
47
|
`variant-allocator-corpus/cases.json` gold corpus.
|
|
48
48
|
|
|
49
49
|
```ruby
|
|
50
|
-
|
|
50
|
+
# Prefer ambient identity: Config#identity, Client#set_identity, or Rails
|
|
51
|
+
# feature_variant (uses toggly_context). Per-call context is an override.
|
|
52
|
+
client = Toggly::Client.new(app_key: '...', environment: 'Production', identity: 'user-1')
|
|
53
|
+
client.set_identity('user-2') # optional runtime update
|
|
54
|
+
|
|
55
|
+
variant = client.get_variant('checkout-flow') # uses client identity
|
|
56
|
+
variant = client.get_variant('checkout-flow', context: Toggly::Context.new(identity: 'override'))
|
|
51
57
|
variant&.name # assigned variant name, or nil
|
|
52
58
|
variant&.configuration_value # untyped configuration payload
|
|
53
59
|
variant&.enabled # effective enabled after StatusOverride
|
|
54
60
|
variant&.reason # "User" | "Group" | "Percentile" | "DefaultWhenEnabled" | "DefaultWhenDisabled"
|
|
55
61
|
|
|
56
|
-
client.get_variant_value('checkout-flow'
|
|
62
|
+
client.get_variant_value('checkout-flow') # shortcut for configuration_value
|
|
57
63
|
```
|
|
58
64
|
|
|
59
65
|
`enabled?` stays filter-based only. The `enable_variants` /
|
data/lib/toggly/client.rb
CHANGED
|
@@ -47,6 +47,7 @@ module Toggly
|
|
|
47
47
|
# True once a revision (including empty) or durable snapshot was applied.
|
|
48
48
|
@definitions_loaded = false
|
|
49
49
|
@mutex = Mutex.new
|
|
50
|
+
@identity = normalize_client_identity(@config.identity)
|
|
50
51
|
@ready = false
|
|
51
52
|
@closed = false
|
|
52
53
|
|
|
@@ -121,6 +122,16 @@ module Toggly
|
|
|
121
122
|
# `enable_variants` / `evaluated-variants-signed` dual-rail removed in
|
|
122
123
|
# 1.0 (see CHANGELOG).
|
|
123
124
|
#
|
|
125
|
+
# Targeting identity resolution (first non-empty wins):
|
|
126
|
+
# 1. per-call `context.identity`
|
|
127
|
+
# 2. {#identity} from Config / {#set_identity}
|
|
128
|
+
# 3. empty (MF anonymous)
|
|
129
|
+
#
|
|
130
|
+
# Groups come only from the per-call context (never Config). Prefer
|
|
131
|
+
# Rails `feature_variant` / ambient `toggly_context`, or
|
|
132
|
+
# `set_identity` / `Config#identity` for non-HTTP hosts — not a
|
|
133
|
+
# hand-built identity on every call.
|
|
134
|
+
#
|
|
124
135
|
# NOTE: this is the actual A/B assignment. It is unrelated to the
|
|
125
136
|
# `variant:` telemetry label on `record_usage` / `record_view`, which is
|
|
126
137
|
# a free-form usage tag (defaults to "enabled"/"disabled").
|
|
@@ -137,7 +148,7 @@ module Toggly
|
|
|
137
148
|
assignment = VariantAllocator.assign(
|
|
138
149
|
definition,
|
|
139
150
|
enabled: enabled,
|
|
140
|
-
identity: context
|
|
151
|
+
identity: variant_user_id(context),
|
|
141
152
|
groups: context&.groups || []
|
|
142
153
|
)
|
|
143
154
|
return nil if assignment.variant_name.nil?
|
|
@@ -159,6 +170,25 @@ module Toggly
|
|
|
159
170
|
get_variant(feature_key, context: context)&.configuration_value
|
|
160
171
|
end
|
|
161
172
|
|
|
173
|
+
# Default targeting userId used by {#get_variant} / {#get_variant_value}
|
|
174
|
+
# when the per-call context has no identity.
|
|
175
|
+
#
|
|
176
|
+
# @return [String, nil]
|
|
177
|
+
def identity
|
|
178
|
+
@mutex.synchronize { @identity }
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Set the default targeting userId (overrides Config#identity at runtime).
|
|
182
|
+
# Pass +nil+ or an empty string to clear.
|
|
183
|
+
#
|
|
184
|
+
# Named +set_identity+ (not +identity=+) to match Python/Java/Go SDK APIs.
|
|
185
|
+
#
|
|
186
|
+
# @param value [String, nil]
|
|
187
|
+
# @return [String, nil]
|
|
188
|
+
def set_identity(value) # rubocop:disable Naming/AccessorMethodName
|
|
189
|
+
@mutex.synchronize { @identity = normalize_client_identity(value) }
|
|
190
|
+
end
|
|
191
|
+
|
|
162
192
|
# Get detailed evaluation result
|
|
163
193
|
#
|
|
164
194
|
# @param feature_key [String, Symbol] The feature key
|
|
@@ -452,6 +482,20 @@ module Toggly
|
|
|
452
482
|
@telemetry.record_check(feature_key, enabled, identity)
|
|
453
483
|
end
|
|
454
484
|
|
|
485
|
+
# Allocator userId: per-call context identity when present, else client identity.
|
|
486
|
+
def variant_user_id(context)
|
|
487
|
+
return context.identity if context&.identity?
|
|
488
|
+
|
|
489
|
+
identity
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def normalize_client_identity(value)
|
|
493
|
+
return nil if value.nil?
|
|
494
|
+
|
|
495
|
+
text = value.to_s
|
|
496
|
+
text.empty? ? nil : text
|
|
497
|
+
end
|
|
498
|
+
|
|
455
499
|
def log_info(message)
|
|
456
500
|
@config.logger&.info("[Toggly] #{message}")
|
|
457
501
|
end
|
data/lib/toggly/config.rb
CHANGED
|
@@ -12,6 +12,17 @@ module Toggly
|
|
|
12
12
|
# @return [String] Application key from Toggly dashboard
|
|
13
13
|
attr_reader :app_key
|
|
14
14
|
|
|
15
|
+
# Default targeting userId for catalog-local +get_variant+ /
|
|
16
|
+
# +get_variant_value+ when neither a per-call +Context#identity+ nor
|
|
17
|
+
# Rails ambient context supplies one. Groups are never taken from Config.
|
|
18
|
+
#
|
|
19
|
+
# Set at configuration time only ({Config.new}, +Toggly.configure+ block).
|
|
20
|
+
# After a {Client} is built, mutating this value has no effect — use
|
|
21
|
+
# {Client#set_identity} for runtime updates.
|
|
22
|
+
#
|
|
23
|
+
# @return [String, nil]
|
|
24
|
+
attr_reader :identity
|
|
25
|
+
|
|
15
26
|
# @return [String] Environment name (e.g., "Production", "Staging")
|
|
16
27
|
attr_accessor :environment
|
|
17
28
|
|
|
@@ -89,6 +100,7 @@ module Toggly
|
|
|
89
100
|
|
|
90
101
|
def initialize(**options)
|
|
91
102
|
@app_key = options[:app_key]
|
|
103
|
+
@identity = normalize_identity(options[:identity])
|
|
92
104
|
@environment = options[:environment] || DEFAULT_ENVIRONMENT
|
|
93
105
|
@base_url = normalize_url(options[:base_url] || DEFAULT_BASE_URL)
|
|
94
106
|
@definitions_url = options[:definitions_url]
|
|
@@ -172,12 +184,23 @@ module Toggly
|
|
|
172
184
|
(@app_key.nil? || @app_key.empty?) && !@defaults.empty?
|
|
173
185
|
end
|
|
174
186
|
|
|
187
|
+
# Configuration-time identity only (e.g. inside +Toggly.configure+ before
|
|
188
|
+
# {Client} is constructed). Does not update an existing client's targeting
|
|
189
|
+
# identity — call {Client#set_identity} after initialization.
|
|
190
|
+
#
|
|
191
|
+
# @param value [String, nil]
|
|
192
|
+
# @return [String, nil]
|
|
193
|
+
def identity=(value)
|
|
194
|
+
@identity = normalize_identity(value)
|
|
195
|
+
end
|
|
196
|
+
|
|
175
197
|
# Convert to hash
|
|
176
198
|
#
|
|
177
199
|
# @return [Hash]
|
|
178
200
|
def to_h
|
|
179
201
|
{
|
|
180
202
|
app_key: @app_key,
|
|
203
|
+
identity: @identity,
|
|
181
204
|
environment: @environment,
|
|
182
205
|
base_url: @base_url,
|
|
183
206
|
definitions_url: @definitions_url,
|
|
@@ -208,5 +231,12 @@ module Toggly
|
|
|
208
231
|
|
|
209
232
|
url.end_with?("/") ? url : "#{url}/"
|
|
210
233
|
end
|
|
234
|
+
|
|
235
|
+
def normalize_identity(value)
|
|
236
|
+
return nil if value.nil?
|
|
237
|
+
|
|
238
|
+
text = value.to_s
|
|
239
|
+
text.empty? ? nil : text
|
|
240
|
+
end
|
|
211
241
|
end
|
|
212
242
|
end
|
data/lib/toggly/version.rb
CHANGED
data/lib/toggly.rb
CHANGED
|
@@ -106,6 +106,29 @@ module Toggly
|
|
|
106
106
|
!enabled?(feature_key, context: context)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
# Assign a catalog-local variant using the global client.
|
|
110
|
+
# See {Client#get_variant}.
|
|
111
|
+
#
|
|
112
|
+
# @param feature_key [String, Symbol]
|
|
113
|
+
# @param context [Context, nil]
|
|
114
|
+
# @return [VariantResult, nil]
|
|
115
|
+
def get_variant(feature_key, context: nil)
|
|
116
|
+
raise Error, "Toggly not configured. Call Toggly.configure first." unless @client
|
|
117
|
+
|
|
118
|
+
@client.get_variant(feature_key, context: context)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Configuration value for the assigned variant. See {Client#get_variant_value}.
|
|
122
|
+
#
|
|
123
|
+
# @param feature_key [String, Symbol]
|
|
124
|
+
# @param context [Context, nil]
|
|
125
|
+
# @return [Object, nil]
|
|
126
|
+
def get_variant_value(feature_key, context: nil)
|
|
127
|
+
raise Error, "Toggly not configured. Call Toggly.configure first." unless @client
|
|
128
|
+
|
|
129
|
+
@client.get_variant_value(feature_key, context: context)
|
|
130
|
+
end
|
|
131
|
+
|
|
109
132
|
# Reset the global client (mainly for testing)
|
|
110
133
|
def reset!
|
|
111
134
|
@client&.close
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: toggly
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ops.ai
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: High-performance Ruby SDK for Toggly feature flag management. Works with
|
|
14
14
|
or without Toggly.io.
|