From c44a8ab6c4602cbf014701cc2df4a635b1e79790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Luis=20Leal=20Cardoso=20Junior?= Date: Sun, 26 Jul 2026 13:49:34 -0300 Subject: [PATCH 1/2] Fix the broken "create a metric via code" README example --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 531300b8..a531721f 100644 --- a/README.md +++ b/README.md @@ -636,11 +636,15 @@ the experiment name: ab_finished(:my_metric) ``` -You can also create a new metric by instantiating and saving a new Metric object. +You can also create a new metric by instantiating and saving a new Metric +object. A metric groups one or more experiments (`Split::Experiment` objects) +under a name and is persisted to Redis: ```ruby -Split::Metric.new(:my_metric) -Split::Metric.save +signup = Split::ExperimentCatalog.find_or_create("signup_form", "control", "blue") +checkout = Split::ExperimentCatalog.find_or_create("checkout_flow", "control", "one_page") + +Split::Metric.new(name: :conversion, experiments: [signup, checkout]).save ``` #### Goals From 153aa9624f09e73613aa760c5de45e0a93835697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Luis=20Leal=20Cardoso=20Junior?= Date: Sun, 26 Jul 2026 13:49:34 -0300 Subject: [PATCH 2/2] Skip per-key metric lookups in active_experiments when no metrics exist --- lib/split/user.rb | 16 +++++++++++++++- spec/user_spec.rb | 12 ++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/split/user.rb b/lib/split/user.rb index b7b32c73..5f39816a 100644 --- a/lib/split/user.rb +++ b/lib/split/user.rb @@ -56,7 +56,7 @@ def cleanup_old_versions!(experiment) def active_experiments experiments_by_key = keys_without_finished(user.keys).each_with_object({}) do |key, memo| - memo[key] = Metric.possible_experiments(key_without_version(key)) + memo[key] = experiments_for(key_without_version(key)) end names = experiments_by_key.values.flatten.map(&:name).uniq @@ -95,5 +95,19 @@ def keys_without_finished(keys) def key_without_version(key) key.split(/\:\d(?!\:)/)[0] end + + def experiments_for(name) + if metrics_defined? + Metric.possible_experiments(name) + else + Array(Experiment.find(name)) + end + end + + def metrics_defined? + return @metrics_defined if defined?(@metrics_defined) + @metrics_defined = + Split.configuration.metrics.any? || Split.redis.exists?(:metrics) + end end end diff --git a/spec/user_spec.rb b/spec/user_spec.rb index 5e46210f..695736dc 100644 --- a/spec/user_spec.rb +++ b/spec/user_spec.rb @@ -137,6 +137,18 @@ expect(Split.redis).to receive(:hmget).with(:experiment_winner, any_args).once.and_call_original @subject.active_experiments end + + it "resolves experiments directly, without per-key metric lookups, when no metrics are defined" do + expect(Split::Metric).not_to receive(:possible_experiments) + expect(@subject.active_experiments).to eq("active" => "red") + end + + it "still honors a metric persisted only in Redis" do + Split::Metric.new(name: :conversion, experiments: [Split::ExperimentCatalog.find("active")]).save + + expect(Split::Metric).to receive(:possible_experiments).at_least(:once).and_call_original + expect(@subject.active_experiments).to eq("active" => "red") + end end context "allows user to be loaded from adapter" do