flagsmith 3.0.1 → 3.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/Gemfile.lock +3 -3
- data/README.md +1 -1
- data/example/Gemfile.lock +1 -1
- data/flagsmith.gemspec +38 -0
- data/lib/flagsmith/engine/core.rb +1 -1
- data/lib/flagsmith/engine/segments/constants.rb +5 -1
- data/lib/flagsmith/engine/segments/evaluator.rb +14 -2
- data/lib/flagsmith/engine/segments/models.rb +10 -0
- data/lib/flagsmith/sdk/analytics_processor.rb +2 -2
- data/lib/flagsmith/sdk/models/flags.rb +1 -1
- data/lib/flagsmith/sdk/models/segments.rb +14 -0
- data/lib/flagsmith/version.rb +1 -1
- data/lib/flagsmith.rb +149 -4
- metadata +8 -7
- data/lib/flagsmith/sdk/instance_methods.rb +0 -137
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18c4f2e2e68aaffe9c18d2b1e2af5f0018695ecc17c5af3a94051c8bf4cde1b8
|
4
|
+
data.tar.gz: 53e41364ca7a0347f0358d80616c4781f81835bff43b8f2aedc15d5fa53bb77d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3da8964610c7fa4dbd31b94fdbc74b323711b49a4b9be7ad6f92738fc4c9b38e9a69f6a97c1875b78d6ccb86283325cc579b3f16d8b7d97e3b23eab89e8f8c1d
|
7
|
+
data.tar.gz: c464168ac8cfaff3611e95503b291b4e136e9bc944549b8ad66689232e0ef7411c2074781fbb8f7fd92bdb80775b3317400eb101f8c95bd83bb4d94206891033
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
flagsmith (3.0
|
4
|
+
flagsmith (3.1.0)
|
5
5
|
faraday
|
6
6
|
faraday-retry
|
7
7
|
faraday_middleware
|
@@ -40,7 +40,7 @@ GEM
|
|
40
40
|
faraday (~> 1.0)
|
41
41
|
gem-release (2.2.0)
|
42
42
|
method_source (1.0.0)
|
43
|
-
multipart-post (2.2.
|
43
|
+
multipart-post (2.2.3)
|
44
44
|
parallel (1.20.1)
|
45
45
|
parser (3.0.0.0)
|
46
46
|
ast (~> 2.4.1)
|
@@ -50,7 +50,7 @@ GEM
|
|
50
50
|
rainbow (3.0.0)
|
51
51
|
rake (13.0.3)
|
52
52
|
regexp_parser (2.0.3)
|
53
|
-
rexml (3.2.
|
53
|
+
rexml (3.2.5)
|
54
54
|
rspec (3.10.0)
|
55
55
|
rspec-core (~> 3.10.0)
|
56
56
|
rspec-expectations (~> 3.10.0)
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ The SDK clients for Ruby [https://www.flagsmith.com/](https://www.flagsmith.com/
|
|
6
6
|
|
7
7
|
## Adding to your project
|
8
8
|
|
9
|
-
For full documentation visit [https://docs.flagsmith.com/clients/
|
9
|
+
For full documentation visit [https://docs.flagsmith.com/clients/server-side](https://docs.flagsmith.com/clients/server-side).
|
10
10
|
|
11
11
|
## Contributing
|
12
12
|
|
data/example/Gemfile.lock
CHANGED
data/flagsmith.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('lib/flagsmith/version', __dir__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.required_ruby_version = '>= 2.4.0'
|
7
|
+
spec.name = 'flagsmith'
|
8
|
+
spec.version = Flagsmith::VERSION
|
9
|
+
spec.authors = ['Tom Stuart', 'Brian Moelk']
|
10
|
+
spec.email = ['tom@solidstategroup.com', 'bmoelk@gmail.com']
|
11
|
+
# Specify which files should be added to the gem when it is released.
|
12
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
13
|
+
spec.files = Dir.chdir(__dir__) do
|
14
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
15
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
spec.summary = 'Flagsmith - Ship features with confidence'
|
20
|
+
spec.description = 'Ruby Client for Flagsmith. Ship features with confidence using feature flags and remote config. Host yourself or use our hosted version at https://flagsmith.com'
|
21
|
+
spec.homepage = 'https://flagsmith.com'
|
22
|
+
|
23
|
+
spec.bindir = 'exe'
|
24
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ['lib']
|
26
|
+
|
27
|
+
spec.add_development_dependency 'bundler'
|
28
|
+
spec.add_development_dependency 'gem-release'
|
29
|
+
spec.add_development_dependency 'pry'
|
30
|
+
spec.add_development_dependency 'rake'
|
31
|
+
spec.add_development_dependency 'rspec'
|
32
|
+
spec.add_development_dependency 'rubocop'
|
33
|
+
|
34
|
+
spec.add_dependency 'faraday'
|
35
|
+
spec.add_dependency 'faraday_middleware'
|
36
|
+
spec.add_dependency 'faraday-retry'
|
37
|
+
spec.add_dependency 'semantic'
|
38
|
+
end
|
@@ -15,7 +15,7 @@ require_relative 'utils/hash_func'
|
|
15
15
|
module Flagsmith
|
16
16
|
module Engine
|
17
17
|
# Flags engine methods
|
18
|
-
|
18
|
+
class Engine
|
19
19
|
include Flagsmith::Engine::Segments::Evaluator
|
20
20
|
|
21
21
|
def get_identity_feature_state(environment, identity, feature_name, override_traits = nil)
|
@@ -22,6 +22,9 @@ module Flagsmith
|
|
22
22
|
NOT_EQUAL = 'NOT_EQUAL'
|
23
23
|
REGEX = 'REGEX'
|
24
24
|
PERCENTAGE_SPLIT = 'PERCENTAGE_SPLIT'
|
25
|
+
IS_SET = 'IS_SET'
|
26
|
+
IS_NOT_SET = 'IS_NOT_SET'
|
27
|
+
MODULO = 'MODULO'
|
25
28
|
|
26
29
|
CONDITION_OPERATORS = [
|
27
30
|
EQUAL,
|
@@ -33,7 +36,8 @@ module Flagsmith
|
|
33
36
|
NOT_CONTAINS,
|
34
37
|
NOT_EQUAL,
|
35
38
|
REGEX,
|
36
|
-
PERCENTAGE_SPLIT
|
39
|
+
PERCENTAGE_SPLIT,
|
40
|
+
MODULO
|
37
41
|
].freeze
|
38
42
|
end
|
39
43
|
end
|
@@ -56,12 +56,24 @@ module Flagsmith
|
|
56
56
|
return hashed_percentage_for_object_ids([segment_id, identity_id]) <= condition.value.to_f
|
57
57
|
end
|
58
58
|
|
59
|
-
trait = identity_traits.find { |t| t.key == condition.property }
|
59
|
+
trait = identity_traits.find { |t| t.key.to_s == condition.property }
|
60
60
|
|
61
|
-
|
61
|
+
if [IS_SET, IS_NOT_SET].include?(condition.operator)
|
62
|
+
return handle_trait_existence_conditions(trait, condition.operator)
|
63
|
+
end
|
64
|
+
|
65
|
+
return condition.match_trait_value?(trait.trait_value) if trait
|
62
66
|
|
63
67
|
false
|
64
68
|
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def handle_trait_existence_conditions(matching_trait, operator)
|
73
|
+
return operator == IS_NOT_SET if matching_trait.nil?
|
74
|
+
|
75
|
+
operator == IS_SET
|
76
|
+
end
|
65
77
|
end
|
66
78
|
end
|
67
79
|
end
|
@@ -55,10 +55,13 @@ module Flagsmith
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def match_trait_value?(trait_value)
|
58
|
+
# handle some exceptions
|
58
59
|
if @value.is_a?(String) && @value.match?(/:semver$/)
|
59
60
|
trait_value = Semantic::Version.new(trait_value.gsub(/:semver$/, ''))
|
60
61
|
end
|
61
62
|
|
63
|
+
return match_modulo_value(trait_value) if @operator == MODULO
|
64
|
+
|
62
65
|
type_as_trait_value = format_to_type_of(trait_value)
|
63
66
|
formatted_value = type_as_trait_value ? type_as_trait_value.call(@value) : @value
|
64
67
|
|
@@ -78,6 +81,13 @@ module Flagsmith
|
|
78
81
|
end
|
79
82
|
# rubocop:enable Metrics/AbcSize
|
80
83
|
|
84
|
+
def match_modulo_value(trait_value)
|
85
|
+
divisor, remainder = @value.split('|')
|
86
|
+
trait_value.is_a?(Numeric) && trait_value % divisor.to_f == remainder.to_f
|
87
|
+
rescue StandardError
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
81
91
|
class << self
|
82
92
|
def build(json)
|
83
93
|
new(**json.slice(:operator, :value).merge(property: json[:property_]))
|
@@ -31,8 +31,8 @@ module Flagsmith
|
|
31
31
|
@last_flushed = Time.now
|
32
32
|
end
|
33
33
|
|
34
|
-
def track_feature(
|
35
|
-
@analytics_data[
|
34
|
+
def track_feature(feature_name)
|
35
|
+
@analytics_data[feature_name] = @analytics_data.fetch(feature_name, 0) + 1
|
36
36
|
flush if (Time.now - @last_flushed) > TIMER * 1000
|
37
37
|
end
|
38
38
|
end
|
@@ -122,7 +122,7 @@ module Flagsmith
|
|
122
122
|
def get_flag(feature_name)
|
123
123
|
key = Flagsmith::Flags::Collection.normalize_key(feature_name)
|
124
124
|
flag = flags.fetch(key)
|
125
|
-
@analytics_processor.track_feature(flag.
|
125
|
+
@analytics_processor.track_feature(flag.feature_name) if @analytics_processor && flag.feature_id
|
126
126
|
flag
|
127
127
|
rescue KeyError
|
128
128
|
return @default_flag_handler.call(feature_name) if @default_flag_handler
|
data/lib/flagsmith/version.rb
CHANGED
data/lib/flagsmith.rb
CHANGED
@@ -15,7 +15,7 @@ require 'flagsmith/sdk/errors'
|
|
15
15
|
require 'flagsmith/sdk/intervals'
|
16
16
|
require 'flagsmith/sdk/pooling_manager'
|
17
17
|
require 'flagsmith/sdk/models/flags'
|
18
|
-
require 'flagsmith/sdk/
|
18
|
+
require 'flagsmith/sdk/models/segments'
|
19
19
|
|
20
20
|
require 'flagsmith/engine/core'
|
21
21
|
|
@@ -24,8 +24,6 @@ module Flagsmith
|
|
24
24
|
# Ruby client for flagsmith.com
|
25
25
|
class Client
|
26
26
|
extend Forwardable
|
27
|
-
include Flagsmith::SDK::InstanceMethods
|
28
|
-
include Flagsmith::Engine::Core
|
29
27
|
# A Flagsmith client.
|
30
28
|
#
|
31
29
|
# Provides an interface for interacting with the Flagsmith http API.
|
@@ -37,9 +35,11 @@ module Flagsmith
|
|
37
35
|
# feature_enabled = environment_flags.is_feature_enabled('foo')
|
38
36
|
# feature_value = identity_flags.get_feature_value('foo')
|
39
37
|
#
|
40
|
-
# identity_flags = flagsmith.get_identity_flags('identifier', 'foo': 'bar')
|
38
|
+
# identity_flags = flagsmith.get_identity_flags('identifier', {'foo': 'bar'})
|
41
39
|
# feature_enabled_for_identity = identity_flags.is_feature_enabled('foo')
|
42
40
|
# feature_value_for_identity = identity_flags.get_feature_value('foo')
|
41
|
+
#
|
42
|
+
# identity_segments = flagsmith.get_identity_segments('identifier', {'foo': 'bar'})
|
43
43
|
|
44
44
|
# Available Configs.
|
45
45
|
#
|
@@ -58,12 +58,17 @@ module Flagsmith
|
|
58
58
|
api_client
|
59
59
|
analytics_processor
|
60
60
|
environment_data_polling_manager
|
61
|
+
engine
|
61
62
|
end
|
62
63
|
|
63
64
|
def api_client
|
64
65
|
@api_client ||= Flagsmith::ApiClient.new(@config)
|
65
66
|
end
|
66
67
|
|
68
|
+
def engine
|
69
|
+
@engine ||= Flagsmith::Engine::Engine.new
|
70
|
+
end
|
71
|
+
|
67
72
|
def analytics_processor
|
68
73
|
return nil unless @config.enable_analytics?
|
69
74
|
|
@@ -94,5 +99,145 @@ module Flagsmith
|
|
94
99
|
environment_data = api_client.get(@config.environment_url).body
|
95
100
|
Flagsmith::Engine::Environment.build(environment_data)
|
96
101
|
end
|
102
|
+
|
103
|
+
# Get all the default for flags for the current environment.
|
104
|
+
# @returns Flags object holding all the flags for the current environment.
|
105
|
+
def get_environment_flags # rubocop:disable Naming/AccessorMethodName
|
106
|
+
return environment_flags_from_document if @config.local_evaluation?
|
107
|
+
|
108
|
+
environment_flags_from_api
|
109
|
+
end
|
110
|
+
|
111
|
+
# Get all the flags for the current environment for a given identity. Will also
|
112
|
+
# upsert all traits to the Flagsmith API for future evaluations. Providing a
|
113
|
+
# trait with a value of None will remove the trait from the identity if it exists.
|
114
|
+
#
|
115
|
+
# identifier a unique identifier for the identity in the current
|
116
|
+
# environment, e.g. email address, username, uuid
|
117
|
+
# traits { key => value } is a dictionary of traits to add / update on the identity in
|
118
|
+
# Flagsmith, e.g. { "num_orders": 10 }
|
119
|
+
# returns Flags object holding all the flags for the given identity.
|
120
|
+
def get_identity_flags(identifier, **traits)
|
121
|
+
return get_identity_flags_from_document(identifier, traits) if environment
|
122
|
+
|
123
|
+
get_identity_flags_from_api(identifier, traits)
|
124
|
+
end
|
125
|
+
|
126
|
+
def feature_enabled?(feature_name, default: false)
|
127
|
+
flag = get_environment_flags[feature_name]
|
128
|
+
return default if flag.nil?
|
129
|
+
|
130
|
+
flag.enabled?
|
131
|
+
end
|
132
|
+
|
133
|
+
def feature_enabled_for_identity?(feature_name, user_id, default: false)
|
134
|
+
flag = get_identity_flags(user_id)[feature_name]
|
135
|
+
return default if flag.nil?
|
136
|
+
|
137
|
+
flag.enabled?
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_value(feature_name, default: nil)
|
141
|
+
flag = get_environment_flags[feature_name]
|
142
|
+
return default if flag.nil?
|
143
|
+
|
144
|
+
flag.value
|
145
|
+
end
|
146
|
+
|
147
|
+
def get_value_for_identity(feature_name, user_id = nil, default: nil)
|
148
|
+
flag = get_identity_flags(user_id)[feature_name]
|
149
|
+
return default if flag.nil?
|
150
|
+
|
151
|
+
flag.value
|
152
|
+
end
|
153
|
+
|
154
|
+
def get_identity_segments(identifier, traits = {})
|
155
|
+
unless environment
|
156
|
+
raise Flagsmith::ClientError,
|
157
|
+
'Local evaluation required to obtain identity segments.'
|
158
|
+
end
|
159
|
+
|
160
|
+
identity_model = build_identity_model(identifier, traits)
|
161
|
+
segment_models = engine.get_identity_segments(environment, identity_model)
|
162
|
+
return segment_models.map { |sm| Flagsmith::Segments::Segment.new(id: sm.id, name: sm.name) }.compact
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def environment_flags_from_document
|
168
|
+
Flagsmith::Flags::Collection.from_feature_state_models(
|
169
|
+
engine.get_environment_feature_states(environment),
|
170
|
+
analytics_processor: analytics_processor,
|
171
|
+
default_flag_handler: default_flag_handler
|
172
|
+
)
|
173
|
+
end
|
174
|
+
|
175
|
+
def get_identity_flags_from_document(identifier, traits = {})
|
176
|
+
identity_model = build_identity_model(identifier, traits)
|
177
|
+
|
178
|
+
Flagsmith::Flags::Collection.from_feature_state_models(
|
179
|
+
engine.get_identity_feature_states(environment, identity_model),
|
180
|
+
analytics_processor: analytics_processor,
|
181
|
+
default_flag_handler: default_flag_handler
|
182
|
+
)
|
183
|
+
end
|
184
|
+
|
185
|
+
def environment_flags_from_api
|
186
|
+
rescue_with_default_handler do
|
187
|
+
api_flags = api_client.get(@config.environment_flags_url).body
|
188
|
+
api_flags = api_flags.select { |flag| flag[:feature_segment].nil? }
|
189
|
+
Flagsmith::Flags::Collection.from_api(
|
190
|
+
api_flags,
|
191
|
+
analytics_processor: analytics_processor,
|
192
|
+
default_flag_handler: default_flag_handler
|
193
|
+
)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def get_identity_flags_from_api(identifier, traits = {})
|
198
|
+
rescue_with_default_handler do
|
199
|
+
data = generate_identities_data(identifier, traits)
|
200
|
+
json_response = api_client.post(@config.identities_url, data.to_json).body
|
201
|
+
|
202
|
+
Flagsmith::Flags::Collection.from_api(
|
203
|
+
json_response[:flags],
|
204
|
+
analytics_processor: analytics_processor,
|
205
|
+
default_flag_handler: default_flag_handler
|
206
|
+
)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def rescue_with_default_handler
|
211
|
+
yield
|
212
|
+
rescue StandardError
|
213
|
+
if default_flag_handler
|
214
|
+
return Flagsmith::Flags::Collection.new(
|
215
|
+
{},
|
216
|
+
default_flag_handler: default_flag_handler
|
217
|
+
)
|
218
|
+
end
|
219
|
+
raise
|
220
|
+
end
|
221
|
+
|
222
|
+
def build_identity_model(identifier, traits = {})
|
223
|
+
unless environment
|
224
|
+
raise Flagsmith::ClientError,
|
225
|
+
'Unable to build identity model when no local environment present.'
|
226
|
+
end
|
227
|
+
|
228
|
+
trait_models = traits.map do |key, value|
|
229
|
+
Flagsmith::Engine::Identities::Trait.new(trait_key: key, trait_value: value)
|
230
|
+
end
|
231
|
+
Flagsmith::Engine::Identity.new(
|
232
|
+
identity_traits: trait_models, environment_api_key: environment_key, identifier: identifier
|
233
|
+
)
|
234
|
+
end
|
235
|
+
|
236
|
+
def generate_identities_data(identifier, traits = {})
|
237
|
+
{
|
238
|
+
identifier: identifier,
|
239
|
+
traits: traits.map { |key, value| { trait_key: key, trait_value: value } }
|
240
|
+
}
|
241
|
+
end
|
97
242
|
end
|
98
243
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flagsmith
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Stuart
|
8
8
|
- Brian Moelk
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-11-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -204,6 +204,7 @@ files:
|
|
204
204
|
- example/spec/web/features/.gitkeep
|
205
205
|
- example/spec/web/views/application_layout_spec.rb
|
206
206
|
- example/spec/web/views/home/index_spec.rb
|
207
|
+
- flagsmith.gemspec
|
207
208
|
- lib/flagsmith.rb
|
208
209
|
- lib/flagsmith/engine/core.rb
|
209
210
|
- lib/flagsmith/engine/environments/models.rb
|
@@ -220,15 +221,15 @@ files:
|
|
220
221
|
- lib/flagsmith/sdk/api_client.rb
|
221
222
|
- lib/flagsmith/sdk/config.rb
|
222
223
|
- lib/flagsmith/sdk/errors.rb
|
223
|
-
- lib/flagsmith/sdk/instance_methods.rb
|
224
224
|
- lib/flagsmith/sdk/intervals.rb
|
225
225
|
- lib/flagsmith/sdk/models/flags.rb
|
226
|
+
- lib/flagsmith/sdk/models/segments.rb
|
226
227
|
- lib/flagsmith/sdk/pooling_manager.rb
|
227
228
|
- lib/flagsmith/version.rb
|
228
229
|
homepage: https://flagsmith.com
|
229
230
|
licenses: []
|
230
231
|
metadata: {}
|
231
|
-
post_install_message:
|
232
|
+
post_install_message:
|
232
233
|
rdoc_options: []
|
233
234
|
require_paths:
|
234
235
|
- lib
|
@@ -243,8 +244,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
244
|
- !ruby/object:Gem::Version
|
244
245
|
version: '0'
|
245
246
|
requirements: []
|
246
|
-
rubygems_version: 3.
|
247
|
-
signing_key:
|
247
|
+
rubygems_version: 3.3.7
|
248
|
+
signing_key:
|
248
249
|
specification_version: 4
|
249
250
|
summary: Flagsmith - Ship features with confidence
|
250
251
|
test_files: []
|
@@ -1,137 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Flagsmith
|
4
|
-
module SDK
|
5
|
-
# Available Flagsmith Functions
|
6
|
-
module InstanceMethods
|
7
|
-
# Get all the default for flags for the current environment.
|
8
|
-
# @returns Flags object holding all the flags for the current environment.
|
9
|
-
def get_environment_flags # rubocop:disable Naming/AccessorMethodName
|
10
|
-
return environment_flags_from_document if @config.local_evaluation?
|
11
|
-
|
12
|
-
environment_flags_from_api
|
13
|
-
end
|
14
|
-
|
15
|
-
# Get all the flags for the current environment for a given identity. Will also
|
16
|
-
# upsert all traits to the Flagsmith API for future evaluations. Providing a
|
17
|
-
# trait with a value of None will remove the trait from the identity if it exists.
|
18
|
-
#
|
19
|
-
# identifier a unique identifier for the identity in the current
|
20
|
-
# environment, e.g. email address, username, uuid
|
21
|
-
# traits { key => value } is a dictionary of traits to add / update on the identity in
|
22
|
-
# Flagsmith, e.g. { "num_orders": 10 }
|
23
|
-
# returns Flags object holding all the flags for the given identity.
|
24
|
-
def get_identity_flags(identifier, **traits)
|
25
|
-
return get_identity_flags_from_document(identifier, traits) if environment
|
26
|
-
|
27
|
-
get_identity_flags_from_api(identifier, traits)
|
28
|
-
end
|
29
|
-
|
30
|
-
def feature_enabled?(feature_name, default: false)
|
31
|
-
flag = get_environment_flags[feature_name]
|
32
|
-
return default if flag.nil?
|
33
|
-
|
34
|
-
flag.enabled?
|
35
|
-
end
|
36
|
-
|
37
|
-
def feature_enabled_for_identity?(feature_name, user_id, default: false)
|
38
|
-
flag = get_identity_flags(user_id)[feature_name]
|
39
|
-
return default if flag.nil?
|
40
|
-
|
41
|
-
flag.enabled?
|
42
|
-
end
|
43
|
-
|
44
|
-
def get_value(feature_name, default: nil)
|
45
|
-
flag = get_environment_flags[feature_name]
|
46
|
-
return default if flag.nil?
|
47
|
-
|
48
|
-
flag.value
|
49
|
-
end
|
50
|
-
|
51
|
-
def get_value_for_identity(feature_name, user_id = nil, default: nil)
|
52
|
-
flag = get_identity_flags(user_id)[feature_name]
|
53
|
-
return default if flag.nil?
|
54
|
-
|
55
|
-
flag.value
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def environment_flags_from_document
|
61
|
-
Flagsmith::Flags::Collection.from_feature_state_models(
|
62
|
-
get_environment_feature_states(environment),
|
63
|
-
analytics_processor: analytics_processor,
|
64
|
-
default_flag_handler: default_flag_handler
|
65
|
-
)
|
66
|
-
end
|
67
|
-
|
68
|
-
def get_identity_flags_from_document(identifier, traits = {})
|
69
|
-
identity_model = build_identity_model(identifier, traits)
|
70
|
-
|
71
|
-
Flagsmith::Flags::Collection.from_feature_state_models(
|
72
|
-
get_identity_feature_states(environment, identity_model),
|
73
|
-
analytics_processor: analytics_processor,
|
74
|
-
default_flag_handler: default_flag_handler
|
75
|
-
)
|
76
|
-
end
|
77
|
-
|
78
|
-
def environment_flags_from_api
|
79
|
-
rescue_with_default_handler do
|
80
|
-
api_flags = api_client.get(@config.environment_flags_url).body
|
81
|
-
api_flags = api_flags.select { |flag| flag[:feature_segment].nil? }
|
82
|
-
Flagsmith::Flags::Collection.from_api(
|
83
|
-
api_flags,
|
84
|
-
analytics_processor: analytics_processor,
|
85
|
-
default_flag_handler: default_flag_handler
|
86
|
-
)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def get_identity_flags_from_api(identifier, traits = {})
|
91
|
-
rescue_with_default_handler do
|
92
|
-
data = generate_identities_data(identifier, traits)
|
93
|
-
json_response = api_client.post(@config.identities_url, data.to_json).body
|
94
|
-
|
95
|
-
Flagsmith::Flags::Collection.from_api(
|
96
|
-
json_response[:flags],
|
97
|
-
analytics_processor: analytics_processor,
|
98
|
-
default_flag_handler: default_flag_handler
|
99
|
-
)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def rescue_with_default_handler
|
104
|
-
yield
|
105
|
-
rescue StandardError
|
106
|
-
if default_flag_handler
|
107
|
-
return Flagsmith::Flags::Collection.new(
|
108
|
-
{},
|
109
|
-
default_flag_handler: default_flag_handler
|
110
|
-
)
|
111
|
-
end
|
112
|
-
raise
|
113
|
-
end
|
114
|
-
|
115
|
-
def build_identity_model(identifier, traits = {})
|
116
|
-
unless environment
|
117
|
-
raise Flagsmith::ClientError,
|
118
|
-
'Unable to build identity model when no local environment present.'
|
119
|
-
end
|
120
|
-
|
121
|
-
trait_models = traits.map do |key, value|
|
122
|
-
Flagsmith::Engine::Identities::Trait.new(trait_key: key, trait_value: value)
|
123
|
-
end
|
124
|
-
Flagsmith::Engine::Identity.new(
|
125
|
-
identity_traits: trait_models, environment_api_key: environment_key, identifier: identifier
|
126
|
-
)
|
127
|
-
end
|
128
|
-
|
129
|
-
def generate_identities_data(identifier, traits = {})
|
130
|
-
{
|
131
|
-
identifier: identifier,
|
132
|
-
traits: traits.map { |key, value| { trait_key: key, trait_value: value } }
|
133
|
-
}
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|