absmartly-sdk 0.1.2 → 1.0.5

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: 16d7c8f31de8bdbceddf60618c90ddfc81ab73381403d957a7bd8a3fbdb43d3a
4
- data.tar.gz: 2145b7d168f0e425164e1fcccb14d3efbd1ac4d91ddc3c5ebc120fca32734cdf
3
+ metadata.gz: 85cc6f9a1f752cedc113e346ddd7fbbe885e18a571d94cb4696fbeb65afcfaf3
4
+ data.tar.gz: 7a16ba9a23c51f82030beb5cc25e0bff6da063bacdecfef24d506a843d63c29d
5
5
  SHA512:
6
- metadata.gz: 840d40d52e3878321a7d08ebfe1bb38e9db8994a3296afc2d3de43383ca01b8b0cc0513a2a0e4480b679ef38a8c3edda3688bd0bbcbb7b5a82c39a7f979ba595
7
- data.tar.gz: cb15ab60ca2a4cd40e736b8b69b5a32b131f9a92ac8942cb3b48d16fb20b67915636035b30dd2b8d5c7039ec787509fcd3080773aa902fe23988742cce027269
6
+ metadata.gz: 7ce160a8e6898a17504f4292f87443ba8c8b18c15f953464ba04e16388a98dc091c73854cebc7e18fa0d6cce02be73969a5b3979d9a2e281913ce6753e592bca
7
+ data.tar.gz: 6e057f2dcdaa1a7d1b5916baf6f28eaec66b8240433d6c28ea776238e87b39f179ca0084f30ed7bef1dda372d7e8dc0a42b3e5bac090ebe8ad1ad6ea1edb0cc7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- absmartly (0.1.0)
4
+ absmartly-sdk (1.0.5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -78,7 +78,7 @@ PLATFORMS
78
78
  x86_64-darwin-20
79
79
 
80
80
  DEPENDENCIES
81
- absmartly!
81
+ absmartly-sdk!
82
82
  arraybuffer
83
83
  byebug
84
84
  faraday
data/README.md ADDED
@@ -0,0 +1,253 @@
1
+ # A/B Smartly SDK
2
+
3
+ A/B Smartly Ruby SDK
4
+
5
+ ## Compatibility
6
+
7
+ The A/B Smartly Ruby SDK is compatible with Ruby versions 2.7 and later. For the best performance and code readability, Ruby 3 or later is recommended. This SDK is being constantly tested with the nightly builds of Ruby, to ensure it is compatible with the latest Ruby version.
8
+
9
+
10
+ ## Getting Started
11
+
12
+ ### Install the SDK
13
+
14
+ Install the gem and add to the application's Gemfile by executing:
15
+
16
+ $ bundle add absmartly-sdk
17
+
18
+ If bundler is not being used to manage dependencies, install the gem by executing:
19
+
20
+ $ gem install absmartly-sdk
21
+
22
+ ## Import and Initialize the SDK
23
+
24
+ Once the SDK is installed, it can be initialized in your project.
25
+
26
+ ```ruby
27
+ Absmartly.configure_client do |config|
28
+ config.endpoint = "https://your-company.absmartly.io/v1"
29
+ config.api_key = "YOUR-API-KEY"
30
+ config.application = "website"
31
+ config.environment = "development"
32
+ end
33
+ ```
34
+
35
+ **SDK Options**
36
+
37
+ | Config | Type | Required? | Default | Description |
38
+ | :---------- | :----------------------------------- | :-------: | :-------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
39
+ | endpoint | `string` | ✅ | `undefined` | The URL to your API endpoint. Most commonly `"your-company.absmartly.io"` |
40
+ | apiKey | `string` | ✅ | `undefined` | Your API key which can be found on the Web Console. |
41
+ | environment | `"production"` or `"development"` | ✅ | `undefined` | The environment of the platform where the SDK is installed. Environments are created on the Web Console and should match the available environments in your infrastructure. |
42
+ | application | `string` | ✅ | `undefined` | The name of the application where the SDK is installed. Applications are created on the Web Console and should match the applications where your experiments will be running. |
43
+ | retries | `number` | ❌ | `5` | The number of retries before the SDK stops trying to connect. |
44
+ | timeout | `number` | ❌ | `3000` | An amount of time, in milliseconds, before the SDK will stop trying to connect. |
45
+ | eventLogger | `(context, eventName, data) => void` | ❌ | See "Using a Custom Event Logger" below | A callback function which runs after SDK events. |
46
+
47
+ ### Using a Custom Event Logger
48
+
49
+ The A/B Smartly SDK can be instantiated with an event logger used for all
50
+ contexts. In addition, an event logger can be specified when creating a
51
+ particular context, in the `[CONTEXT_CONFIG_VARIABLE]`.
52
+
53
+ ```
54
+ Custom Event Logger Code
55
+ ```
56
+
57
+ The data parameter depends on the type of event. Currently, the SDK logs the
58
+ following events:
59
+
60
+ | eventName | when | data |
61
+ | ------------ | ------------------------------------------------------- | -------------------------------------------- |
62
+ | `"error"` | `Context` receives an error | error object thrown |
63
+ | `"ready"` | `Context` turns ready | data used to initialize the context |
64
+ | `"refresh"` | `Context.refresh()` method succeeds | data used to refresh the context |
65
+ | `"publish"` | `Context.publish()` method succeeds | data sent to the A/B Smartly event collector |
66
+ | `"exposure"` | `Context.treatment()` method succeeds on first exposure | exposure data enqueued for publishing |
67
+ | `"goal"` | `Context.track()` method succeeds | goal data enqueued for publishing |
68
+ | `"close"` | `Context.close()` method succeeds the first time | nil |
69
+
70
+ ## Create a New Context Request
71
+
72
+
73
+ ```ruby
74
+ context_config = Absmartly.create_context_config
75
+ ```
76
+
77
+ **With Prefetched Data**
78
+
79
+ ```ruby
80
+ client_config = ClientConfig.new(
81
+ endpoint: 'https://your-company.absmartly.io/v1',
82
+ api_key: 'YOUR-API-KEY',
83
+ application: 'website',
84
+ environment: 'development')
85
+
86
+ sdk_config = ABSmartlyConfig.create
87
+ sdk_config.client = Client.create(client_config)
88
+
89
+ sdk = Absmartly.create(sdk_config)
90
+ ```
91
+
92
+ **Refreshing the Context with Fresh Experiment Data**
93
+
94
+ For long-running contexts, the context is usually created once when the
95
+ application is first started. However, any experiments being tracked in your
96
+ production code, but started after the context was created, will not be
97
+ triggered.
98
+
99
+ Alternatively, the `refresh` method can be called manually. The
100
+ `refresh` method pulls updated experiment data from the A/B
101
+ Smartly collector and will trigger recently started experiments when
102
+ `treatment` is called again.
103
+
104
+ **Setting Extra Units**
105
+
106
+ You can add additional units to a context by calling the `set_unit()` or
107
+ `set_units()` methods. These methods may be used, for example, when a user
108
+ logs in to your application and you want to use the new unit type in the
109
+ context.
110
+
111
+ Please note, you cannot override an already set unit type as that would be
112
+ a change of identity and would throw an exception. In this case, you must
113
+ create a new context instead. The `set_unit()` and
114
+ `set_units()` methods can be called before the context is ready.
115
+
116
+ ```ruby
117
+ context_config.set_unit('session_id', 'bf06d8cb5d8137290c4abb64155584fbdb64d8')
118
+ context_config.set_unit('user_id', '123456')
119
+ context = Absmartly.create_context(context_config)
120
+ ```
121
+ or
122
+ ```ruby
123
+ context_config.set_units(
124
+ session_id: 'bf06d8cb5d8137290c4abb64155584fbdb64d8',
125
+ user_id: '123456'
126
+ )
127
+ context = Absmartly.create_context(context_config)
128
+ ```
129
+
130
+ ## Basic Usage
131
+
132
+ ### Selecting A Treatment
133
+
134
+ ```ruby
135
+ treatment = context.treatment('exp_test_experiment')
136
+
137
+ if treatment.zero?
138
+ # user is in control group (variant 0)
139
+ else
140
+ # user is in treatment group
141
+ end
142
+ ```
143
+
144
+ ### Treatment Variables
145
+
146
+ ```ruby
147
+ default_button_color_value = 'red'
148
+
149
+ context.variable_value('experiment_name', default_button_color_value)
150
+ ```
151
+
152
+ ### Peek at Treatment Variants
153
+
154
+ Although generally not recommended, it is sometimes necessary to peek at
155
+ a treatment or variable without triggering an exposure. The A/B Smartly
156
+ SDK provides a `peek_treatment()` method for that.
157
+
158
+ ```ruby
159
+ treatment = context.peek_treatment('exp_test_experiment')
160
+ ```
161
+
162
+ #### Peeking at variables
163
+
164
+ ```ruby
165
+ treatment = context.peek_variable_value('exp_test_experiment')
166
+ ```
167
+
168
+ ### Overriding Treatment Variants
169
+
170
+ During development, for example, it is useful to force a treatment for an
171
+ experiment. This can be achieved with the `set_override()` and/or `set_overrides()`
172
+ methods. These methods can be called before the context is ready.
173
+
174
+ ```ruby
175
+ context.set_override("exp_test_experiment", 1) # force variant 1 of treatment
176
+
177
+ context.set_overrides(
178
+ 'exp_test_experiment' => 1,
179
+ 'exp_another_experiment' => 0,
180
+ )
181
+ ```
182
+
183
+ ## Advanced
184
+
185
+ ### Context Attributes
186
+
187
+ Attributes are used to pass meta-data about the user and/or the request.
188
+ They can be used later in the Web Console to create segments or audiences.
189
+ They can be set using the `set_attribute()` or `set_attributes()`
190
+ methods, before or after the context is ready.
191
+
192
+ ```ruby
193
+ context.set_attribute('session_id', session_id)
194
+ context.set_attributes(
195
+ 'customer_age' => 'new_customer'
196
+ )
197
+ ```
198
+
199
+ ### Custom Assignments
200
+
201
+ Sometimes it may be necessary to override the automatic selection of a
202
+ variant. For example, if you wish to have your variant chosen based on
203
+ data from an API call. This can be accomplished using the
204
+ `set_custom_assignment()` method.
205
+
206
+ ```ruby
207
+ chosen_variant = 1
208
+ context.set_custom_assignment('experiment_name', chosen_variant)
209
+ ```
210
+
211
+ If you are running multiple experiments and need to choose different
212
+ custom assignments for each one, you can do so using the
213
+ `set_custom_assignments()` method.
214
+
215
+ ```ruby
216
+ assignments = [
217
+ 'experiment_name' => 1,
218
+ 'another_experiment_name' => 0,
219
+ 'a_third_experiment_name' => 2
220
+ ]
221
+
222
+ context.set_custom_assignments(assignments)
223
+ ```
224
+
225
+ ### Publish
226
+
227
+ Sometimes it is necessary to ensure all events have been published to the
228
+ A/B Smartly collector, before proceeding. You can explicitly call the
229
+ `publish()` methods.
230
+
231
+ ```
232
+ context.publish
233
+ ```
234
+
235
+ ### Finalize
236
+
237
+ The `close()` method will ensure all events have been
238
+ published to the A/B Smartly collector, like `publish()`, and will also
239
+ "seal" the context, throwing an error if any method that could generate
240
+ an event is called.
241
+
242
+ ```
243
+ context.close
244
+ ```
245
+
246
+ ### Tracking Goals
247
+
248
+ ```ruby
249
+ context.track(
250
+ 'payment',
251
+ { item_count: 1, total_amount: 1999.99 }
252
+ )
253
+ ```
data/absmartly.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # $:.push File.expand_path("../lib", __FILE__)
4
+ require File.expand_path("lib/absmartly/version", __dir__)
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "absmartly-sdk"
7
+ spec.version = Absmartly::VERSION
8
+ spec.authors = ["absmartly"]
9
+ spec.email = ["sdks@absmartly.com"]
10
+
11
+ spec.summary = "Absmartly gem"
12
+ spec.description = "Absmartly gem"
13
+
14
+ spec.homepage = "https://github.com/absmartly/ruby-sdk"
15
+
16
+ spec.license = "MIT"
17
+ spec.required_ruby_version = ">= 2.7.0"
18
+ spec.extra_rdoc_files = ["README.md"]
19
+
20
+ spec.metadata["homepage_uri"] = spec.homepage
21
+ spec.metadata["source_code_uri"] = "https://github.com/absmartly/ruby-sdk"
22
+ spec.metadata["changelog_uri"] = "https://github.com/absmartly/ruby-sdk"
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
+ spec.files = Dir.chdir(__dir__) do
27
+ `git ls-files -z`.split("\x0").reject do |f|
28
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
29
+ end
30
+ end
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+
35
+ # Uncomment to register a new dependency of your gem
36
+ # spec.add_dependency "example-gem", "~> 1.0"
37
+
38
+ # For more information and examples about making a new gem, check out our
39
+ # guide at: https://bundler.io/guides/creating_gem.html
40
+ end
data/example/example.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../lib/absmartly"
2
4
 
3
5
  # config file
@@ -25,7 +27,7 @@ treatment3 = ctx.treatment("test")
25
27
  puts(treatment3) # 1
26
28
 
27
29
  ctx.set_unit("db_user_id", 1000013)
28
- ctx.set_units(db_user_id2: 1000013, session_id: 12311)
30
+ ctx.set_units(db_user_id2: 1000013, session_id2: 12311)
29
31
 
30
32
  ctx.set_attribute("user_agent", "Chrome 2022")
31
33
  ctx.set_attributes(
data/lib/a_b_smartly.rb CHANGED
@@ -58,7 +58,7 @@ class ABSmartly
58
58
 
59
59
  def create_context(config)
60
60
  validate_params(config)
61
- Context.create(get_utc_format, config, @scheduler, @context_data_provider.context_data,
61
+ Context.create(get_utc_format, config, @context_data_provider.context_data,
62
62
  @context_data_provider, @context_event_handler, @context_event_logger, @variable_parser,
63
63
  AudienceMatcher.new(@audience_deserializer))
64
64
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Absmartly
4
- VERSION = "0.1.2"
4
+ VERSION = "1.0.5"
5
5
  end
data/lib/context.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "hashing"
4
4
  require_relative "variant_assigner"
5
+ require_relative "context_event_logger"
5
6
  require_relative "json/unit"
6
7
  require_relative "json/attribute"
7
8
  require_relative "json/exposure"
@@ -11,13 +12,13 @@ require_relative "json/goal_achievement"
11
12
  class Context
12
13
  attr_reader :data, :pending_count
13
14
 
14
- def self.create(clock, config, scheduler, data_future, data_provider,
15
+ def self.create(clock, config, data_future, data_provider,
15
16
  event_handler, event_logger, variable_parser, audience_matcher)
16
- Context.new(clock, config, scheduler, data_future, data_provider,
17
+ Context.new(clock, config, data_future, data_provider,
17
18
  event_handler, event_logger, variable_parser, audience_matcher)
18
19
  end
19
20
 
20
- def initialize(clock, config, scheduler, data_future, data_provider,
21
+ def initialize(clock, config, data_future, data_provider,
21
22
  event_handler, event_logger, variable_parser, audience_matcher)
22
23
  @index = []
23
24
  @achievements = []
@@ -31,7 +32,6 @@ class Context
31
32
  @data_provider = data_provider
32
33
  @variable_parser = variable_parser
33
34
  @audience_matcher = audience_matcher
34
- @scheduler = scheduler
35
35
  @closed = false
36
36
 
37
37
  @units = {}
@@ -49,8 +49,10 @@ class Context
49
49
  set_custom_assignments(config.custom_assignments) if config.custom_assignments
50
50
  if data_future.success?
51
51
  assign_data(data_future.data_future)
52
+ log_event(ContextEventLogger::EVENT_TYPE::READY, data_future.data_future)
52
53
  else
53
54
  set_data_failed(data_future.exception)
55
+ log_error(data_future.exception)
54
56
  end
55
57
  end
56
58
 
@@ -157,11 +159,11 @@ class Context
157
159
  assignment.exposed = true
158
160
 
159
161
  exposure = Exposure.new
160
- exposure.id = assignment.id
162
+ exposure.id = assignment.id || 0
161
163
  exposure.name = assignment.name
162
164
  exposure.unit = assignment.unit_type
163
165
  exposure.variant = assignment.variant
164
- exposure.exposed_at = @clock
166
+ exposure.exposed_at = @clock.to_i
165
167
  exposure.assigned = assignment.assigned
166
168
  exposure.eligible = assignment.eligible
167
169
  exposure.overridden = assignment.overridden
@@ -171,6 +173,7 @@ class Context
171
173
 
172
174
  @pending_count += 1
173
175
  @exposures.push(exposure)
176
+ log_event(ContextEventLogger::EVENT_TYPE::EXPOSURE, exposure)
174
177
  end
175
178
  end
176
179
 
@@ -221,6 +224,7 @@ class Context
221
224
 
222
225
  @pending_count += 1
223
226
  @achievements.push(achievement)
227
+ log_event(ContextEventLogger::EVENT_TYPE::GOAL, achievement)
224
228
  end
225
229
 
226
230
  def publish
@@ -236,8 +240,10 @@ class Context
236
240
  data_future = @data_provider.context_data
237
241
  if data_future.success?
238
242
  assign_data(data_future.data_future)
243
+ log_event(ContextEventLogger::EVENT_TYPE::REFRESH, data_future.data_future)
239
244
  else
240
245
  set_data_failed(data_future.exception)
246
+ log_error(data_future.exception)
241
247
  end
242
248
  end
243
249
  end
@@ -248,6 +254,7 @@ class Context
248
254
  flush
249
255
  end
250
256
  @closed = true
257
+ log_event(ContextEventLogger::EVENT_TYPE::CLOSE, nil)
251
258
  end
252
259
  end
253
260
 
@@ -282,18 +289,20 @@ class Context
282
289
  event.hashed = true
283
290
  event.published_at = @clock.to_i
284
291
  event.units = @units.map do |key, value|
285
- Unit.new(key, unit_hash(key, value))
292
+ Unit.new(key.to_s, unit_hash(key, value))
286
293
  end
287
- event.attributes = @attributes.empty? ? nil : @attributes
288
294
  event.exposures = exposures
289
- event.goals = achievements
290
- return @event_handler.publish(self, event)
295
+ event.attributes = @attributes unless @attributes.empty?
296
+ event.goals = achievements unless achievements.nil?
297
+ log_event(ContextEventLogger::EVENT_TYPE::PUBLISH, event)
298
+ @event_handler.publish(self, event)
291
299
  end
292
300
  end
293
301
  else
294
302
  @exposures = []
295
303
  @achievements = []
296
304
  @pending_count = 0
305
+ @data_failed
297
306
  end
298
307
  end
299
308
 
@@ -365,7 +374,7 @@ class Context
365
374
  hash
366
375
  end
367
376
  match = @audience_matcher.evaluate(experiment.data.audience, attrs)
368
- if match.nil? || !match.result
377
+ if match && !match.result
369
378
  assignment.audience_mismatch = true
370
379
  end
371
380
  end
@@ -471,6 +480,18 @@ class Context
471
480
  @failed = true
472
481
  end
473
482
 
483
+ def log_event(event, data)
484
+ unless @event_logger.nil?
485
+ @event_logger.handle_event(event, data)
486
+ end
487
+ end
488
+
489
+ def log_error(error)
490
+ unless @event_logger.nil?
491
+ @event_logger.handle_event(ContextEventLogger::EVENT_TYPE::ERROR, error.message)
492
+ end
493
+ end
494
+
474
495
  attr_accessor :clock,
475
496
  :publish_delay,
476
497
  :event_handler,
@@ -478,7 +499,6 @@ class Context
478
499
  :data_provider,
479
500
  :variable_parser,
480
501
  :audience_matcher,
481
- :scheduler,
482
502
  :units,
483
503
  :failed,
484
504
  :data_lock,
@@ -67,4 +67,12 @@ class ContextConfig
67
67
  def custom_assignment(experiment_name)
68
68
  @custom_assignments[experiment_name.to_sym]
69
69
  end
70
+
71
+
72
+ def set_event_logger(event_logger)
73
+ @event_logger = event_logger
74
+ self
75
+ end
76
+
77
+ attr_reader :event_logger
70
78
  end
@@ -1,9 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ContextEventLogger
4
- EVENT_TYPE = %w[error ready refresh publish exposure goal close]
5
- # @interface method
6
- def handle_event
7
- raise NotImplementedError.new("You must implement handleEvent method.")
4
+ module EVENT_TYPE
5
+ ERROR = "error"
6
+ READY = "ready"
7
+ REFRESH = "refresh"
8
+ PUBLISH = "publish"
9
+ EXPOSURE = "exposure"
10
+ GOAL = "goal"
11
+ CLOSE = "close"
12
+ end
13
+
14
+ def handle_event(event, data)
15
+ raise NotImplementedError.new("You must implement handle_event method.")
8
16
  end
9
17
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ContextEventLoggerCallback < ContextEventLogger
4
+ attr_accessor :callable
5
+
6
+ def initialize(callable)
7
+ @callable = callable
8
+ end
9
+
10
+ def handle_event(event, data)
11
+ @callable.call(event, data) if @callable.present?
12
+ end
13
+ end
data/lib/json/exposure.rb CHANGED
@@ -8,7 +8,7 @@ class Exposure
8
8
  exposed_at = nil, assigned = nil, eligible = nil,
9
9
  overridden = nil, full_on = nil, custom = nil,
10
10
  audience_mismatch = nil)
11
- @id = id
11
+ @id = id || 0
12
12
  @name = name
13
13
  @unit = unit
14
14
  @variant = variant
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: absmartly-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - absmartly
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-04 00:00:00.000000000 Z
11
+ date: 2023-04-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Absmartly gem
14
14
  email:
@@ -16,7 +16,7 @@ email:
16
16
  executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files:
19
- - README
19
+ - README.md
20
20
  files:
21
21
  - ".rspec"
22
22
  - ".rubocop.yml"
@@ -26,8 +26,9 @@ files:
26
26
  - Gemfile
27
27
  - Gemfile.lock
28
28
  - LICENSE.txt
29
- - README
29
+ - README.md
30
30
  - Rakefile
31
+ - absmartly.gemspec
31
32
  - example/example.rb
32
33
  - lib/a_b_smartly.rb
33
34
  - lib/a_b_smartly_config.rb
@@ -45,6 +46,7 @@ files:
45
46
  - lib/context_data_provider.rb
46
47
  - lib/context_event_handler.rb
47
48
  - lib/context_event_logger.rb
49
+ - lib/context_event_logger_callback.rb
48
50
  - lib/context_event_serializer.rb
49
51
  - lib/default_audience_deserializer.rb
50
52
  - lib/default_context_data_deserializer.rb
@@ -113,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
115
  - !ruby/object:Gem::Version
114
116
  version: '0'
115
117
  requirements: []
116
- rubygems_version: 3.1.6
118
+ rubygems_version: 3.4.10
117
119
  signing_key:
118
120
  specification_version: 4
119
121
  summary: Absmartly gem
data/README DELETED
@@ -1,180 +0,0 @@
1
- # A/B Smartly SDK
2
-
3
- A/B Smartly Ruby SDK
4
-
5
- ## Compatibility
6
-
7
- The A/B Smartly Ruby SDK is compatible with Ruby versions 2.7 and later. For the best performance and code readability, Ruby 3 or later is recommended. This SDK is being constantly tested with the nightly builds of Ruby, to ensure it is compatible with the latest Ruby version.
8
-
9
- ## Getting Started
10
-
11
- ### Install the SDK
12
-
13
- Install the gem and add to the application's Gemfile by executing:
14
-
15
- $ bundle add absmartly
16
-
17
- If bundler is not being used to manage dependencies, install the gem by executing:
18
-
19
- $ gem install absmartly
20
-
21
- ## Basic Usage
22
-
23
- Once the SDK is installed, it can be initialized in your project.
24
-
25
- You can create an SDK instance using the API key, application name, environment, and the endpoint URL obtained from A/B Smartly.
26
-
27
- ```Ruby
28
- require 'absmartly'
29
-
30
- Absmartly.configure_client do |config|
31
- config.endpoint = "https://your-company.absmartly.io/v1"
32
- config.api_key = "YOUR-API-KEY"
33
- config.application = "website"
34
- config.environment = "development"
35
- end
36
- ```
37
- #### Creating a new Context with raw promises
38
-
39
- ```Ruby
40
- # define a new context request
41
- context_config = Absmartly.create_context_config
42
- context_config.set_unit("session_id", "bf06d8cb5d8137290c4abb64155584fbdb64d8")
43
- context_config.set_unit("user_id", "123456")
44
-
45
- context = Absmartly.create_context(context_config)
46
- ```
47
-
48
- ### Selecting A Treatment
49
-
50
- ```Ruby
51
- treatment = context.treatment('exp_test_experiment')
52
-
53
- if treatment.zero?
54
- # user is in control group (variant 0)
55
- else
56
- # user is in treatment group
57
- end
58
- ```
59
-
60
- ### Treatment Variables
61
-
62
- ```Ruby
63
- default_button_color_value = 'red'
64
- button_color = context.variable_value('button.color')
65
- ```
66
-
67
- ### Peek at Treatment Variants
68
-
69
- Although generally not recommended, it is sometimes necessary to peek at a treatment or variable without triggering an exposure. The A/B Smartly SDK provides a `Context.peek_treatment()` method for that.
70
-
71
- ```Ruby
72
- treatment = context.peek_treatment('exp_test_experiment')
73
-
74
- if treatment.zero?
75
- # user is in control group (variant 0)
76
- else
77
- # user is in treatment group
78
- end
79
- ```
80
-
81
- #### Peeking at variables
82
-
83
- ```Ruby
84
- button_color = context.peek_variable_value('button.color', 'red')
85
- ```
86
-
87
- ### Overriding Treatment Variants
88
-
89
- During development, for example, it is useful to force a treatment for an
90
- experiment. This can be achieved with the `Context.set_override()` and/or `Context.set_overrides()` methods. These methods can be called before the context is ready.
91
-
92
- ```Ruby
93
- context.set_override("exp_test_experiment", 1) # force variant 1 of treatment
94
-
95
- context.set_overrides(
96
- 'exp_test_experiment' => 1,
97
- 'exp_another_experiment' => 0,
98
- )
99
- ```
100
-
101
- ## Advanced
102
-
103
- ### Context Attributes
104
-
105
- Attributes are used to pass meta-data about the user and/or the request.
106
- They can be used later in the Web Console to create segments or audiences.
107
- They can be set using the `context.set_attribute()` or `context.set_attributes()` methods, before or after the context is ready.
108
-
109
- ```Ruby
110
- context.set_attribute('session_id', session_id)
111
- context.set_attributes(
112
- 'customer_age' => 'new_customer'
113
- )
114
- ```
115
-
116
- ### Custom Assignments
117
-
118
- Sometimes it may be necessary to override the automatic selection of a variant. For example, if you wish to have your variant chosen based on data from an API call. This can be accomplished using the `Context.set_custom_assignment()` method.
119
-
120
- ```Ruby
121
- chosen_variant = 1
122
- context.set_custom_assignment("experiment_name", chosen_variant)
123
- ```
124
-
125
- If you are running multiple experiments and need to choose different custom assignments for each one, you can do so using the `Context->setCustomAssignments()` method.
126
-
127
- ```Ruby
128
- assignments = [
129
- "experiment_name" => 1,
130
- "another_experiment_name" => 0,
131
- "a_third_experiment_name" => 2
132
- ]
133
-
134
- context.set_custom_assignments(assignments)
135
- ```
136
-
137
- ### Publish
138
-
139
- Sometimes it is necessary to ensure all events have been published to the A/B Smartly collector, before proceeding. You can explicitly call the `context.publish()` method.
140
-
141
- ```Ruby
142
- context.publish
143
- ```
144
-
145
- ### Finalize
146
-
147
- The `close()` method will ensure all events have been published to the A/B Smartly collector, like `context.publish()`, and will also "seal" the context, throwing an error if any method that could generate an event is called.
148
-
149
- ```Ruby
150
- context.close
151
- ```
152
-
153
- ### Tracking Goals
154
-
155
- ```Ruby
156
- context.track(
157
- 'payment',
158
- { item_count: 1, total_amount: 1999.99 }
159
- )
160
- ```
161
-
162
-
163
-
164
- ## Development
165
-
166
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
167
-
168
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
169
-
170
- ## Contributing
171
-
172
- Bug reports and pull requests are welcome on GitHub at https://github.com/omairazam/absmartly. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/omairazam/absmartly/blob/master/CODE_OF_CONDUCT.md).
173
-
174
- ## License
175
-
176
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
177
-
178
- ## Code of Conduct
179
-
180
- Everyone interacting in the Absmartly project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/omairazam/absmartly/blob/master/CODE_OF_CONDUCT.md).