Skip to content

Commit c778707

Browse files
jsalaberCopilot
andauthored
feat: support cloud eval reasons (#123)
* feat: support cloud eval reasons * Update lib/devcycle-ruby-server-sdk/api/client.rb Co-authored-by: Copilot <[email protected]> * Update lib/devcycle-ruby-server-sdk/api/client.rb Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent 288c113 commit c778707

File tree

6 files changed

+109
-4
lines changed

6 files changed

+109
-4
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ group :development, :test do
1515
gem 'rake', '~> 13.0.1'
1616
gem 'pry-byebug'
1717
gem 'rubocop', '~> 1.57.1'
18+
gem 'webmock'
1819
end

lib/devcycle-ruby-server-sdk/api/client.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,14 +325,27 @@ def variable_with_http_info(key, user, default, opts = {})
325325
if @api_client.config.debugging
326326
@api_client.config.logger.debug "API called: DevCycle::Client#variable\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
327327
end
328+
if default && data.type
329+
api_type_to_ruby_class = {
330+
'Boolean' => [TrueClass, FalseClass],
331+
'Number' => [Integer, Float],
332+
'String' => [String],
333+
'JSON' => [Hash]
334+
}
335+
ruby_classes = api_type_to_ruby_class[data.type.to_s]
336+
unless ruby_classes && ruby_classes.any? { |klass| default.is_a?(klass) }
337+
eval = { reason: DevCycle::EVAL_REASONS::DEFAULT, details: DevCycle::DEFAULT_REASON_DETAILS::TYPE_MISMATCH }
338+
return Variable.new(key: key, value: default, isDefaulted: true, eval: eval)
339+
end
340+
end
328341
return data
329342
rescue ApiError => error
330-
if error.code != 404
343+
if error.code == 404
331344
@api_client.config.logger.error("Failed to retrieve variable value: #{error.message}")
332345
end
333346

334-
return Variable.new(key: key, value: default, isDefaulted: true)
335-
end
347+
return Variable.new(key: key, value: default, isDefaulted: true, eval: { reason: DevCycle::EVAL_REASONS::DEFAULT, details: DevCycle::DEFAULT_REASON_DETAILS::ERROR })
348+
end
336349
end
337350

338351
# Get all variables by key for user data

lib/devcycle-ruby-server-sdk/eval_reasons.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ module EVAL_REASONS
99
module DEFAULT_REASON_DETAILS
1010
MISSING_CONFIG = 'Missing Config'
1111
USER_NOT_TARGETED = 'User Not Targeted'
12+
TYPE_MISMATCH = 'Variable Type Mismatch'
13+
MISSING_VARIABLE = 'Missing Variable'
14+
ERROR = 'Error'
1215
end
1316
end

lib/devcycle-ruby-server-sdk/models/variable.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ def self.openapi_types
7878
:'type' => :'String',
7979
:'value' => :'Object',
8080
:'defaultValue' => :'Object',
81-
:'isDefaulted' => :'Boolean'
81+
:'isDefaulted' => :'Boolean',
82+
:'eval' => :'Object'
8283
}
8384
end
8485

spec/api/devcycle_api_spec.rb

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
require 'spec_helper'
1414
require 'json'
15+
require 'webmock'
16+
17+
include WebMock::API
1518

1619
# Unit tests for DevCycle::Client
1720
# Automatically generated by openapi-generator (https://openapi-generator.tech)
@@ -68,6 +71,8 @@
6871
it 'should work' do
6972
result = @api_instance.variable(@user, "ruby-example-tests-default", false)
7073
expect(result.isDefaulted).to eq true
74+
expect(result.eval[:reason]).to eq "DEFAULT"
75+
expect(result.eval[:details]).to eq "Error"
7176

7277
result = @api_instance.variable_value(@user, "ruby-example-tests-default", true)
7378
expect(result).to eq true
@@ -88,6 +93,51 @@
8893

