diff --git a/CHANGELOG.md b/CHANGELOG.md index 44f5a0f1..e0f13b55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.0.3 +June 25th, 2018 + +### Bug Fixes +Fixes [#109](https://github.com/optimizely/ruby-sdk/issues/109) + ## 2.0.2 June 19th, 2018 diff --git a/lib/optimizely.rb b/lib/optimizely.rb index 5989dab2..4e404c2f 100644 --- a/lib/optimizely.rb +++ b/lib/optimizely.rb @@ -63,8 +63,8 @@ def initialize(datafile, event_dispatcher = nil, logger = nil, error_handler = n validate_instantiation_options(datafile, skip_json_validation) rescue InvalidInputError => e @is_valid = false - logger = SimpleLogger.new - logger.log(Logger::ERROR, e.message) + @logger = SimpleLogger.new + @logger.log(Logger::ERROR, e.message) return end @@ -72,15 +72,15 @@ def initialize(datafile, event_dispatcher = nil, logger = nil, error_handler = n @config = ProjectConfig.new(datafile, @logger, @error_handler) rescue @is_valid = false - logger = SimpleLogger.new - logger.log(Logger::ERROR, InvalidInputError.new('datafile').message) + @logger = SimpleLogger.new + @logger.log(Logger::ERROR, InvalidInputError.new('datafile').message) return end unless @config.parsing_succeeded? @is_valid = false - logger = SimpleLogger.new - logger.log(Logger::ERROR, InvalidDatafileVersionError.new.message) + @logger = SimpleLogger.new + @logger.log(Logger::ERROR, InvalidDatafileVersionError.new.message) return end @@ -100,8 +100,7 @@ def activate(experiment_key, user_id, attributes = nil) # Returns nil if experiment is not Running, if user is not in experiment, or if datafile is invalid. unless @is_valid - logger = SimpleLogger.new - logger.log(Logger::ERROR, InvalidDatafileError.new('activate').message) + @logger.log(Logger::ERROR, InvalidDatafileError.new('activate').message) return nil end @@ -137,8 +136,7 @@ def get_variation(experiment_key, user_id, attributes = nil) # Returns nil if experiment is not Running, if user is not in experiment, or if datafile is invalid. unless @is_valid - logger = SimpleLogger.new - logger.log(Logger::ERROR, InvalidDatafileError.new('get_variation').message) + @logger.log(Logger::ERROR, InvalidDatafileError.new('get_variation').message) return nil end @@ -200,8 +198,7 @@ def track(event_key, user_id, attributes = nil, event_tags = nil) # event_tags - Hash representing metadata associated with the event. unless @is_valid - logger = SimpleLogger.new - logger.log(Logger::ERROR, InvalidDatafileError.new('track').message) + @logger.log(Logger::ERROR, InvalidDatafileError.new('track').message) return nil end @@ -259,8 +256,7 @@ def is_feature_enabled(feature_flag_key, user_id, attributes = nil) # False if the feature is disabled. # False if the feature is not found. unless @is_valid - logger = SimpleLogger.new - logger.log(Logger::ERROR, InvalidDatafileError.new('is_feature_enabled').message) + @logger.log(Logger::ERROR, InvalidDatafileError.new('is_feature_enabled').message) return false end @@ -315,8 +311,7 @@ def get_enabled_features(user_id, attributes = nil) enabled_features = [] unless @is_valid - logger = SimpleLogger.new - logger.log(Logger::ERROR, InvalidDatafileError.new('get_enabled_features').message) + @logger.log(Logger::ERROR, InvalidDatafileError.new('get_enabled_features').message) return enabled_features end @@ -343,6 +338,11 @@ def get_feature_variable_string(feature_flag_key, variable_key, user_id, attribu # Returns the string variable value. # Returns nil if the feature flag or variable are not found. + unless @is_valid + @logger.log(Logger::ERROR, InvalidDatafileError.new('get_feature_variable_string').message) + return nil + end + variable_value = get_feature_variable_for_type( feature_flag_key, variable_key, @@ -365,6 +365,11 @@ def get_feature_variable_boolean(feature_flag_key, variable_key, user_id, attrib # Returns the boolean variable value. # Returns nil if the feature flag or variable are not found. + unless @is_valid + @logger.log(Logger::ERROR, InvalidDatafileError.new('get_feature_variable_boolean').message) + return nil + end + variable_value = get_feature_variable_for_type( feature_flag_key, variable_key, @@ -387,6 +392,11 @@ def get_feature_variable_double(feature_flag_key, variable_key, user_id, attribu # Returns the double variable value. # Returns nil if the feature flag or variable are not found. + unless @is_valid + @logger.log(Logger::ERROR, InvalidDatafileError.new('get_feature_variable_double').message) + return nil + end + variable_value = get_feature_variable_for_type( feature_flag_key, variable_key, @@ -409,6 +419,11 @@ def get_feature_variable_integer(feature_flag_key, variable_key, user_id, attrib # Returns the integer variable value. # Returns nil if the feature flag or variable are not found. + unless @is_valid + @logger.log(Logger::ERROR, InvalidDatafileError.new('get_feature_variable_integer').message) + return nil + end + variable_value = get_feature_variable_for_type( feature_flag_key, variable_key, diff --git a/lib/optimizely/version.rb b/lib/optimizely/version.rb index 4097bce3..4fe2439d 100644 --- a/lib/optimizely/version.rb +++ b/lib/optimizely/version.rb @@ -17,5 +17,5 @@ # module Optimizely CLIENT_ENGINE = 'ruby-sdk' - VERSION = '2.0.2' + VERSION = '2.0.3' end diff --git a/spec/project_spec.rb b/spec/project_spec.rb index d2c122e6..85620b7d 100644 --- a/spec/project_spec.rb +++ b/spec/project_spec.rb @@ -895,6 +895,17 @@ class InvalidErrorHandler; end user_id = 'test_user' user_attributes = {} + it 'should return nil when called with invalid project config' do + logger = double('logger') + allow(logger).to receive(:log) + allow(Optimizely::SimpleLogger).to receive(:new) { logger } + invalid_project = Optimizely::Project.new('invalid', nil, spy_logger) + expect(invalid_project.get_feature_variable_string('string_single_variable_feature', 'string_variable', user_id, user_attributes)) + .to eq(nil) + expect(logger).to have_received(:log).once.with(Logger::ERROR, 'Provided datafile is in an invalid format.') + expect(logger).to have_received(:log).once.with(Logger::ERROR, 'Provided datafile is in an invalid format. Aborting get_feature_variable_string.') + end + describe 'when the feature flag is enabled for the user' do describe 'and a variable usage instance is not found' do it 'should return the default variable value' do @@ -1029,6 +1040,17 @@ class InvalidErrorHandler; end user_id = 'test_user' user_attributes = {} + it 'should return nil when called with invalid project config' do + logger = double('logger') + allow(logger).to receive(:log) + allow(Optimizely::SimpleLogger).to receive(:new) { logger } + invalid_project = Optimizely::Project.new('invalid', nil, spy_logger) + expect(invalid_project.get_feature_variable_boolean('boolean_single_variable_feature', 'boolean_variable', user_id, user_attributes)) + .to eq(nil) + expect(logger).to have_received(:log).once.with(Logger::ERROR, 'Provided datafile is in an invalid format.') + expect(logger).to have_received(:log).once.with(Logger::ERROR, 'Provided datafile is in an invalid format. Aborting get_feature_variable_boolean.') + end + it 'should return the variable value for the variation for the user is bucketed into' do boolean_feature = project_instance.config.feature_flag_key_map['boolean_single_variable_feature'] rollout = project_instance.config.rollout_id_map[boolean_feature['rolloutId']] @@ -1055,6 +1077,17 @@ class InvalidErrorHandler; end user_id = 'test_user' user_attributes = {} + it 'should return nil when called with invalid project config' do + logger = double('logger') + allow(logger).to receive(:log) + allow(Optimizely::SimpleLogger).to receive(:new) { logger } + invalid_project = Optimizely::Project.new('invalid', nil, spy_logger) + expect(invalid_project.get_feature_variable_double('double_single_variable_feature', 'double_variable', user_id, user_attributes)) + .to eq(nil) + expect(logger).to have_received(:log).once.with(Logger::ERROR, 'Provided datafile is in an invalid format.') + expect(logger).to have_received(:log).once.with(Logger::ERROR, 'Provided datafile is in an invalid format. Aborting get_feature_variable_double.') + end + it 'should return the variable value for the variation for the user is bucketed into' do double_feature = project_instance.config.feature_flag_key_map['double_single_variable_feature'] experiment_to_return = project_instance.config.experiment_id_map[double_feature['experimentIds'][0]] @@ -1082,6 +1115,17 @@ class InvalidErrorHandler; end user_id = 'test_user' user_attributes = {} + it 'should return nil when called with invalid project config' do + logger = double('logger') + allow(logger).to receive(:log) + allow(Optimizely::SimpleLogger).to receive(:new) { logger } + invalid_project = Optimizely::Project.new('invalid', nil, spy_logger) + expect(invalid_project.get_feature_variable_integer('integer_single_variable_feature', 'integer_variable', user_id, user_attributes)) + .to eq(nil) + expect(logger).to have_received(:log).once.with(Logger::ERROR, 'Provided datafile is in an invalid format.') + expect(logger).to have_received(:log).once.with(Logger::ERROR, 'Provided datafile is in an invalid format. Aborting get_feature_variable_integer.') + end + it 'should return the variable value for the variation for the user is bucketed into' do integer_feature = project_instance.config.feature_flag_key_map['integer_single_variable_feature'] experiment_to_return = project_instance.config.experiment_id_map[integer_feature['experimentIds'][0]]