{"id":19935060,"url":"https://github.com/optimizely/ruby-sdk","last_synced_at":"2025-04-12T14:58:59.263Z","repository":{"id":39632957,"uuid":"64881624","full_name":"optimizely/ruby-sdk","owner":"optimizely","description":"Ruby SDK for Optimizely Feature Experimentation and Optimizely Full Stack (legacy).　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　🚨 Calling All Developers! 🚨　　　　　　　　　　　　　We invite you to provide your input on Feature Experimentation by completing this brief survey: https://qualtricsxm8wgr4vwty.qualtrics.com/jfe/form/SV_8AI3F5BovuSiulo","archived":false,"fork":false,"pushed_at":"2025-01-22T15:12:52.000Z","size":1456,"stargazers_count":25,"open_issues_count":1,"forks_count":28,"subscribers_count":100,"default_branch":"master","last_synced_at":"2025-04-12T14:58:50.926Z","etag":null,"topics":["optimizely-environment-prod","optimizely-environment-public","optimizely-owner-px"],"latest_commit_sha":null,"homepage":"https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/ruby-sdk","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/optimizely.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-08-03T21:47:04.000Z","updated_at":"2025-01-31T22:47:42.000Z","dependencies_parsed_at":"2023-12-08T17:27:37.704Z","dependency_job_id":"af120045-f7cd-4150-b2ea-576e4fdec87e","html_url":"https://github.com/optimizely/ruby-sdk","commit_stats":null,"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimizely%2Fruby-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimizely%2Fruby-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimizely%2Fruby-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimizely%2Fruby-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/optimizely","download_url":"https://codeload.github.com/optimizely/ruby-sdk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248586249,"owners_count":21128997,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["optimizely-environment-prod","optimizely-environment-public","optimizely-owner-px"],"created_at":"2024-11-12T23:18:39.590Z","updated_at":"2025-04-12T14:58:59.237Z","avatar_url":"https://github.com/optimizely.png","language":"Ruby","readme":"# Optimizely Ruby SDK\n\n[![Build Status](https://github.com/optimizely/ruby-sdk/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/optimizely/ruby-sdk/actions/workflows/ruby.yml?query=branch%3Amaster)\n[![Coverage Status](https://coveralls.io/repos/github/optimizely/ruby-sdk/badge.svg)](https://coveralls.io/github/optimizely/ruby-sdk)\n[![Apache 2.0](https://img.shields.io/github/license/nebula-plugins/gradle-extra-configurations-plugin.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n\n\nThis repository houses the Ruby SDK for use with Optimizely Feature Experimentation and Optimizely Full Stack (legacy).\n\nOptimizely Feature Experimentation is an A/B testing and feature management tool for product development teams that enables you to experiment at every step. Using Optimizely Feature Experimentation allows for every feature on your roadmap to be an opportunity to discover hidden insights. Learn more at [Optimizely.com](https://www.optimizely.com/products/experiment/feature-experimentation/), or see the [developer documentation](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/welcome).\n\nOptimizely Rollouts is [free feature flags](https://www.optimizely.com/free-feature-flagging/) for development teams. You can easily roll out and roll back features in any application without code deploys, mitigating risk for every feature on your roadmap.\n\n## Get Started\n\nRefer to the [Ruby SDK's developer documentation](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/ruby-sdk) for detailed instructions on getting started with using the SDK.\n\n### Requirements\n\n* Ruby 3.0+\n\n### Install the SDK\n\nThe SDK is available through [RubyGems](https://rubygems.org/gems/optimizely-sdk). To install:\n\n```\ngem install optimizely-sdk\n```\n\n### Feature Management Access\nTo access the Feature Management configuration in the Optimizely dashboard, please contact your Optimizely customer success manager.\n\n## Use the Ruby SDK\n\n### Initialization\n\nYou can initialize the Optimizely instance in two ways: directly with a datafile, or by using a factory class, `OptimizelyFactory`, which provides methods to create an Optimizely instance with the default configuration.\n\n#### Initialization with datafile\n\n Initialize Optimizely with a datafile. This datafile will be used as ProjectConfig throughout the life of the Optimizely instance.\n\n ```ruby\n optimizely_instance = Optimizely::Project.new(datafile: datafile)\n ```\n\n#### Initialization by OptimizelyFactory\n\n 1. Initialize Optimizely by providing an `sdk_key` and an optional `datafile`. This will initialize an HTTPConfigManager that makes an HTTP GET request to the URL (formed using your provided `sdk_key` and the default datafile CDN url template) to asynchronously download the project datafile at regular intervals and update ProjectConfig when a new datafile is received.\n\n    ```ruby\n    optimizely_instance = Optimizely::OptimizelyFactory.default_instance('put_your_sdk_key_here', datafile)\n    ```\n\n   When the `datafile` is given then it will be used initially before any update.\n\n 2. Initialize Optimizely by providing a Config Manager that implements a `config` method. You can customize our `HTTPConfigManager` as needed.\n\n    ```ruby\n    custom_config_manager = CustomConfigManager.new\n    optimizely_instance = Optimizely::OptimizelyFactory.default_instance_with_config_manager(custom_config_manager)\n    ```\n\n 3. Initialize Optimizely with required `sdk_key` and other optional arguments.\n\n      ```ruby\n       optimizely_instance = Optimizely::OptimizelyFactory.custom_instance(\n          sdk_key,\n          datafile,\n          event_dispatcher,\n          logger,\n          error_handler,\n          skip_json_validation,\n          user_profile_service,\n          config_manager,\n          notification_center,\n          event_processor\n      )\n      ```\n\n**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.\n\n#### HTTP Config Manager\n\nThe `HTTPConfigManager` asynchronously polls for datafiles from a specified URL at regular intervals by making HTTP requests.\n\n\n```ruby\n http_project_config_manager = Optimizely::HTTPProjectConfigManager.new(\n        sdk_key: nil,\n        url: nil,\n        datafile: nil,\n        url_template: nil,\n        auto_update: nil,\n        polling_interval: nil,\n        start_by_default: nil,\n        blocking_timeout: nil,\n        logger: nil,\n        error_handler: nil,\n        skip_json_validation: false,\n        notification_center: notification_center,\n        datafile_access_token: nil,\n        proxy_config: nil\n      )\n```\n**Note:** You must provide either the `sdk_key` or URL. If you provide both, the URL takes precedence.\n\n**sdk_key**\nThe `sdk_key` is used to compose the outbound HTTP request to the default datafile location on the Optimizely CDN.\n\n**datafile**\nYou can provide an initial datafile to bootstrap the  `DataFileProjectConfig`  so that it can be used immediately. The initial datafile also serves as a fallback datafile if HTTP connection cannot be established. The initial datafile will be discarded after the first successful datafile poll.\n\n**polling_interval**\nThe polling interval is used to specify a fixed delay between consecutive HTTP requests for the datafile. Valid duration is greater than 0 and less than 2592000 seconds. Default is 5 minutes.\n\n**url_template**\nA string with placeholder `{sdk_key}` can be provided so that this template along with the provided `sdk_key` is used to form the target URL.\n\n**start_by_default**\nBoolean flag used to start the `AsyncScheduler` for datafile polling if set to `true`.\n\n**blocking_timeout**\nThe blocking timeout period is used to specify a maximum time to wait for initial bootstrapping. Valid blocking timeout period is between 1 and 2592000 seconds. Default is 15 seconds.\n\n**datafile_access_token**\nAn access token sent in an authorization header with the request to fetch private datafiles.\n\nYou may also provide your own logger, error handler, or notification center.\n\n\n#### Advanced configuration\nThe following properties can be set to override the default configurations for `HTTPConfigManager`.\n\n| **PropertyName** | **Default Value** | **Description**\n| -- | -- | --\n| update_interval | 5 minutes | Fixed delay between fetches for the datafile\n| sdk_key | nil | Optimizely project SDK key\n| url | nil | URL override location used to specify custom HTTP source for the Optimizely datafile\n| url_template | 'https://cdn.optimizely.com/datafiles/{sdk_key}.json' | Parameterized datafile URL by SDK key\n| datafile | nil | Initial datafile, typically sourced from a local cached source\n| auto_update | true | Boolean flag to specify if callback needs to execute infinitely or only once\n| start_by_default | true | Boolean flag to specify if datafile polling should start right away as soon as `HTTPConfigManager` initializes\n| blocking_timeout | 15 seconds | Maximum time in seconds to block the `config` call until config has been initialized\n\nA notification signal will be triggered whenever a _new_ datafile is fetched and Project Config is updated. To subscribe to these notifications, use the\n```ruby\nnotification_center.add_notification_listener(Optimizely::NotificationCenter::NOTIFICATION_TYPES[:OPTIMIZELY_CONFIG_UPDATE], @callback)\n```\n\n\n#### BatchEventProcessor\n\n[BatchEventProcessor](https://github.com/optimizely/ruby-sdk/blob/master/lib/optimizely/event/batch_event_processor.rb) is a batched implementation of the [EventProcessor](https://github.com/optimizely/ruby-sdk/blob/master/lib/optimizely/event/event_processor.rb)\n\n   * Events passed to the `BatchEventProcessor` are immediately added to a `Queue`.\n\n   * The `BatchEventProcessor` maintains a single consumer thread that pulls events off of the `Queue` and buffers them for either a configured batch size or for a maximum duration before the resulting `LogEvent` is sent to the `NotificationCenter`.\n\n#### Use BatchEventProcessor\n```ruby\nevent_processor = Optimizely::BatchEventProcessor.new(\n    event_queue: SizedQueue.new(10),\n    event_dispatcher: event_dispatcher,\n    batch_size: 10,\n    flush_interval: 30000,\n    logger: logger,\n    notification_center: notification_center\n)\n```\n\n#### Advanced configuration\nThe following properties can be used to customize the `BatchEventProcessor` configuration.\n\n| **Property Name** | **Default Value** | **Description**\n| -- | -- | --\n| `event_queue` | 1000 | `SizedQueue.new(100)` or `Queue.new`. Queues individual events to be batched and dispatched by the executor. Default value is 1000.\n| `event_dispatcher` | nil | Used to dispatch event payload to Optimizely. By default `EventDispatcher.new` will be set.\n| `batch_size` | 10 | The maximum number of events to batch before dispatching. Once this number is reached, all queued events are flushed and sent to Optimizely.\n| `flush_interval` | 30000 ms | Maximum time to wait before batching and dispatching events. In milliseconds.\n| `notification_center` | nil | Notification center instance to be used to trigger any notifications.\n\n\n#### Close Optimizely\nIf you enable event batching, make sure that you call the `close` method, `optimizely.close()`, prior to exiting. This ensures that queued events are flushed as soon as possible to avoid any data loss.\n\n**Note:** Because the Optimizely client maintains a buffer of queued events, we recommend that you call `close()` on the Optimizely instance before shutting down your application or whenever dereferencing the instance.\n\n| **Method** | **Description**\n| -- | --\n| `close()` | Stops all timers and flushes the event queue. This method will also stop any timers that are happening for the datafile manager.\n\nFor Further details see the Optimizely [Feature Experimentation documentation](https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/welcome)\nto learn how to set up your first Ruby project and use the SDK.\n\n## SDK Development\n\n### Building the SDK\n\nTo build a local copy of the gem which will be output to `/pkg`:\n\n```\nrake build\n```\n\n### Unit Tests\n\n#### Running all tests\nYou can run all unit tests with:\n\n```\nrake spec\n```\n\n### Contributing\n\nPlease see [CONTRIBUTING](CONTRIBUTING.md).\n\n### Credits\n\nThis software incorporates code from the following open source projects:\n\n**Httparty** [https://github.com/jnunemaker/httparty](https://github.com/jnunemaker/httparty)\nCopyright \u0026copy; 2008 John Nunemaker\nLicense (MIT): [https://github.com/jnunemaker/httparty/blob/master/MIT-LICENSE](https://github.com/jnunemaker/httparty/blob/master/MIT-LICENSE)\n\n**JSON Schema Validator** [https://github.com/ruby-json-schema/json-schema](https://github.com/ruby-json-schema/json-schema)\nCopyright \u0026copy; 2010-2011, Lookingglass Cyber Solutions\nLicense (MIT): [https://github.com/ruby-json-schema/json-schema/blob/master/LICENSE.md](https://github.com/ruby-json-schema/json-schema/blob/master/LICENSE.md)\n\n**Murmurhash3** [https://github.com/funny-falcon/murmurhash3-ruby](https://github.com/funny-falcon/murmurhash3-ruby)\nCopyright \u0026copy; 2012 Sokolov Yura 'funny-falcon'\nLicense (MIT): [https://github.com/funny-falcon/murmurhash3-ruby/blob/master/LICENSE](https://github.com/funny-falcon/murmurhash3-ruby/blob/master/LICENSE)\n\n### Additional Code\n\nThis software may be used with additional code that is separately downloaded by you.  _These components are subject to\ntheir own license terms, which you should review carefully_.\n\n**Bundler** [https://github.com/bundler/bundler](https://github.com/bundler/bundler)\nCopyright \u0026copy; 2008-2018 Andre Arko, Engine Yard, et al\nLicense (MIT): [https://github.com/bundler/bundler/blob/master/LICENSE.md](https://github.com/bundler/bundler/blob/master/LICENSE.md)\n\n**Coveralls** [https://github.com/lemurheavy/coveralls-ruby](https://github.com/lemurheavy/coveralls-ruby)\nCopyright \u0026copy; 2012 Wil Gieseler\nLicense (MIT): [https://github.com/lemurheavy/coveralls-ruby/blob/master/LICENSE](https://github.com/lemurheavy/coveralls-ruby/blob/master/LICENSE)\n\n**Rake** [https://github.com/ruby/rake](https://github.com/ruby/rake)\nCopyright \u0026copy; 2004-2017 Jim Weirich\nLicense (MIT): [https://github.com/ruby/rake/blob/master/MIT-LICENSE](https://github.com/ruby/rake/blob/master/MIT-LICENSE)\n\n**RSpec** [https://github.com/rspec/rspec](https://github.com/rspec/rspec)\nCopyright \u0026copy; 2009 Chad Humphries, David Chelimsky\nCopyright \u0026copy; 2006 David Chelimsky, The RSpec Development Team\nCopyright \u0026copy; 2005 Steven Baker\nLicense (MIT): [https://github.com/rspec/rspec/blob/master/LICENSE.md](https://github.com/rspec/rspec/blob/master/LICENSE.md)\n\n**RuboCop** [https://github.com/rubocop-hq/rubocop](https://github.com/rubocop-hq/rubocop)\nCopyright \u0026copy; 2012-19 Bozhidar Batsov\nLicense (MIT): [https://github.com/rubocop-hq/rubocop/blob/master/LICENSE.txt](https://github.com/rubocop-hq/rubocop/blob/master/LICENSE.txt)\n\n**WebMock** [https://github.com/bblimke/webmock](https://github.com/bblimke/webmock)\nCopyright \u0026copy; 2009-2010 Bartosz Blimke\nLicense (MIT): [https://github.com/bblimke/webmock/blob/master/LICENSE](https://github.com/bblimke/webmock/blob/master/LICENSE)\n\n### Other Optimizely SDKs\n\n- Agent - https://github.com/optimizely/agent\n\n- Android - https://github.com/optimizely/android-sdk\n\n- C# - https://github.com/optimizely/csharp-sdk\n\n- Flutter - https://github.com/optimizely/optimizely-flutter-sdk\n\n- Go - https://github.com/optimizely/go-sdk\n\n- Java - https://github.com/optimizely/java-sdk\n\n- JavaScript - https://github.com/optimizely/javascript-sdk\n\n- PHP - https://github.com/optimizely/php-sdk\n\n- Python - https://github.com/optimizely/python-sdk\n\n- React - https://github.com/optimizely/react-sdk\n\n- Ruby - https://github.com/optimizely/ruby-sdk\n\n- Swift - https://github.com/optimizely/swift-sdk\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foptimizely%2Fruby-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foptimizely%2Fruby-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foptimizely%2Fruby-sdk/lists"}