8994
result = @api_instance.variable_value(@user, "test", true)
9095
expect(result).to eq true
96+
97+
result = @api_instance.variable(@user, "test-number-variable", 0)
98+
expect(result.isDefaulted).to eq false
99+
expect(result.value).to eq 123
100+
101+
result = @api_instance.variable(@user, "test-number-variable", 0)
102+
expect(result.isDefaulted).to eq false
103+
expect(result.value).to eq 123
104+
105+
result = @api_instance.variable(@user, "test-float-variable", 0.0)
106+
expect(result.isDefaulted).to eq false
107+
expect(result.value).to eq 4.56
108+
109+
result = @api_instance.variable(@user, "test-string-variable", "")
110+
expect(result.isDefaulted).to eq false
111+
expect(result.value).to eq "on"
112+
113+
result = @api_instance.variable(@user, "test-json-variable", {})
114+
expect(result.isDefaulted).to eq false
115+
expect(result.value).to eq({:message => "a"})
116+
117+
result = @api_instance.variable(@user, "test", "false")
118+
expect(result.isDefaulted).to eq true
119+
expect(result.eval[:reason]).to eq "DEFAULT"
120+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
121+
122+
result = @api_instance.variable(@user, "test-number-variable", "123")
123+
expect(result.isDefaulted).to eq true
124+
expect(result.eval[:reason]).to eq "DEFAULT"
125+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
126+
127+
result = @api_instance.variable(@user, "test-number-variable", true)
128+
expect(result.isDefaulted).to eq true
129+
expect(result.eval[:reason]).to eq "DEFAULT"
130+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
131+
132+
result = @api_instance.variable(@user, "test-string-variable", true)
133+
expect(result.isDefaulted).to eq true
134+
expect(result.eval[:reason]).to eq "DEFAULT"
135+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
136+
137+
result = @api_instance.variable(@user, "test-json-variable", "on")
138+
expect(result.isDefaulted).to eq true
139+
expect(result.eval[:reason]).to eq "DEFAULT"
140+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
91141
end
92142
end
93143

@@ -104,4 +154,37 @@
104154
end
105155
end
106156

157+
describe 'get_variable_by_key test' do
158+
before do
159+
WebMock.disable_net_connect!(allow_localhost: true)
160+
end
161+
162+
after do
163+
WebMock.allow_net_connect!
164+
end
165+
166+
it 'should work with mocked response' do
167+
stub_request(:post, "https://bucketing-api.devcycle.com/v1/variables/mocked_variable").
168+
to_return(status: 200, body: "{\"isDefaulted\": false, \"value\": true, \"eval\": {\"reason\": \"SPLIT\", \"details\": \"Random Distribution | All Users\", \"target_id\": \"621642332ea68943c8833c4d\"}}", headers: {})
169+
170+
result = @api_instance.variable(@user, "mocked_variable", false)
171+
expect(result.isDefaulted).to eq false
172+
expect(result.value).to eq true
173+
# Use Hash syntax since eval is deserialized as a Hash
174+
expect(result.eval[:reason]).to eq "SPLIT"
175+
expect(result.eval[:details]).to eq "Random Distribution | All Users"
176+
expect(result.eval[:target_id]).to eq "621642332ea68943c8833c4d"
177+
end
178+
179+
it 'should return error details' do
180+
stub_request(:post, "https://bucketing-api.devcycle.com/v1/variables/test").
181+
to_return(status: 500, body: "{\"isDefaulted\": true, \"value\": false, \"eval\": {\"reason\": \"DEFAULT\", \"details\": \"Error\"}}", headers: {})
182+
183+
result = @api_instance.variable(@user, "test", false)
184+
expect(result.isDefaulted).to eq true
185+
expect(result.eval[:reason]).to eq "DEFAULT"
186+
expect(result.eval[:details]).to eq "Error"
187+
end
188+
end
189+
107190
end

spec/spec_helper.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212

1313
# load the gem
1414
require 'devcycle-ruby-server-sdk'
15+
require 'webmock/rspec'
16+
17+
# Configure WebMock to allow real HTTP requests by default, but enable it for specific tests
18+
WebMock.allow_net_connect!
1519

1620
# The following was generated by the `rspec --init` command. Conventionally, all
1721
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.

0 commit comments

Comments
 (0)