diff --git a/docs/reference/technologies/server/ruby.mdx b/docs/reference/technologies/server/ruby.mdx new file mode 100644 index 000000000..e5930a9fd --- /dev/null +++ b/docs/reference/technologies/server/ruby.mdx @@ -0,0 +1,281 @@ +--- +title: OpenFeature Ruby SDK +slug: ruby +sidebar_label: Ruby +--- + + + +
+ +## Quick start + +### Requirements + +| Supported Ruby Version | OS | +| ------------ | --------------------- | +| Ruby 3.1.4 | Windows, MacOS, Linux | +| Ruby 3.2.3 | Windows, MacOS, Linux | +| Ruby 3.3.0 | Windows, MacOS, Linux | + +### Install + +Install the gem and add to the application's Gemfile by executing: + +```sh +bundle add openfeature-sdk +``` + +If bundler is not being used to manage dependencies, install the gem by executing: + +```sh +gem install openfeature-sdk +``` + +### Usage + +```ruby +require 'open_feature/sdk' +require 'json' # For JSON.dump + +# API Initialization and configuration + +OpenFeature::SDK.configure do |config| + # your provider of choice, which will be used as the default provider + config.set_provider(OpenFeature::SDK::Provider::InMemoryProvider.new( + { + "flag1" => true, + "flag2" => 1 + } + )) +end + +# Create a client +client = OpenFeature::SDK.build_client + +# fetching boolean value feature flag +bool_value = client.fetch_boolean_value(flag_key: 'boolean_flag', default_value: false) + +# a details method is also available for more information about the flag evaluation +# see `ResolutionDetails` for more info +bool_details = client.fetch_boolean_details(flag_key: 'boolean_flag', default_value: false) == + +# fetching string value feature flag +string_value = client.fetch_string_value(flag_key: 'string_flag', default_value: false) + +# fetching number value feature flag +float_value = client.fetch_number_value(flag_key: 'number_value', default_value: 1.0) +integer_value = client.fetch_number_value(flag_key: 'number_value', default_value: 1) + +# get an object value +object = client.fetch_object_value(flag_key: 'object_value', default_value: JSON.dump({ name: 'object'})) +``` + +## Features + +| Status | Features | Description | +| ------ | --------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. | +| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). | +| ⚠️ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | +| ❌ | [Logging](#logging) | Integrate with popular logging packages. | +| ✅ | [Domains](#domains) | Logically bind clients with providers. | +| ❌ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | +| ⚠️ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | +| ❌ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) | +| ⚠️ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | + +Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ + +### Providers + +[Providers](/docs/reference/concepts/provider) are an abstraction between a flag management system and the OpenFeature SDK. +Look [here](/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Ruby) for a complete list of available providers. +If the provider you're looking for hasn't been created yet, see the [develop a provider](#develop-a-provider) section to learn how to build it yourself. + +Once you've added a provider as a dependency, it can be registered with OpenFeature like this: + +```ruby +OpenFeature::SDK.configure do |config| + # your provider of choice, which will be used as the default provider + config.set_provider(OpenFeature::SDK::Provider::InMemoryProvider.new( + { + "v2_enabled" => true, + } + )) +end +``` + +In some situations, it may be beneficial to register multiple providers in the same application. +This is possible using [domains](#domains), which is covered in more detail below. + +### Targeting + +Sometimes, the value of a flag must consider some dynamic criteria about the application or user, such as the user's location, IP, email address, or the server's location. +In OpenFeature, we refer to this as [targeting](/specification/glossary#targeting). +If the flag management system you're using supports targeting, you can provide the input data using the [evaluation context](/docs/reference/concepts/evaluation-context). + +```ruby +OpenFeature::SDK.configure do |config| + # you can set a global evaluation context here + config.evaluation_context = OpenFeature::SDK::EvaluationContext.new("host" => "myhost.com") +end + +# Evaluation context can be set on a client as well +client_with_context = OpenFeature::SDK.build_client( + evaluation_context: OpenFeature::SDK::EvaluationContext.new("controller_name" => "admin") +) + +# Invocation evaluation context can also be passed in during flag evaluation. +# During flag evaluation, invocation context takes precedence over client context +# which takes precedence over API (aka global) context. +bool_value = client.fetch_boolean_value( + flag_key: 'boolean_flag', + default_value: false, + evaluation_context: OpenFeature::SDK::EvaluationContext.new("is_friday" => true) +) +``` + +### Hooks + +Coming Soon! [Issue available](https://github.com/open-feature/ruby-sdk/issues/52) to be worked on. + + + +### Logging + +Coming Soon! [Issue available](https://github.com/open-feature/ruby-sdk/issues/148) to work on. + +### Domains + +Clients can be assigned to a domain. A domain is a logical identifier which can be used to associate clients with a particular provider. +If a domain has no associated provider, the default provider is used. + +```ruby +OpenFeature::SDK.configure do |config| + config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new, domain: "legacy_flags") +end + +# Create a client for a different domain, this will use the provider assigned to that domain +legacy_flag_client = OpenFeature::SDK.build_client(domain: "legacy_flags") +``` + +### Eventing + +Coming Soon! [Issue available](https://github.com/open-feature/ruby-sdk/issues/51) to be worked on. + + + +### Shutdown + +Coming Soon! [Issue available](https://github.com/open-feature/ruby-sdk/issues/149) to be worked on. + + + +### Transaction Context Propagation + +Coming Soon! [Issue available](https://github.com/open-feature/ruby-sdk/issues/150) to be worked on. + + + +## Extending + +### Develop a provider + +To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. +This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/ruby-sdk-contrib) available under the OpenFeature organization. +You’ll then need to write the provider by implementing the `Provider` duck. + +```ruby +class MyProvider + def init + # Perform any initialization steps with flag management system here + # Return value is ignored + # **Note** The OpenFeature spec defines a lifecycle method called `initialize` to be called when a new provider is set. + # To avoid conflicting with the Ruby `initialize` method, this method should be named `init` when creating a provider. + end + + def shutdown + # Perform any shutdown/reclamation steps with flag management system here + # Return value is ignored + end + + def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil) + # Retrieve a boolean value from provider source + end + + def fetch_string_value(flag_key:, default_value:, evaluation_context: nil) + # Retrieve a string value from provider source + end + + def fetch_number_value(flag_key:, default_value:, evaluation_context: nil) + # Retrieve a numeric value from provider source + end + + def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil) + # Retrieve a integer value from provider source + end + + def fetch_float_value(flag_key:, default_value:, evaluation_context: nil) + # Retrieve a float value from provider source + end + + def fetch_object_value(flag_key:, default_value:, evaluation_context: nil) + # Retrieve a hash value from provider source + end +end +``` + +> Built a new provider? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=provider&projects=&template=document-provider.yaml&title=%5BProvider%5D%3A+) so we can add it to the docs! + +### Develop a hook + +Coming Soon! [Issue available](https://github.com/open-feature/ruby-sdk/issues/52) to be worked on. + + + diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 189c4728d..46b95087b 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -162,7 +162,7 @@ const themeConfig: ThemeCommonConfig & AlgoliaThemeConfig = { }, prism: { theme: themes.oceanicNext, - additionalLanguages: ['java', 'csharp', 'powershell', 'php', 'kotlin'], + additionalLanguages: ['java', 'csharp', 'powershell', 'php', 'kotlin', 'ruby'], magicComments: [ { className: 'theme-code-block-highlighted-line', diff --git a/src/datasets/index.ts b/src/datasets/index.ts index e3327be8b..4d960bc80 100644 --- a/src/datasets/index.ts +++ b/src/datasets/index.ts @@ -20,6 +20,8 @@ export const TECHNOLOGY_COLOR_MAP: Record