Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d2c1da5
[FSSDK-9555] GitHub Issue Templates (#337)
mikechu-optimizely Aug 8, 2023
85512a2
[FSSDK-9509] Update http_project_config_manager.rb with soft log warn…
Mat001 Sep 25, 2023
9b77a5b
feat: include object id/key in invalid object errors (#301)
stoneman Oct 10, 2023
a269a52
updated to ruby version (#341)
Mat001 Nov 9, 2023
9487c0a
remove config manager stop restriction (#340)
andrewleap-optimizely Nov 14, 2023
ca43f1e
[FSSDK-9382] switch client init args from positional to keyword (#342)
andrewleap-optimizely Dec 8, 2023
1333d60
[FSSDK-9781] warn on duplicate experiment key (#343)
andrewleap-optimizely Dec 8, 2023
32d0d99
[FSSDK-9951] add multi thread warning (#345)
andrewleap-optimizely Jan 17, 2024
7a5261d
[FSSDK-8582] chore: prepare for 5.0 release (#346)
andrewleap-optimizely Jan 18, 2024
2a284da
[FSSDK-9990] add missing info to gemspec (#348)
andrewleap-optimizely Feb 2, 2024
a8c3c7b
update version and changelog (#349)
Mat001 Feb 8, 2024
4142ae6
[FSSDK-9461] Bump Ruby version to 3.3 (#351)
Mat001 Jun 10, 2024
db57cd0
FSSDK-10665] fix: Github Actions YAML files vulnerable to script inje…
FarhanAnjum-opti Sep 25, 2024
321947e
Update ruby.yml (#355)
muzahidul-opti Dec 13, 2024
39e8e7e
Revert "Update ruby.yml (#355)" (#357)
muzahidul-opti Dec 13, 2024
69b2453
[FSSDK-10765] enhancement: Implement UPS request batching for decideF…
FarhanAnjum-opti Jan 9, 2025
cfdd022
[FSSDK-10847] chore: preparing for release 5.1.0 (#360)
FarhanAnjum-opti Jan 13, 2025
61a95c3
[FSSDK-11389] update: experiment_id and variation_id added to payload…
FarhanAnjum-opti May 16, 2025
7658884
[FSSDK-11140] Ruby: Update project config to track CMAB properties (#…
esrakartalOpt Jun 13, 2025
95f9e35
[FSSDK-11149] Ruby: Implement CMAB Client (#364)
esrakartalOpt Jun 13, 2025
b210c55
[FSSDK-11158] update: add remove method in LRU Cache for CMAB service…
FarhanAnjum-opti Jul 17, 2025
da64665
[FSSDK-11167] Implement CMAB service (#367)
FarhanAnjum-opti Jul 17, 2025
adbd74e
[FSSDK-11459] Ruby - Add SDK Multi-Region Support for Data Hosting (#…
esrakartalOpt Jul 28, 2025
1135958
[FSSDK-11176] Update: Implement Decision Service methods to handle CM…
FarhanAnjum-opti Jul 29, 2025
a3e6b06
[FSSDK-11723] fix: rubocop failing on ruby 3.0.0 (#371)
FarhanAnjum-opti Jul 29, 2025
f4967e4
[FSSDK-11185] Update: Send CMAB uuid in impression events (#370)
FarhanAnjum-opti Aug 6, 2025
1a8881f
[FSSDK-11575][FSSDK-11576] Ruby: Parsing holdout to datafile and upda…
esrakartalOpt Sep 29, 2025
d789392
[FSSDK-11577] Ruby: Add holdout support and refactor decision logic i…
esrakartalOpt Oct 14, 2025
7f7f988
[FSSDK-11902] Fix concurrency bug in cmab service (#375)
FarhanAnjum-opti Oct 16, 2025
0abc6f0
[FSSDK-11578] Ruby: Update impression event handling and send notific…
esrakartalOpt Oct 22, 2025
f6b7ad1
update: bugbash fixes. (#377)
FarhanAnjum-opti Oct 23, 2025
7e2ccf2
expose cmab prediction endpoint in url template (#378)
Mat001 Nov 7, 2025
9fd228c
[FSSDK-11959] chore: preparing for release v5.2.0 (#379)
FarhanAnjum-opti Nov 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "Ruby SDK",

"image": "mcr.microsoft.com/devcontainers/ruby:1-3.3-bullseye",

"postCreateCommand": "set -e && bundle install && gem install optimizely-sdk && rake build && gem install pkg/* && gem install solargraph",

"customizations": {
"vscode": {
"extensions": [
"eamodio.gitlens",
"github.vscode-github-actions",
"castwide.solargraph"
]
}
}
}
94 changes: 94 additions & 0 deletions .github/ISSUE_TEMPLATE/BUG-REPORT.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: 🐞 Bug
description: File a bug/issue
title: "[BUG] <title>"
labels: ["bug", "needs-triage"]
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
label: SDK Version
description: Version of the SDK in use?
validations:
required: true
- type: textarea
attributes:
label: Current Behavior
description: A concise description of what you're experiencing.
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1. In this environment...
1. With this config...
1. Run '...'
1. See error...
validations:
required: true
- type: textarea
attributes:
label: Ruby Version
description: What version of Ruby are you using?
validations:
required: false
- type: textarea
attributes:
label: Rails
description: If you're using Rail, what version?
validations:
required: false
- type: textarea
attributes:
label: Link
description: Link to code demonstrating the problem.
validations:
required: false
- type: textarea
attributes:
label: Logs
description: Logs/stack traces related to the problem (⚠️do not include sensitive information).
validations:
required: false
- type: dropdown
attributes:
label: Severity
description: What is the severity of the problem?
multiple: true
options:
- Blocking development
- Affecting users
- Minor issue
validations:
required: false
- type: textarea
attributes:
label: Workaround/Solution
description: Do you have any workaround or solution in mind for the problem?
validations:
required: false
- type: textarea
attributes:
label: Recent Change
description: Has this issue started happening after an update or experiment change?
validations:
required: false
- type: textarea
attributes:
label: Conflicts
description: Are there other libraries/dependencies potentially in conflict?
validations:
required: false
45 changes: 45 additions & 0 deletions .github/ISSUE_TEMPLATE/ENHANCEMENT.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: ✨Enhancement
description: Create a new ticket for a Enhancement/Tech-initiative for the benefit of the SDK which would be considered for a minor version update.
title: "[ENHANCEMENT] <title>"
labels: ["enhancement"]
body:
- type: textarea
id: description
attributes:
label: Description
description: Briefly describe the enhancement in a few sentences.
placeholder: Short description...
validations:
required: true
- type: textarea
id: benefits
attributes:
label: Benefits
description: How would the enhancement benefit to your product or usage?
placeholder: Benefits...
validations:
required: true
- type: textarea
id: detail
attributes:
label: Detail
description: How would you like the enhancement to work? Please provide as much detail as possible
placeholder: Detailed description...
validations:
required: false
- type: textarea
id: examples
attributes:
label: Examples
description: Are there any examples of this enhancement in other products/services? If so, please provide links or references.
placeholder: Links/References...
validations:
required: false
- type: textarea
id: risks
attributes:
label: Risks/Downsides
description: Do you think this enhancement could have any potential downsides or risks?
placeholder: Risks/Downsides...
validations:
required: false
4 changes: 4 additions & 0 deletions .github/ISSUE_TEMPLATE/FEATURE-REQUEST.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!--
Thanks for filing in issue! Are you requesting a new feature? If so, please share your feedback with us on the following link.
-->
## Feedback requesting a new feature can be shared [here.](https://feedback.optimizely.com/)
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: 💡Feature Requests
url: https://feedback.optimizely.com/
about: Feedback requesting a new feature can be shared here.
12 changes: 8 additions & 4 deletions .github/workflows/integration_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@ jobs:
path: 'home/runner/travisci-tools'
ref: 'master'
- name: set SDK Branch if PR
env:
HEAD_REF: ${{ github.head_ref }}
if: ${{ github.event_name == 'pull_request' }}
run: |
echo "SDK_BRANCH=${{ github.head_ref }}" >> $GITHUB_ENV
echo "TRAVIS_BRANCH=${{ github.head_ref }}" >> $GITHUB_ENV
echo "SDK_BRANCH=$HEAD_REF" >> $GITHUB_ENV
echo "TRAVIS_BRANCH=$HEAD_REF" >> $GITHUB_ENV
- name: set SDK Branch if not pull request
env:
REF_NAME: ${{ github.ref_name }}
if: ${{ github.event_name != 'pull_request' }}
run: |
echo "SDK_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
echo "TRAVIS_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
echo "SDK_BRANCH=$REF_NAME" >> $GITHUB_ENV
echo "TRAVIS_BRANCH=$REF_NAME" >> $GITHUB_ENV
- name: Trigger build
env:
SDK: ruby
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,21 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: [ '2.7.0', '3.0.0', '3.1.0' ]
ruby: [ '3.0.0', '3.1.0', '3.2.0', '3.3.0' ]
steps:
- uses: actions/checkout@v3
- name: Set up Ruby ${{ matrix.ruby }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Install rubocop 1.78.0 for Ruby 3.0.0
if: matrix.ruby == '3.0.0'
run: |
echo "Installing rubocop 1.78.0 for Ruby 3.0.0"
bundle add rubocop --version 1.78.0 || true
bundle install
bundle exec rubocop -A Gemfile || true
- name: Run linting
run: |
bundle exec rubocop
Expand Down
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
inherit_from: .rubocop_todo.yml

AllCops:
TargetRubyVersion: 2.7
TargetRubyVersion: 3.0

Layout/SpaceInsideHashLiteralBraces:
EnforcedStyle: no_space
Expand Down
94 changes: 94 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,99 @@
# Optimizely Ruby SDK Changelog

## 5.2.0
November 13th, 2025

### New Features
- Added CMAB client implementation to support contextual multi-armed bandit decisioning. ([#364](https://github.com/optimizely/ruby-sdk/pull/364))
- Implemented CMAB service to manage contextual decision logic. ([#367](https://github.com/optimizely/ruby-sdk/pull/367))
- Added SDK multi-region support for data hosting. ([#365](https://github.com/optimizely/ruby-sdk/pull/365))

### Enhancements
- Added `experiment_id` and `variation_id` to event payloads. ([#361](https://github.com/optimizely/ruby-sdk/pull/361))
- Updated project config to track CMAB properties. ([#362](https://github.com/optimizely/ruby-sdk/pull/362))
- Added `remove` method in LRU Cache for CMAB service. ([#366](https://github.com/optimizely/ruby-sdk/pull/366))
- Implemented Decision Service methods to handle CMAB logic. ([#369](https://github.com/optimizely/ruby-sdk/pull/369))
- Updated impression events to include CMAB UUID. ([#370](https://github.com/optimizely/ruby-sdk/pull/370))
- Exposed CMAB prediction endpoint in URL template. ([#378](https://github.com/optimizely/ruby-sdk/pull/378))

### Bug Fixes
- Fixed Rubocop failures on Ruby 3.0.0. ([#371](https://github.com/optimizely/ruby-sdk/pull/371))
- Fixed concurrency issue in CMAB service. ([#375](https://github.com/optimizely/ruby-sdk/pull/375))
- Minor bugbash updates and stability improvements. ([#377](https://github.com/optimizely/ruby-sdk/pull/377))


## 5.1.0
January 10th, 2025

Added support for batch processing in DecideAll and DecideForKeys, enabling more efficient handling of multiple decisions in the User Profile Service.([#353](https://github.com/optimizely/ruby-sdk/pull/353))

## 5.0.1
February 8th, 2024

The 5.0.1 minor release introduces update of metadata in gemspec.

## 5.0.0
January 18th, 2024

### New Features

The 5.0.0 release introduces a new primary feature, [Advanced Audience Targeting]( https://docs.developers.optimizely.com/feature-experimentation/docs/optimizely-data-platform-advanced-audience-targeting) enabled through integration with [Optimizely Data Platform (ODP)](https://docs.developers.optimizely.com/optimizely-data-platform/docs)
([#303](https://github.com/optimizely/ruby-sdk/pull/303),
[#308](https://github.com/optimizely/ruby-sdk/pull/308),
[#310](https://github.com/optimizely/ruby-sdk/pull/310),
[#311](https://github.com/optimizely/ruby-sdk/pull/311),
[#312](https://github.com/optimizely/ruby-sdk/pull/312),
[#314](https://github.com/optimizely/ruby-sdk/pull/314),
[#316](https://github.com/optimizely/ruby-sdk/pull/316)).
You can use ODP, a high-performance [Customer Data Platform (CDP)]( https://www.optimizely.com/optimization-glossary/customer-data-platform/), to easily create complex real-time segments (RTS) using first-party and 50+ third-party data sources out of the box. You can create custom schemas that support the user attributes important for your business, and stitch together user behavior done on different devices to better understand and target your customers for personalized user experiences. ODP can be used as a single source of truth for these segments in any Optimizely or 3rd party tool.

With ODP accounts integrated into Optimizely projects, you can build audiences using segments pre-defined in ODP. The SDK will fetch the segments for given users and make decisions using the segments. For access to ODP audience targeting in your Feature Experimentation account, please contact your Optimizely Customer Success Manager.

This version includes the following changes:

* New API added to `OptimizelyUserContext`:

* `fetch_qualified_segments()`: this API will retrieve user segments from the ODP server. The fetched segments will be used for audience evaluation. The fetched data will be stored in the local cache to avoid repeated network delays.

* When an `OptimizelyUserContext` is created, the SDK will automatically send an identify request to the ODP server to facilitate observing user activities.

* New APIs added to `Optimizely::Project`:

* `send_odp_event()`: customers can build/send arbitrary ODP events that will bind user identifiers and data to user profiles in ODP.

For details, refer to our documentation pages:

* [Advanced Audience Targeting](https://docs.developers.optimizely.com/feature-experimentation/docs/optimizely-data-platform-advanced-audience-targeting)

* [Server SDK Support](https://docs.developers.optimizely.com/feature-experimentation/v1.0/docs/advanced-audience-targeting-for-server-side-sdks)

* [Initialize Ruby SDK](https://docs.developers.optimizely.com/feature-experimentation/docs/initialize-sdk-ruby)

* [OptimizelyUserContext Ruby SDK](https://docs.developers.optimizely.com/feature-experimentation/docs/optimizelyusercontext-ruby)

* [Advanced Audience Targeting segment qualification methods](https://docs.developers.optimizely.com/feature-experimentation/docs/advanced-audience-targeting-segment-qualification-methods-ruby)

* [Send Optimizely Data Platform data using Advanced Audience Targeting](https://docs.developers.optimizely.com/feature-experimentation/docs/send-odp-data-using-advanced-audience-targeting-ruby)

### Logging

* Add warning to polling intervals below 30 seconds ([#338](https://github.com/optimizely/ruby-sdk/pull/338))
* Add warning to duplicate experiment keys ([#343](https://github.com/optimizely/ruby-sdk/pull/343))

### Enhancements
* Removed polling config manager stop restriction, allowing it to be restarted ([#340](https://github.com/optimizely/ruby-sdk/pull/340)).
* Include object id/key in invalid object errors ([#301](https://github.com/optimizely/ruby-sdk/pull/301)).

### Breaking Changes

* Updated required Ruby version from 2.7 -> 3.0
* `Optimizely::Project` initialization arguments have been changed from positional to keyword ([#342](https://github.com/optimizely/ruby-sdk/pull/342)).
* `ODPManager` in the SDK is enabled by default. Unless an ODP account is integrated into the Optimizely projects, most `ODPManager` functions will be ignored. If needed, `ODPManager` can be disabled when `Optimizely::Project` is instantiated.

* `ProjectConfigManager` interface now requires a `sdk_key` method ([#323](https://github.com/optimizely/ruby-sdk/pull/323)).
* `HTTPProjectConfigManager` requires either the `sdk_key` parameter or a datafile containing an sdkKey ([#323](https://github.com/optimizely/ruby-sdk/pull/323)).
* `BatchEventProcessor` is now the default `EventProcessor` when `Optimizely::Project` is instantiated ([#325](https://github.com/optimizely/ruby-sdk/pull/325)).

## 5.0.0-beta
April 28th, 2023

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2016, Optimizely and contributors
© Optimizely 2016

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Refer to the [Ruby SDK's developer documentation](https://docs.developers.optimi

### Requirements

* Ruby 2.7+
* Ruby 3.0+

### Install the SDK

Expand All @@ -41,7 +41,7 @@ You can initialize the Optimizely instance in two ways: directly with a datafile
Initialize Optimizely with a datafile. This datafile will be used as ProjectConfig throughout the life of the Optimizely instance.

```ruby
optimizely_instance = Optimizely::Project.new(datafile)
optimizely_instance = Optimizely::Project.new(datafile: datafile)
```

#### Initialization by OptimizelyFactory
Expand Down Expand Up @@ -78,6 +78,8 @@ You can initialize the Optimizely instance in two ways: directly with a datafile
)
```

**Note:** The SDK spawns multiple threads when initialized. These threads have infinite loops that are used for fetching the datafile, as well as batching and dispatching events in the background. When using in a web server that spawn multiple child processes, you need to initialize the SDK after those child processes or workers have been spawned.

#### HTTP Config Manager

The `HTTPConfigManager` asynchronously polls for datafiles from a specified URL at regular intervals by making HTTP requests.
Expand Down
Loading