featurevisor 0.1.1 → 0.2.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: 7b51aa1bea2c05bb11437fc38b488f959de46b190e0c0ed7c9c6f39ee53f978e
4
- data.tar.gz: 2a6062fcb9aafddb52dad685b781c8049f64bc74df04aa9b5267de878884f46f
3
+ metadata.gz: 984dcbada7b55c304a639cf58935c7b1dd561db2d6159b178a3829709473925a
4
+ data.tar.gz: 2a4068e17a151e671b45befb743be0935b19432e91411a243e2b3f8cbfa2c1e2
5
5
  SHA512:
6
- metadata.gz: af2413b5ca231e827ae57ad580c1ea0f31e117e229fed5161c5cd87d66629865c5cddf3c978f84dea3659427809c80530a297160cc39ea207b5fb6e5fdf7bcf8
7
- data.tar.gz: 8edc93ec41d1a73ef115fd8e739aafb7d1e3db6c1fb8199334a1608f8e8a4a75f574b10f2b16bc58de019fe0b8b1540cc4e21f51ea010292bb4650173725df86
6
+ metadata.gz: b813718a6962bd78a1142e5cd7758c3a0ea176d6fc8943114bfb6c630ece7e2dc160281ec7ca661d9de012366ba7b1e3ceeff9af6f6e7bfcdc4b53d89e3ac04b
7
+ data.tar.gz: 3fcc3e23b3b773c7780e5d018679c74a453e263797342b0912b02c74d634d60b4029c7e042f74225ba6550d7f293ab9819ff657f51a318f90a026b145fc896bb
data/README.md CHANGED
@@ -81,7 +81,9 @@ require 'json'
81
81
  # Fetch datafile from URL
82
82
  datafile_url = 'https://cdn.yoursite.com/datafile.json'
83
83
  response = Net::HTTP.get_response(URI(datafile_url))
84
- datafile_content = JSON.parse(response.body)
84
+
85
+ # Parse JSON with symbolized keys (required)
86
+ datafile_content = JSON.parse(response.body, symbolize_names: true)
85
87
 
86
88
  # Create SDK instance
