Featurevisor

Migrating the Ruby SDK for Featurevisor v4

Upgrade Ruby applications to SDK 4.0.0 for Featurevisor v4 support.

Follow the shared migration order: prepare canonical prerequisite datafiles, upgrade consumers, then upgrade the project CLI. Before publishing new runtime fields, follow Adopt new syntax safely.

Convert Groups before upgrading

This SDK silently ignores legacy feature ranges, with no compatibility handling or warning. Convert Groups to flat list requirements while still on the previous compatible SDK and v3 CLI, then publish all datafiles, caches and bundled copies before upgrading. Unconverted files can change cohorts or enable features without a variation. Old cohorts are not guaranteed. Follow Groups removed.

Minimal migration path

  1. Prepare existing feature prerequisites using the central migration order.
  2. Replace the removed module hooks and detailed evaluation fields below if your application uses them.
  3. Upgrade the base gem to 4.0.0. If the application uses the OpenFeature gem, upgrade it at the same time.
  4. Follow the mixed version deployment guidance before enabling any new v4 datafile capability.

Most application source code can stay unchanged after datafile preparation. The factory, standard getters, child instances, sticky setters and separate evaluation snapshots keep their existing names:

Existing application calls remain valid
f = Featurevisor.create_featurevisor(datafile: datafile)
enabled = f.is_enabled('checkout', context)
variation = f.get_variation('checkout', context)
label = f.get_variable('checkout', 'label', context)
support_email = f.get_variable('supportEmail', context)
f.set_sticky_features(sticky_features)
f.set_sticky_variables(sticky_variables)
feature_evaluations = f.get_feature_evaluations
variable_evaluations = f.get_variable_evaluations
child = f.spawn({ country: 'nl' })

There is no sticky API or snapshot API rename to perform for these canonical methods.

Breaking changes

Plain Date inputs Breaking

A plain Ruby Date has no time or offset and is no longer accepted by before or after. Both comparisons return false, which a surrounding not may invert. Replace it with an explicit instant, using Time, DateTime or a portable timestamp string:

Before
context = { now: Date.new(2026, 1, 1) }
After
context = { now: Time.utc(2026, 1, 1) }

Choose the intended timezone explicitly rather than relying on the server's local timezone.

Root condition reason Breaking

An unmet root gate reports conditions_unmet for feature flags and global variables, replacing the v3 required reason for feature flags and required_features_unmet for global variables. This applies to attribute, segment, feature and variable leaves in root conditions. Update callbacks, analytics and test expectations. Variation and feature variable evaluations retain their disabled reasons. See the shared migration guidance.

Before
unmet_requirement = evaluation[:reason] == "required"
After
unmet_requirement = evaluation[:reason] == "conditions_unmet"

Datafile update result Breaking

set_datafile now returns true when it accepts the update, including unchanged content, and false when it rejects the update or the instance is closed. A rejected update keeps the previous datafile and reports details through diagnostics. Calls that ignore the result keep working. Update any wrapper or interface that declares the old return type. Merging remains the default.

Before
f.set_datafile(datafile)
After
accepted = f.set_datafile(datafile)
unless accepted
warn 'Datafile rejected. Check diagnostics.'
end

Replace removed module hooks Breaking

The old before and after module hooks are removed. Use before_evaluation and after_evaluation, which already existed in the previous SDK line and are now the only evaluation hooks.

Before
my_module = {
name: 'application-module',
before: ->(options) { options },
after: ->(evaluation, options) { evaluation }
}
f = Featurevisor.create_featurevisor(
datafile: datafile,
modules: [my_module]
)
After
my_module = {
name: 'application-module',
before_evaluation: ->(options) { options },
after_evaluation: ->(evaluation, options) { evaluation }
}
f = Featurevisor.create_featurevisor(
datafile: datafile,
modules: [my_module]
)

The canonical hooks also run for global variable evaluation. If a module contains feature specific behaviour, guard it with options.key?(:feature_key).

Update detailed evaluation fields Breaking

Only code that reads detailed evaluation hashes needs these changes:

BeforeAfter
evaluation[:required]evaluation[:conditions]
evaluation[:sticky]evaluation[:sticky_feature]

New variable prerequisite failures are exposed through evaluation[:conditions]. Ordinary getter return types do not change.

Number getter Breaking

Variables that hold numbers have the type number, so the typed getter is now get_variable_number. It reads number variables and the double variables of datafiles built before v4. get_variable_double was removed. Rename calls to the number getter, which returns the same value.

Before
threshold = f.get_variable_double("freeShippingThreshold", context)
After
threshold = f.get_variable_number("freeShippingThreshold", context)

OpenFeature

The Ruby OpenFeature provider remains in the separate featurevisor-openfeature gem, which requires the matching base featurevisor gem. If your application uses the provider, upgrade both gems to 4.0.0. The updated provider maps conditions_unmet to OpenFeature's disabled reason.

An empty targeting key received by the provider now replaces an existing userId or configured targeting field with "". An omitted key preserves that field. Verify the final context delivered by your OpenFeature client when contexts are merged.

See the Ruby SDK OpenFeature guide for provider setup.

Migration checklist

Required for the migration

  1. Confirm every consumer uses a compatible SDK release and that existing prerequisites use conditions and feature.
  2. Confirm no module still declares before or after, and detailed evaluation readers use the canonical fields.
  3. Rename get_variable_double calls to get_variable_number.
  4. Upgrade the project CLI last, review mutation order and date and regex comparisons, and retain a prepared rollback datafile.

Only if adopting optional features

Follow Adopt new syntax safely before publishing new datafile syntax. Upgrade every CLI runner before adding checks or scenarios.