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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 963916124a96866380ffb9defdda64421c2205e28f46a2dfe0fdecbb1c068989
4
- data.tar.gz: 97ecf1f596db52665c0c69d46df178ab47223c7eede56e6a2c2da222b2d760e2
3
+ metadata.gz: 18c4f2e2e68aaffe9c18d2b1e2af5f0018695ecc17c5af3a94051c8bf4cde1b8
4
+ data.tar.gz: 53e41364ca7a0347f0358d80616c4781f81835bff43b8f2aedc15d5fa53bb77d
5
5
  SHA512:
6
- metadata.gz: 73dd7ed243d419f59259c04edc73fde2e8a6bd915da45e2ac2db1c5ff802771e1ab59669a718f0e0af36cf2ff3f33206625785a52268e50fdc96cc9440537027
7
- data.tar.gz: 33248a4a9343cb15898d4db5821260f83c1d3ec4fed858cb7adbf612e6c0c355ccbe1e68b4e1f0861fe5fdd72d48ce9713bee4b12127d9bfb5d89e6a3b812888
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.1)
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.0)
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.4)
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/ruby/](https://docs.flagsmith.com/clients/ruby/)
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
@@ -172,7 +172,7 @@ GEM
172
172
  public_suffix (4.0.7)
173
173
  puma (5.6.4)
174
174
  nio4r (~> 2.0)
175
- rack (2.2.3)
175
+ rack (2.2.3.1)
176
176
  rack-test (1.1.0)
177
177
  rack (>= 1.0, < 3)
178
178
  rainbow (3.1.1)
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
- module Core
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
- return condition.match_trait_value?(trait.value) if trait
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(feature_id)
35
- @analytics_data[feature_id] = @analytics_data.fetch(feature_id, 0) + 1
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.feature_id) if @analytics_processor && flag.feature_id
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
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flagsmith
4
+ module Segments
5
+ class Segment
6
+ attr_reader :id, :name
7
+
8
+ def initialize(id:, name:)
9
+ @id = id
10
+ @name = name
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flagsmith
4
- VERSION = '3.0.1'
4
+ VERSION = '3.1.0'
5
5
  end
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/instance_methods'
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.1
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-06-09 00:00:00.000000000 Z
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.0.3.1
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