flagsmith 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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