diff --git a/README.mdown b/README.mdown index 81bdfa1e..c33ffdb2 100644 --- a/README.mdown +++ b/README.mdown @@ -344,6 +344,7 @@ Split.configure do |config| config.enabled = true config.persistence = Split::Persistence::SessionAdapter #config.start_manually = false ## new test will have to be started manually from the admin panel. default false + config.include_rails_helper = true end ``` diff --git a/lib/split.rb b/lib/split.rb index f876b119..25cbae61 100755 --- a/lib/split.rb +++ b/lib/split.rb @@ -7,6 +7,7 @@ helper metric persistence + encapsulated_helper trial version].each do |f| require "split/#{f}" diff --git a/lib/split/configuration.rb b/lib/split/configuration.rb index e0eaaaac..011fffd9 100644 --- a/lib/split/configuration.rb +++ b/lib/split/configuration.rb @@ -17,6 +17,7 @@ class Configuration attr_accessor :on_trial_complete attr_accessor :on_experiment_reset attr_accessor :on_experiment_delete + attr_accessor :include_rails_helper attr_reader :experiments @@ -118,6 +119,10 @@ def normalized_experiments if goals = value_for(settings, :goals) experiment_config[experiment_name.to_sym][:goals] = goals end + + if (resettable = value_for(settings, :resettable)) != nil + experiment_config[experiment_name.to_sym][:resettable] = resettable + end end experiment_config @@ -172,13 +177,14 @@ def initialize @experiments = {} @persistence = Split::Persistence::SessionAdapter @algorithm = Split::Algorithms::WeightedSample + @include_rails_helper = true end private def value_for(hash, key) if hash.kind_of?(Hash) - hash[key.to_s] || hash[key.to_sym] + hash.has_key?(key.to_s) ? hash[key.to_s] : hash[key.to_sym] end end diff --git a/lib/split/encapsulated_helper.rb b/lib/split/encapsulated_helper.rb new file mode 100644 index 00000000..4797c809 --- /dev/null +++ b/lib/split/encapsulated_helper.rb @@ -0,0 +1,58 @@ +# Split's helper exposes all kinds of methods we don't want to +# mix into our model classes. +# +# This module exposes only two methods +# - ab_test and +# - ab_test_finished +# that can safely be mixed into any class. +# +# Passes the instance of the class that it's mixed into to the +# Split persistence adapter as context. +# +module Split + module EncapsulatedHelper + + class ContextShim + include Split::Helper + def initialize(context, original_params) + @context = context + @_params = original_params + end + def ab_user + @ab_user ||= Split::Persistence.adapter.new(@context) + end + def params + @_params + end + end + + def ab_test(*arguments) + ret = split_context_shim.ab_test(*arguments) + # TODO there must be a better way to pass a block straight + # through to the original ab_test + if block_given? + if defined?(capture) # a block in a rails view + block = Proc.new { yield(ret) } + concat(capture(ret, &block)) + false + else + yield(ret) + end + else + ret + end + end + + def ab_test_finished(*arguments) + split_context_shim.finished *arguments + end + + private + + # instantiate and memoize a context shim in case of multiple ab_test* calls + def split_context_shim + _params = defined?(params) ? params : {} + @split_context_shim ||= ContextShim.new(self, _params) + end + end +end diff --git a/lib/split/engine.rb b/lib/split/engine.rb index 692655f1..04392e76 100644 --- a/lib/split/engine.rb +++ b/lib/split/engine.rb @@ -1,8 +1,10 @@ module Split class Engine < ::Rails::Engine initializer "split" do |app| - ActionController::Base.send :include, Split::Helper - ActionController::Base.helper Split::Helper + if Split.configuration.include_rails_helper + ActionController::Base.send :include, Split::Helper + ActionController::Base.helper Split::Helper + end end end -end \ No newline at end of file +end diff --git a/spec/configuration_spec.rb b/spec/configuration_spec.rb index 568c8453..44b429f5 100644 --- a/spec/configuration_spec.rb +++ b/spec/configuration_spec.rb @@ -86,7 +86,7 @@ end it 'should normalize experiments' do - @config.normalized_experiments.should == {:my_experiment=>{:alternatives=>["Control Opt", ["Alt One", "Alt Two"]]}} + @config.normalized_experiments.should == {:my_experiment=>{:resettable=>false,:alternatives=>["Control Opt", ["Alt One", "Alt Two"]]}} end end @@ -112,7 +112,7 @@ end it "should normalize experiments" do - @config.normalized_experiments.should == {:my_experiment=>{:alternatives=>[{"Control Opt"=>0.67}, + @config.normalized_experiments.should == {:my_experiment=>{:resettable=>false,:alternatives=>[{"Control Opt"=>0.67}, [{"Alt One"=>0.1}, {"Alt Two"=>0.23}]]}, :another_experiment=>{:alternatives=>["a", ["b"]]}} end @@ -139,7 +139,7 @@ end it "should normalize experiments" do - @config.normalized_experiments.should == {:my_experiment=>{:alternatives=>["Control Opt", ["Alt One", "Alt Two"]]}} + @config.normalized_experiments.should == {:my_experiment=>{:resettable=>false,:alternatives=>["Control Opt", ["Alt One", "Alt Two"]]}} end end