87
89
  f = Featurevisor.create_instance(
@@ -89,6 +91,19 @@ f = Featurevisor.create_instance(
89
91
  )
90
92
  ```
91
93
 
94
+ **Important**: When parsing JSON datafiles, you must use `symbolize_names: true` to ensure proper key handling by the SDK.
95
+
96
+ Alternatively, you can pass a JSON string directly and the SDK will parse it automatically:
97
+
98
+ ```ruby
99
+ # Option 1: Parse JSON yourself (recommended)
100
+ datafile_content = JSON.parse(json_string, symbolize_names: true)
101
+ f = Featurevisor.create_instance(datafile: datafile_content)
102
+
103
+ # Option 2: Pass JSON string directly (automatic parsing)
104
+ f = Featurevisor.create_instance(datafile: json_string)
105
+ ```
106
+
92
107
  ## Evaluation types
93
108
 
94
109
  We can evaluate 3 types of values against a particular [feature](https://featurevisor.com/docs/features/):
@@ -334,9 +349,16 @@ f.set_sticky({
334
349
  You may also initialize the SDK without passing `datafile`, and set it later on:
335
350
 
336
351
  ```ruby
352
+ # Parse with symbolized keys before setting
353
+ datafile_content = JSON.parse(json_string, symbolize_names: true)
337
354
  f.set_datafile(datafile_content)
355
+
356
+ # Or pass JSON string directly for automatic parsing
357
+ f.set_datafile(json_string)
338
358
  ```
339
359
 
360
+ **Important**: When calling `set_datafile()`, ensure JSON is parsed with `symbolize_names: true` if you're parsing it yourself.
361
+
340
362
  ### Updating datafile
341
363
 
342
364
  You can set the datafile as many times as you want in your application, which will result in emitting a [`datafile_set`](#datafile_set) event that you can listen and react to accordingly.
@@ -715,7 +737,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
715
737
  - Push commit to `main` branch
716
738
  - Wait for CI to complete
717
739
  - Tag the release with the version number
718
- - This will trigger a new release to RubyGems
740
+ - This will trigger a new release to [RubyGems](https://rubygems.org/gems/featurevisor)
719
741
 
720
742
  ## License
721
743
 
@@ -58,8 +58,8 @@ module FeaturevisorCLI
58
58
 
59
59
  # Initialize evaluation counters
60
60
  flag_evaluations = {
61
- "enabled" => 0,
62
- "disabled" => 0
61
+ enabled: 0,
62
+ disabled: 0
63
63
  }
64
64
  variation_evaluations = {}
65
65
 
@@ -78,9 +78,9 @@ module FeaturevisorCLI
78
78
  # Evaluate flag
79
79
  flag_evaluation = instance.is_enabled(@options.feature, context_copy)
80
80
  if flag_evaluation
81
- flag_evaluations["enabled"] += 1
81
+ flag_evaluations[:enabled] += 1
82
82
  else
83
- flag_evaluations["disabled"] += 1
83
+ flag_evaluations[:disabled] += 1
84
84
  end
85
85
 
86
86
  # Evaluate variation if feature has variations
@@ -147,7 +147,7 @@ module FeaturevisorCLI
147
147
  end
148
148
 
149
149
  begin
150
- JSON.parse(stdout)
150
+ JSON.parse(stdout, symbolize_names: true)
151
151
  rescue JSON::ParserError => e
152
152
  puts "Error: Failed to parse datafile JSON: #{e.message}"
153
153
  exit 1
@@ -160,27 +160,13 @@ module FeaturevisorCLI
160
160
  end
161
161
 
162
162
  def create_instance(datafile)
163
- # Convert datafile to proper format for the SDK
164
- symbolized_datafile = symbolize_keys(datafile)
165
-
166
163
  # Create SDK instance
167
164
  Featurevisor.create_instance(
168
- datafile: symbolized_datafile,
165
+ datafile: datafile,
169
166
  log_level: get_logger_level
170
167
  )
171
168
  end
172
169
 
173
- def symbolize_keys(obj)
174
- case obj
175
- when Hash
176
- obj.transform_keys(&:to_sym).transform_values { |v| symbolize_keys(v) }
177
- when Array
178
- obj.map { |item| symbolize_keys(item) }
179
- else
180
- obj
181
- end
182
- end
183
-
184
170
  def get_logger_level
185
171
  if @options.verbose
186
172
  "debug"
@@ -120,7 +120,7 @@ module FeaturevisorCLI
120
120
 
121
121
  # Parse the JSON output
122
122
  begin
123
- JSON.parse(datafile_output)
123
+ JSON.parse(datafile_output, symbolize_names: true)
124
124
  rescue JSON::ParserError => e
125
125
  puts "Error: Failed to parse datafile JSON: #{e.message}"
126
126
  puts "Command output: #{datafile_output}"
@@ -143,16 +143,13 @@ module FeaturevisorCLI
143
143
  end
144
144
 
145
145
  def create_instance(datafile)
146
- # Convert string keys to symbols for the SDK
147
- symbolized_datafile = symbolize_keys(datafile)
148
-
149
146
  # Create a real Featurevisor instance
150
147
  instance = Featurevisor.create_instance(
151
148
  log_level: get_logger_level
152
149
  )
153
150
 
154
151
  # Explicitly set the datafile
155
- instance.set_datafile(symbolized_datafile)
152
+ instance.set_datafile(datafile)
156
153
 
157
154
  instance
158
155
  end
@@ -167,17 +164,6 @@ module FeaturevisorCLI
167
164
  end
168
165
  end
169
166
 
170
- def symbolize_keys(obj)
171
- case obj
172
- when Hash
173
- obj.transform_keys(&:to_sym).transform_values { |v| symbolize_keys(v) }
174
- when Array
175
- obj.map { |item| symbolize_keys(item) }
176
- else
177
- obj
178
- end
179
- end
180
-
181
167
  def benchmark_feature_flag(instance, feature_key, context, n)
182
168
  start_time = Time.now
183
169
 
data/bin/commands/test.rb CHANGED
@@ -19,13 +19,13 @@ module FeaturevisorCLI
19
19
 
20
20
  # Get project configuration
21
21
  config = get_config
22
- environments = config["environments"] || []
22
+ environments = config[:environments] || []
23
23
  segments_by_key = get_segments
24
24
 
25
25
  # Use CLI schemaVersion option or fallback to config
26
26
  schema_version = @options.schema_version
27
27
  if schema_version.nil? || schema_version.empty?
28
- schema_version = config["schemaVersion"]
28
+ schema_version = config[:schemaVersion]
29
29
  end
30
30
 
31
31
  # Build datafiles for all environments
@@ -57,7 +57,7 @@ module FeaturevisorCLI
57
57
  config_output = execute_command(command)
58
58
 
59
59
  begin
60
- JSON.parse(config_output)
60
+ JSON.parse(config_output, symbolize_names: true)
61
61
  rescue JSON::ParserError => e
62
62
  puts "Error: Failed to parse config JSON: #{e.message}"
63
63
  puts "Command output: #{config_output}"
@@ -71,11 +71,11 @@ module FeaturevisorCLI
71
71
  segments_output = execute_command(command)
72
72
 
73
73
  begin
74
- segments = JSON.parse(segments_output)
74
+ segments = JSON.parse(segments_output, symbolize_names: true)
75
75
  segments_by_key = {}
76
76
  segments.each do |segment|
77
- if segment["key"]
78
- segments_by_key[segment["key"]] = segment
77
+ if segment[:key]
78
+ segments_by_key[segment[:key]] = segment
79
79
  end
80
80
  end
81
81
  segments_by_key
@@ -110,7 +110,7 @@ module FeaturevisorCLI
110
110
  datafile_output = execute_command(command)
111
111
 
112
112
  begin
113
- datafile = JSON.parse(datafile_output)
113
+ datafile = JSON.parse(datafile_output, symbolize_names: true)
114
114
  datafiles_by_environment[environment] = datafile
115
115
  rescue JSON::ParserError => e
116
116
  puts "Error: Failed to parse datafile JSON for #{environment}: #{e.message}"
@@ -147,7 +147,7 @@ module FeaturevisorCLI
147
147
  tests_output = execute_command(command)
148
148
 
149
149
  begin
150
- JSON.parse(tests_output)
150
+ JSON.parse(tests_output, symbolize_names: true)
151
151
  rescue JSON::ParserError => e
152
152
  puts "Error: Failed to parse tests JSON: #{e.message}"
153
153
  puts "Command output: #{tests_output}"
@@ -161,12 +161,9 @@ module FeaturevisorCLI
161
161
  environments.each do |environment|
162
162
  datafile = datafiles_by_environment[environment]
163
163
 
164
- # Convert string keys to symbols for the SDK
165
- symbolized_datafile = symbolize_keys(datafile)
166
-
167
164
  # Create SDK instance
168
165
  instance = Featurevisor.create_instance(
169
- datafile: symbolized_datafile,
166
+ datafile: datafile,
170
167
  log_level: level,
171
168
  hooks: [
172
169
  {
@@ -189,8 +186,8 @@ module FeaturevisorCLI
189
186
  failed_assertions_count = 0
190
187
 
191
188
  tests.each do |test|
192
- test_key = test["key"]
193
- assertions = test["assertions"] || []
189
+ test_key = test[:key]
190
+ assertions = test[:assertions] || []
194
191
  results = ""
195
192
  test_has_error = false
196
193
  test_duration = 0.0
@@ -199,8 +196,8 @@ module FeaturevisorCLI
199
196
  if assertion.is_a?(Hash)
200
197
  test_result = nil
201
198
 
202
- if test["feature"]
203
- environment = assertion["environment"]
199
+ if test[:feature]
200
+ environment = assertion[:environment]
204
201
  instance = sdk_instances_by_environment[environment]
205
202
 
206
203
  # Show datafile if requested
@@ -212,12 +209,11 @@ module FeaturevisorCLI
212
209
  end
213
210
 
214
211
  # If "at" parameter is provided, create a new instance with the specific hook
215
- if assertion["at"]
212
+ if assertion[:at]
216
213
  datafile = datafiles_by_environment[environment]
217
- symbolized_datafile = symbolize_keys(datafile)
218
214
 
219
215
  instance = Featurevisor.create_instance(
220
- datafile: symbolized_datafile,
216
+ datafile: datafile,
221
217
  log_level: level,
222
218
  hooks: [
223
219
  {
@@ -225,7 +221,7 @@ module FeaturevisorCLI
225
221
  bucket_value: ->(options) do
226
222
  # Match JavaScript implementation: assertion.at * (MAX_BUCKETED_NUMBER / 100)
227
223
  # MAX_BUCKETED_NUMBER is 100000, so this becomes assertion.at * 1000
228
- at = assertion["at"]
224
+ at = assertion[:at]
229
225
  if at.is_a?(Numeric)
230
226
  (at * 1000).to_i
231
227
  else
@@ -237,9 +233,9 @@ module FeaturevisorCLI
237
233
  )
238
234
  end
239
235
 
240
- test_result = run_test_feature(assertion, test["feature"], instance, level)
241
- elsif test["segment"]
242
- segment_key = test["segment"]
236
+ test_result = run_test_feature(assertion, test[:feature], instance, level)
237
+ elsif test[:segment]
238
+ segment_key = test[:segment]
243
239
  segment = segments_by_key[segment_key]
244
240
  if segment.is_a?(Hash)
245
241
  test_result = run_test_segment(assertion, segment, level)
@@ -250,12 +246,12 @@ module FeaturevisorCLI
250
246
  test_duration += test_result[:duration]
251
247
 
252
248
  if test_result[:has_error]
253
- results += " ✘ #{assertion['description']} (#{(test_result[:duration] * 1000).round(2)}ms)\n"
249
+ results += " ✘ #{assertion[:description]} (#{(test_result[:duration] * 1000).round(2)}ms)\n"
254
250
  results += test_result[:errors]
255
251
  test_has_error = true
256
252
  failed_assertions_count += 1
257
253
  else
258
- results += " ✔ #{assertion['description']} (#{(test_result[:duration] * 1000).round(2)}ms)\n"
254
+ results += " ✔ #{assertion[:description]} (#{(test_result[:duration] * 1000).round(2)}ms)\n"
259
255
  passed_assertions_count += 1
260
256
  end
261
257
  end
@@ -285,8 +281,8 @@ module FeaturevisorCLI
285
281
  end
286
282
 
287
283
  def run_test_feature(assertion, feature_key, instance, level)
288
- context = parse_context(assertion["context"])
289
- sticky = parse_sticky(assertion["sticky"])
284
+ context = parse_context(assertion[:context])
285
+ sticky = parse_sticky(assertion[:sticky])
290
286
 
291
287
  # Set context and sticky for this assertion
292
288
  instance.set_context(context, false)
@@ -302,8 +298,8 @@ module FeaturevisorCLI
302
298
  start_time = Time.now
303
299
 
304
300
  # Test expectedToBeEnabled
305
- if assertion.key?("expectedToBeEnabled")
306
- expected_to_be_enabled = assertion["expectedToBeEnabled"]
301
+ if assertion.key?(:expectedToBeEnabled)
302
+ expected_to_be_enabled = assertion[:expectedToBeEnabled]
307
303
  is_enabled = instance.is_enabled(feature_key, context, override_options)
308
304
 
309
305
  if is_enabled != expected_to_be_enabled
@@ -313,8 +309,8 @@ module FeaturevisorCLI
313
309
  end
314
310
 
315
311
  # Test expectedVariation
316
- if assertion.key?("expectedVariation")
317
- expected_variation = assertion["expectedVariation"]
312
+ if assertion.key?(:expectedVariation)
313
+ expected_variation = assertion[:expectedVariation]
318
314
  variation = instance.get_variation(feature_key, context, override_options)
319
315
 
320
316
  variation_value = variation.nil? ? nil : variation
@@ -325,12 +321,12 @@ module FeaturevisorCLI
325
321
  end
326
322
 
327
323
  # Test expectedVariables
328
- if assertion["expectedVariables"]
329
- expected_variables = assertion["expectedVariables"]
324
+ if assertion[:expectedVariables]
325
+ expected_variables = assertion[:expectedVariables]
330
326
  expected_variables.each do |variable_key, expected_value|
331
327
  # Set default variable value for this specific variable
332
- if assertion["defaultVariableValues"] && assertion["defaultVariableValues"][variable_key]
333
- override_options[:default_variable_value] = assertion["defaultVariableValues"][variable_key]
328
+ if assertion[:defaultVariableValues] && assertion[:defaultVariableValues][variable_key]
329
+ override_options[:default_variable_value] = assertion[:defaultVariableValues][variable_key]
334
330
  end
335
331
 
336
332
  actual_value = instance.get_variable(feature_key, variable_key, context, override_options)
@@ -369,13 +365,13 @@ module FeaturevisorCLI
369
365
  end
370
366
 
371
367
  # Test expectedEvaluations
372
- if assertion["expectedEvaluations"]
373
- expected_evaluations = assertion["expectedEvaluations"]
368
+ if assertion[:expectedEvaluations]
369
+ expected_evaluations = assertion[:expectedEvaluations]
374
370
 
375
371
  # Test flag evaluations
376
- if expected_evaluations["flag"]
372
+ if expected_evaluations[:flag]
377
373
  evaluation = instance.evaluate_flag(feature_key, context, override_options)
378
- expected_evaluations["flag"].each do |key, expected_value|
374
+ expected_evaluations[:flag].each do |key, expected_value|
379
375
  actual_value = get_evaluation_value(evaluation, key)
380
376
  if !compare_values(actual_value, expected_value)
381
377
  has_error = true
@@ -385,9 +381,9 @@ module FeaturevisorCLI
385
381
  end
386
382
 
387
383
  # Test variation evaluations
388
- if expected_evaluations["variation"]
384
+ if expected_evaluations[:variation]
389
385
  evaluation = instance.evaluate_variation(feature_key, context, override_options)
390
- expected_evaluations["variation"].each do |key, expected_value|
386
+ expected_evaluations[:variation].each do |key, expected_value|
391
387
  actual_value = get_evaluation_value(evaluation, key)
392
388
  if !compare_values(actual_value, expected_value)
393
389
  has_error = true
@@ -397,8 +393,8 @@ module FeaturevisorCLI
397
393
  end
398
394
 
399
395
  # Test variable evaluations
400
- if expected_evaluations["variables"]
401
- expected_evaluations["variables"].each do |variable_key, expected_eval|
396
+ if expected_evaluations[:variables]
397
+ expected_evaluations[:variables].each do |variable_key, expected_eval|
402
398
  if expected_eval.is_a?(Hash)
403
399
  evaluation = instance.evaluate_variable(feature_key, variable_key, context, override_options)
404
400
  expected_eval.each do |key, expected_value|
@@ -414,10 +410,10 @@ module FeaturevisorCLI
414
410
  end
415
411
 
416
412
  # Test children
417
- if assertion["children"]
418
- assertion["children"].each do |child|
413
+ if assertion[:children]
414
+ assertion[:children].each do |child|
419
415
  if child.is_a?(Hash)
420
- child_context = parse_context(child["context"])
416
+ child_context = parse_context(child[:context])
421
417
 
422
418
  # Create override options for child with sticky values
423
419
  child_override_options = create_override_options(child)
@@ -452,7 +448,7 @@ module FeaturevisorCLI
452
448
  end
453
449
 
454
450
  def run_test_feature_child(assertion, feature_key, instance, level)
455
- context = parse_context(assertion["context"])
451
+ context = parse_context(assertion[:context])
456
452
  override_options = create_override_options(assertion)
457
453
 
458
454
  has_error = false
@@ -460,8 +456,8 @@ module FeaturevisorCLI
460
456
  start_time = Time.now
461
457
 
462
458
  # Test expectedToBeEnabled
463
- if assertion.key?("expectedToBeEnabled")
464
- expected_to_be_enabled = assertion["expectedToBeEnabled"]
459
+ if assertion.key?(:expectedToBeEnabled)
460
+ expected_to_be_enabled = assertion[:expectedToBeEnabled]
465
461
  is_enabled = instance.is_enabled(feature_key, context, override_options)
466
462
 
467
463
  if is_enabled != expected_to_be_enabled
@@ -471,8 +467,8 @@ module FeaturevisorCLI
471
467
  end
472
468
 
473
469
  # Test expectedVariation
474
- if assertion.key?("expectedVariation")
475
- expected_variation = assertion["expectedVariation"]
470
+ if assertion.key?(:expectedVariation)
471
+ expected_variation = assertion[:expectedVariation]
476
472
  variation = instance.get_variation(feature_key, context, override_options)
477
473
 
478
474
  variation_value = variation.nil? ? nil : variation
@@ -483,12 +479,12 @@ module FeaturevisorCLI
483
479
  end
484
480
 
485
481
  # Test expectedVariables
486
- if assertion["expectedVariables"]
487
- expected_variables = assertion["expectedVariables"]
482
+ if assertion[:expectedVariables]
483
+ expected_variables = assertion[:expectedVariables]
488
484
  expected_variables.each do |variable_key, expected_value|
489
485
  # Set default variable value for this specific variable
490
- if assertion["defaultVariableValues"] && assertion["defaultVariableValues"][variable_key]
491
- override_options[:default_variable_value] = assertion["defaultVariableValues"][variable_key]
486
+ if assertion[:defaultVariableValues] && assertion[:defaultVariableValues][variable_key]
487
+ override_options[:default_variable_value] = assertion[:defaultVariableValues][variable_key]
492
488
  end
493
489
 
494
490
  actual_value = instance.get_variable(feature_key, variable_key, context, override_options)
@@ -536,8 +532,8 @@ module FeaturevisorCLI
536
532
  end
537
533
 
538
534
  def run_test_segment(assertion, segment, level)
539
- context = parse_context(assertion["context"])
540
- conditions = segment["conditions"]
535
+ context = parse_context(assertion[:context])
536
+ conditions = segment[:conditions]
541
537
 
542
538
  # Create a minimal datafile for segment testing
543
539
  datafile = {
@@ -549,7 +545,7 @@ module FeaturevisorCLI
549
545
 
550
546
  # Create SDK instance for segment testing
551
547
  instance = Featurevisor.create_instance(
552
- datafile: symbolize_keys(datafile),
548
+ datafile: datafile,
553
549
  log_level: level
554
550
  )
555
551
 
@@ -557,8 +553,8 @@ module FeaturevisorCLI
557
553
  errors = ""
558
554
  start_time = Time.now
559
555
 
560
- if assertion.key?("expectedToMatch")
561
- expected_to_match = assertion["expectedToMatch"]
556
+ if assertion.key?(:expectedToMatch)
557
+ expected_to_match = assertion[:expectedToMatch]
562
558
  actual = instance.instance_variable_get(:@datafile_reader).all_conditions_are_matched(conditions, context)
563
559
 
564
560
  if actual != expected_to_match
@@ -593,16 +589,16 @@ module FeaturevisorCLI
593
589
  if value.is_a?(Hash)
594
590
  evaluated_feature = {}
595
591
 
596
- if value.key?("enabled")
597
- evaluated_feature[:enabled] = value["enabled"]
592
+ if value.key?(:enabled)
593
+ evaluated_feature[:enabled] = value[:enabled]
598
594
  end
599
595
 
600
- if value.key?("variation")
601
- evaluated_feature[:variation] = value["variation"]
596
+ if value.key?(:variation)
597
+ evaluated_feature[:variation] = value[:variation]
602
598
  end
603
599
 
604
- if value["variables"] && value["variables"].is_a?(Hash)
605
- evaluated_feature[:variables] = value["variables"].transform_keys(&:to_sym)
600
+ if value[:variables] && value[:variables].is_a?(Hash)
601
+ evaluated_feature[:variables] = value[:variables].transform_keys(&:to_sym)
606
602
  end
607
603
 
608
604
  sticky_features[key.to_sym] = evaluated_feature
@@ -618,8 +614,8 @@ module FeaturevisorCLI
618
614
  def create_override_options(assertion)
619
615
  options = {}
620
616
 
621
- if assertion["defaultVariationValue"]
622
- options[:default_variation_value] = assertion["defaultVariationValue"]
617
+ if assertion[:defaultVariationValue]
618
+ options[:default_variation_value] = assertion[:defaultVariationValue]
623
619
  end
624
620
 
625
621
  options
@@ -627,41 +623,41 @@ module FeaturevisorCLI
627
623
 
628
624
  def get_evaluation_value(evaluation, key)
629
625
  case key
630
- when "type"
626
+ when :type
631
627
  evaluation[:type]
632
- when "featureKey"
628
+ when :featureKey
633
629
  evaluation[:feature_key]
634
- when "reason"
630
+ when :reason
635
631
  evaluation[:reason]
636
- when "bucketKey"
632
+ when :bucketKey
637
633
  evaluation[:bucket_key]
638
- when "bucketValue"
634
+ when :bucketValue
639
635
  evaluation[:bucket_value]
640
- when "ruleKey"
636
+ when :ruleKey
641
637
  evaluation[:rule_key]
642
- when "error"
638
+ when :error
643
639
  evaluation[:error]
644
- when "enabled"
640
+ when :enabled
645
641
  evaluation[:enabled]
646
- when "traffic"
642
+ when :traffic
647
643
  evaluation[:traffic]
648
- when "forceIndex"
644
+ when :forceIndex
649
645
  evaluation[:force_index]
650
- when "force"
646
+ when :force
651
647
  evaluation[:force]
652
- when "required"
648
+ when :required
653
649
  evaluation[:required]
654
- when "sticky"
650
+ when :sticky
655
651
  evaluation[:sticky]
656
- when "variation"
652
+ when :variation
657
653
  evaluation[:variation]
658
- when "variationValue"
654
+ when :variationValue
659
655
  evaluation[:variation_value]
660
- when "variableKey"
656
+ when :variableKey
661
657
  evaluation[:variable_key]
662
- when "variableValue"
658
+ when :variableValue
663
659
  evaluation[:variable_value]
664
- when "variableSchema"
660
+ when :variableSchema
665
661
  evaluation[:variable_schema]
666
662
  else
667
663
  nil
@@ -765,16 +761,7 @@ module FeaturevisorCLI
765
761
  end
766
762
  end
767
763
 
768
- def symbolize_keys(obj)
769
- case obj
770
- when Hash
771
- obj.transform_keys(&:to_sym).transform_values { |v| symbolize_keys(v) }
772
- when Array
773
- obj.map { |v| symbolize_keys(v) }
774
- else
775
- obj
776
- end
777
- end
764
+
778
765
 
779
766
  def execute_command(command)
780
767
  stdout, stderr, status = Open3.capture3(command)
@@ -53,12 +53,12 @@ module Featurevisor
53
53
  if value.is_a?(Array) && (context_value_from_path.is_a?(String) || context_value_from_path.is_a?(Numeric) || context_value_from_path.nil?)
54
54
  # Check if the attribute key actually exists in the context
55
55
  key_exists = context.key?(attribute.to_sym) || context.key?(attribute.to_s)
56
-
56
+
57
57
  # If key doesn't exist, notIn should fail (return false), in should also fail
58
58
  if !key_exists
59
59
  return false
60
60
  end
61
-
61
+
62
62
  value_in_context = context_value_from_path.to_s
63
63
 
64
64
  if operator == "in"
@@ -183,6 +183,8 @@ module Featurevisor
183
183
  end
184
184
  end
185
185
 
186
+
187
+
186
188
  if conditions.is_a?(Array)
187
189
  return conditions.all? { |c| all_conditions_are_matched(c, context) }
188
190
  end
@@ -245,6 +247,8 @@ module Featurevisor
245
247
  all_segments_are_matched({ "and" => group_segments["not"] }, context) == false
246
248
  end
247
249
  end
250
+
251
+
248
252
  end
249
253
 
250
254
  if group_segments.is_a?(Array)
@@ -42,7 +42,7 @@ module Featurevisor
42
42
 
43
43
  if options[:datafile]
44
44
  @datafile_reader = Featurevisor::DatafileReader.new(
45
- datafile: options[:datafile].is_a?(String) ? JSON.parse(options[:datafile]) : options[:datafile],
45
+ datafile: options[:datafile].is_a?(String) ? JSON.parse(options[:datafile], symbolize_names: true) : options[:datafile],
46
46
  logger: @logger
47
47
  )
48
48
  end
@@ -61,7 +61,7 @@ module Featurevisor
61
61
  def set_datafile(datafile)
62
62
  begin
63
63
  new_datafile_reader = Featurevisor::DatafileReader.new(
64
- datafile: datafile.is_a?(String) ? JSON.parse(datafile) : datafile,
64
+ datafile: datafile.is_a?(String) ? JSON.parse(datafile, symbolize_names: true) : datafile,
65
65
  logger: @logger
66
66
  )
67
67
 
@@ -1,3 +1,3 @@
1
1
  module Featurevisor
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: featurevisor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fahad Heylaal