diff --git a/README.md b/README.md index 73b4c36..a48f79f 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,23 @@ explicitly in your Gemfile: gem 'redis-objects', '>= 2.0.0.beta' ~~~ You're encouraged to try it out in test code (not production) to ensure it works for you. -Official release is expected later in 2023. +Official release is expected eventually. Key Naming Changes ------------------ -The internal key naming scheme has changed for `Nested::Class::Namespaces` to fix a longstanding bug. -**This means your existing data in Redis will not be accessible until you call `migrate_redis_legacy_keys`.** +A new method to generate the internal key naming scheme has been added to fix a +longstanding bug. (Refer to [#213](https://github.com/nateware/redis-objects/issues/231)) +It can be controlled by `Redis::Objects.prefix_style =` either `:legacy` (default) +or `:modern`. +If your Redis::Object enhanced classes are nested such as `Nested::Class::Namespaces` +then you should upgrade them using the below proceedure. (only needed once) -To fix this (only needed once), create a script like this: +Create a script like this: ~~~ruby class YouClassNameHere < ActiveRecord::Base include Redis::Objects - # ... your relevant definitions here ... + # ... your relevant redis_object definitions here (counters/sets) ... end YourClassName.migrate_redis_legacy_keys @@ -37,7 +41,10 @@ Then, you need to find a time when you can temporarily pause writes to your redi so that you can run that script. It uses `redis.scan` internally so it should be able to handle a high number of keys. For large data sets, it could take a while. -For more details on the issue and fix refer to [#213](https://github.com/nateware/redis-objects/issues/231). +After migrating all of your redis keys, update `Redis::Objects.prefix_style = :modern` to +start using the new keys. +**Your existing data in Redis will not be accessible after running `migrate_redis_legacy_keys` +until the prefix_style has been changed.** Renaming of `lock` Method ------------------------- diff --git a/lib/redis/objects.rb b/lib/redis/objects.rb index c526078..320b637 100644 --- a/lib/redis/objects.rb +++ b/lib/redis/objects.rb @@ -66,6 +66,19 @@ def redis raise(NotConnected, "Redis::Objects.redis not set to a Redis.new connection") end + # Toggles whether to use the legacy redis key naming scheme, which causes + # naming conflicts in certain cases. + # (attr_accessor with a default value) + attr_writer :prefix_style + def prefix_style + # NOTE: In a future release the default will change to :modern + @prefix_style ||= :legacy + end + + def redis_legacy_naming? + prefix_style == :legacy + end + def included(klass) # Core (this file) klass.instance_variable_set(:@redis, nil) @@ -101,11 +114,6 @@ def redis_objects @redis_objects ||= {} end - # Toggles whether to use the legacy redis key naming scheme, which causes - # naming conflicts in certain cases. - attr_accessor :redis_legacy_naming - attr_accessor :redis_silence_warnings - # Set the Redis redis_prefix to use. Defaults to class_name. def redis_prefix=(redis_prefix) @silence_warnings_as_redis_prefix_was_set_manually = true @@ -114,10 +122,10 @@ def redis_prefix=(redis_prefix) def redis_prefix(klass = self) #:nodoc: @redis_prefix ||= - if redis_legacy_naming + if Objects.redis_legacy_naming? + redis_legacy_naming_warning_message(klass) redis_legacy_prefix(klass) else - redis_legacy_naming_warning_message(klass) redis_modern_prefix(klass) end @@ -140,33 +148,44 @@ def redis_legacy_prefix(klass = self) #:nodoc: downcase end - # Temporary warning to help with migrating key names + attr_accessor :redis_silence_warnings + + # Temporary warning to help with migrating key names def redis_legacy_naming_warning_message(klass) # warn @silence_warnings_as_redis_prefix_was_set_manually.inspect - unless redis_legacy_naming || redis_silence_warnings || @silence_warnings_as_redis_prefix_was_set_manually - modern = redis_modern_prefix(klass) - legacy = redis_legacy_prefix(klass) - if modern != legacy - warn < "#{legacy}:*") total_keys += keys.length @@ -183,6 +202,10 @@ def migrate_redis_legacy_keys warn "[redis-objects] Warning: Rename '#{key}', '#{new_key}' failed: #{ok}" if ok != 'OK' end break if cursor == "0" + + ensure + # Change the prefix back (just in case) + self.redis_prefix = legacy end warn "[redis-objects] Migrated #{total_keys} total number of redis keys" diff --git a/spec/redis_key_naming_spec.rb b/spec/redis_key_naming_spec.rb new file mode 100644 index 0000000..60cc858 --- /dev/null +++ b/spec/redis_key_naming_spec.rb @@ -0,0 +1,427 @@ +require File.expand_path(File.dirname(__FILE__) + '/spec_helper') + +require 'redis/objects' +Redis::Objects.redis = REDIS_HANDLE + +require 'securerandom' + +require "stringio" + +def capture_stderr + # The output stream must be an IO-like object. In this case we capture it in + # an in-memory IO object so we can return the string value. You can assign any + # IO object here. + previous_stderr, $stderr = $stderr, StringIO.new + yield + $stderr.string +ensure + # Restore the previous value of stderr (typically equal to STDERR). + $stderr = previous_stderr +end + +describe 'Redis key prefix naming compatibility' do + + describe 'verifies single level classes' do # context + + it 'work the same (modern)' do + Redis::Objects.prefix_style = :modern + + class SingleLevelOne + include Redis::Objects + + def id + 1 + end + end + + obj = SingleLevelOne.new + obj.class.redis_prefix.should == 'single_level_one' + end + + it 'work the same (legacy)' do + Redis::Objects.prefix_style = :legacy + + class SingleLevelTwo + include Redis::Objects + + def id + 1 + end + end + + obj = SingleLevelTwo.new + obj.class.redis_prefix.should == 'single_level_two' + end + + end # context + + describe 'verifies nested classes' do # context + + it 'do NOT work the same (modern)' do + Redis::Objects.prefix_style = :modern + + module Nested + class NamingOne + include Redis::Objects + + def id + 1 + end + end + end + + obj = Nested::NamingOne.new + obj.class.redis_prefix.should == 'nested__naming_one' + end + + it 'do NOT work the same (legacy)' do + Redis::Objects.prefix_style = :legacy + + module Nested + class NamingTwo + include Redis::Objects + self.redis_silence_warnings = true + + def id + 1 + end + end + end + + obj = Nested::NamingTwo.new + obj.class.redis_prefix.should == 'naming_two' + end + + end # context + + describe 'verifies that multiple levels' do # context + + it 'respect __ vs _' do + Redis::Objects.prefix_style = :modern + + module NestedLevel + module Further + class NamingThree + include Redis::Objects + + def id + 1 + end + end + end + end + + obj = NestedLevel::Further::NamingThree.new + obj.class.redis_prefix.should == 'nested_level__further__naming_three' + end + + it 'respect legacy naming' do + Redis::Objects.prefix_style = :legacy + + module NestedLevel + module Further + class NamingFour + include Redis::Objects + self.redis_silence_warnings = true + + def id + 1 + end + + redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT, :db => 31) + value :redis_value, :redis => redis_handle + end + end + end + + obj = NestedLevel::Further::NamingFour.new + obj.class.redis_prefix.should == 'naming_four' + val = SecureRandom.hex(10) + obj.redis_value = val + obj.redis_value.should == val + obj.redis_value.key.should == 'naming_four:1:redis_value' + end + + it 'do not conflict 1' do + Redis::Objects.prefix_style = :modern + + module NestedLevel + module Further + class NamingFive + include Redis::Objects + + def id + 1 + end + + value :redis_value + end + end + end + + obj = NestedLevel::Further::NamingFive.new + obj.class.redis_prefix.should == 'nested_level__further__naming_five' + val = SecureRandom.hex(10) + obj.redis_value = val + obj.redis_value.should == val + obj.redis_value.key.should == 'nested_level__further__naming_five:1:redis_value' + obj.redis_value.redis.should == obj.redis + obj.redis.get('nested_level__further__naming_five:1:redis_value').should == val + end + + it 'do not conflict 2' do + Redis::Objects.prefix_style = :modern + + module Nested + module LevelFurtherNaming + class Five + include Redis::Objects + + def id + 1 + end + + value :redis_value + end + end + end + + obj = Nested::LevelFurtherNaming::Five.new + obj.class.redis_prefix.should == 'nested__level_further_naming__five' + val = SecureRandom.hex(10) + obj.redis_value = val + obj.redis_value.should == val + obj.redis_value.key.should == 'nested__level_further_naming__five:1:redis_value' + obj.redis.get('nested__level_further_naming__five:1:redis_value').should == val + end + + it 'do not conflict 3' do + Redis::Objects.prefix_style = :modern + + module Nested + module LevelFurther + class NamingFive + include Redis::Objects + + def id + 1 + end + + value :redis_value + end + end + end + + obj = Nested::LevelFurther::NamingFive.new + obj.class.redis_prefix.should == 'nested__level_further__naming_five' + val = SecureRandom.hex(10) + obj.redis_value = val + obj.redis_value.should == val + obj.redis_value.key.should == 'nested__level_further__naming_five:1:redis_value' + obj.redis.get('nested__level_further__naming_five:1:redis_value').should == val + end + + end # context + + describe 'handles dynamically created classes correctly' do # context + + it 'in modern mode' do + Redis::Objects.prefix_style = :modern + + module Nested + class LevelSix + include Redis::Objects + + def id + 1 + end + + value :redis_value + end + end + + obj = Nested::LevelSix.new + obj.class.redis_prefix.should == 'nested__level_six' + val = SecureRandom.hex(10) + obj.redis_value = val + obj.redis_value.should == val + obj.redis_value.key.should == 'nested__level_six:1:redis_value' + obj.redis.get('nested__level_six:1:redis_value').should == val + + DynamicClass = Class.new(Nested::LevelSix) + DynamicClass.value :redis_value2 + obj2 = DynamicClass.new + DynamicClass.redis_prefix.should == 'dynamic_class' + obj2.redis_value.should.be.kind_of(Redis::Value) + obj2.redis_value2.should.be.kind_of(Redis::Value) + obj2.redis_value.key.should == 'dynamic_class:1:redis_value' + obj2.redis_value2.key.should == 'dynamic_class:1:redis_value2' + + end + + it 'in legacy mode' do + Redis::Objects.prefix_style = :legacy + + module Nested + class LevelSeven + include Redis::Objects + self.redis_silence_warnings = true + + def id + 1 + end + + value :redis_value + end + end + + obj = Nested::LevelSeven.new + obj.class.redis_prefix.should == 'level_seven' + val = SecureRandom.hex(10) + obj.redis_value = val + obj.redis_value.should == val + obj.redis_value.key.should == 'level_seven:1:redis_value' + obj.redis.get('level_seven:1:redis_value').should == val + + DynamicClass2 = Class.new(Nested::LevelSeven) + DynamicClass2.value :redis_value2 + obj2 = DynamicClass2.new + DynamicClass2.redis_prefix.should == 'dynamic_class2' + obj2.redis_value.should.be.kind_of(Redis::Value) + obj2.redis_value2.should.be.kind_of(Redis::Value) + obj2.redis_value.key.should == 'dynamic_class2:1:redis_value' + obj2.redis_value2.key.should == 'dynamic_class2:1:redis_value2' + end + + end # context + + # ---- other tests ---- + + it 'prints a warning message if the key name changes' do + Redis::Objects.prefix_style = :legacy + + module Nested + class LevelNine + include Redis::Objects + + def id + 1 + end + + value :redis_value + end + end + + captured_output = capture_stderr do + # Does not output anything directly. + obj = Nested::LevelNine.new + val = SecureRandom.hex(10) + obj.redis_value = val + obj.redis_value.should == val + end + + captured_output.should =~ /Warning:/i + end + + it 'supports a method to migrate legacy key names' do + + module Nested + def self.make_class + # TODO notes + klass = Class.new do + def initialize(id) + @id = id + end + def id + @id + end + + include Redis::Objects + + self.redis_silence_warnings = true + + value :redis_value + counter :redis_counter + hash_key :redis_hash + list :redis_list + set :redis_set + sorted_set :redis_sorted_set + + # global class counters + value :global_value, :global => true + counter :global_counter, :global => true + hash_key :global_hash_key, :global => true + list :global_list, :global => true + set :global_set, :global => true + sorted_set :global_sorted_set, :global => true + + # use a callable as the key + value :global_proc_value, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" } + end + end + end + + # First define the class using legacy prefix + Redis::Objects.prefix_style = :legacy + Nested::UpgradeTest = Nested.make_class + + # Sanity checks + Nested::UpgradeTest.redis_objects.length.should == 13 + Nested::UpgradeTest.redis_prefix.should == 'upgrade_test' + + # Create a whole bunch of keys using the legacy prefixed keys + + 30.times do |i| + # warn i.inspect + obj = Nested::UpgradeTest.new(i) + obj.redis_value = i + obj.redis_counter.increment + obj.redis_hash[:key] = i + obj.redis_list << i + obj.redis_set << i + obj.redis_sorted_set[i] = i + end + + obj = Nested::UpgradeTest.new(99) + obj.global_value = 42 + obj.global_counter.increment + obj.global_counter.increment + obj.global_counter.increment + obj.global_hash_key[:key] = 'value' + obj.global_set << 'a' << 'b' + obj.global_sorted_set[:key] = 2.2 + + # Run the upgrade + Nested::UpgradeTest.migrate_redis_legacy_keys + + # Re-Create the class using modern prefix + Nested.send(:remove_const, :UpgradeTest) + Redis::Objects.prefix_style = :modern + Nested::UpgradeTest = Nested.make_class + + # Sanity checks + Nested::UpgradeTest.redis_objects.length.should == 13 + Nested::UpgradeTest.redis_prefix.should == 'nested__upgrade_test' + + # Try to access the keys through modern prefixed keys now + 30.times do |i| + # warn i.inspect + obj = Nested::UpgradeTest.new(i) + obj.redis_value.to_i.should == i + obj.redis_counter.to_i.should == 1 + obj.redis_hash[:key].to_i.should == i + obj.redis_list[0].to_i.should == i + obj.redis_set.include?(i).should == true + obj.redis_sorted_set[i].should == i + end + + obj = Nested::UpgradeTest.new(99) + obj.global_value.to_i.should == 42 + obj.global_counter.to_i.should == 3 + obj.global_hash_key[:key].should == 'value' + obj.global_set.include?('a').should == true + obj.global_set.include?('b').should == true + obj.global_sorted_set[:key].should == 2.2 + end + +end diff --git a/spec/redis_legacy_key_naming_spec.rb b/spec/redis_legacy_key_naming_spec.rb deleted file mode 100644 index 85c1ebb..0000000 --- a/spec/redis_legacy_key_naming_spec.rb +++ /dev/null @@ -1,419 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/spec_helper') - -require 'redis/objects' -Redis::Objects.redis = REDIS_HANDLE - -require 'securerandom' - -require "stringio" - -def capture_stderr - # The output stream must be an IO-like object. In this case we capture it in - # an in-memory IO object so we can return the string value. You can assign any - # IO object here. - previous_stderr, $stderr = $stderr, StringIO.new - yield - $stderr.string -ensure - # Restore the previous value of stderr (typically equal to STDERR). - $stderr = previous_stderr -end - -describe 'Legacy redis key prefix naming compatibility' do - it 'verifies single level classes work the same' do - class SingleLevelOne - include Redis::Objects - - def id - 1 - end - end - - obj = SingleLevelOne.new - obj.class.redis_prefix.should == 'single_level_one' - end - - it 'verifies single level classes obey the legacy naming flag' do - class SingleLevelTwo - include Redis::Objects - self.redis_legacy_naming = true - - def id - 1 - end - end - - obj = SingleLevelTwo.new - obj.class.redis_prefix.should == 'single_level_two' - end - - it 'verifies nested classes do NOT work the same' do - module Nested - class NamingOne - include Redis::Objects - self.redis_silence_warnings = true - - def id - 1 - end - end - end - - obj = Nested::NamingOne.new - obj.class.redis_prefix.should == 'nested__naming_one' - end - - it 'verifies the legacy naming flag is respected' do - module Nested - class NamingTwo - include Redis::Objects - self.redis_legacy_naming = true - self.redis_silence_warnings = true - - def id - 1 - end - end - end - - Nested::NamingTwo.redis_legacy_naming.should == true - obj = Nested::NamingTwo.new - obj.class.redis_prefix.should == 'naming_two' - end - - it 'verifies that multiple levels respect __ vs _' do - module NestedLevel - module Further - class NamingThree - include Redis::Objects - self.redis_silence_warnings = true - - def id - 1 - end - end - end - end - - obj = NestedLevel::Further::NamingThree.new - obj.class.redis_prefix.should == 'nested_level__further__naming_three' - end - - it 'verifies that multiple levels respect the legacy naming' do - module NestedLevel - module Further - class NamingFour - include Redis::Objects - self.redis_legacy_naming = true - - def id - 1 - end - - redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT, :db => 31) - value :redis_value, :redis => redis_handle - end - end - end - - NestedLevel::Further::NamingFour.redis_legacy_naming.should == true - obj = NestedLevel::Further::NamingFour.new - obj.class.redis_prefix.should == 'naming_four' - val = SecureRandom.hex(10) - obj.redis_value = val - obj.redis_value.should == val - obj.redis_value.key.should == 'naming_four:1:redis_value' - end - - it 'verifies that multiple levels do not conflict 1' do - module NestedLevel - module Further - class NamingFive - include Redis::Objects - self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) - self.redis_silence_warnings = true - - def id - 1 - end - - value :redis_value - end - end - end - - obj = NestedLevel::Further::NamingFive.new - obj.class.redis_prefix.should == 'nested_level__further__naming_five' - val = SecureRandom.hex(10) - obj.redis_value = val - obj.redis_value.should == val - obj.redis_value.key.should == 'nested_level__further__naming_five:1:redis_value' - obj.redis_value.redis.should == obj.redis - obj.redis.get('nested_level__further__naming_five:1:redis_value').should == val - end - - it 'verifies that multiple levels do not conflict 2' do - module Nested - module LevelFurtherNaming - class Five - include Redis::Objects - self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) - self.redis_silence_warnings = true - - def id - 1 - end - - value :redis_value - end - end - end - - obj = Nested::LevelFurtherNaming::Five.new - obj.class.redis_prefix.should == 'nested__level_further_naming__five' - val = SecureRandom.hex(10) - obj.redis_value = val - obj.redis_value.should == val - obj.redis_value.key.should == 'nested__level_further_naming__five:1:redis_value' - obj.redis.get('nested__level_further_naming__five:1:redis_value').should == val - end - - it 'verifies that multiple levels do not conflict 3' do - module Nested - module LevelFurther - class NamingFive - include Redis::Objects - self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) - self.redis_silence_warnings = true - - def id - 1 - end - - value :redis_value - end - end - end - - obj = Nested::LevelFurther::NamingFive.new - obj.class.redis_prefix.should == 'nested__level_further__naming_five' - val = SecureRandom.hex(10) - obj.redis_value = val - obj.redis_value.should == val - obj.redis_value.key.should == 'nested__level_further__naming_five:1:redis_value' - obj.redis.get('nested__level_further__naming_five:1:redis_value').should == val - end - - it 'handles dynamically created classes correctly' do - module Nested - class LevelSix - include Redis::Objects - self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) - self.redis_silence_warnings = true - - def id - 1 - end - - value :redis_value - end - end - - obj = Nested::LevelSix.new - obj.class.redis_prefix.should == 'nested__level_six' - val = SecureRandom.hex(10) - obj.redis_value = val - obj.redis_value.should == val - obj.redis_value.key.should == 'nested__level_six:1:redis_value' - obj.redis.get('nested__level_six:1:redis_value').should == val - - DynamicClass = Class.new(Nested::LevelSix) - DynamicClass.value :redis_value2 - obj2 = DynamicClass.new - DynamicClass.redis_prefix.should == 'dynamic_class' - obj2.redis_value.should.be.kind_of(Redis::Value) - obj2.redis_value2.should.be.kind_of(Redis::Value) - obj2.redis_value.key.should == 'dynamic_class:1:redis_value' - obj2.redis_value2.key.should == 'dynamic_class:1:redis_value2' - - end - - it 'handles dynamically created classes correctly in legacy mode' do - module Nested - class LevelSeven - include Redis::Objects - self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) - self.redis_legacy_naming = true - - def id - 1 - end - - value :redis_value - end - end - - obj = Nested::LevelSeven.new - obj.class.redis_prefix.should == 'level_seven' - val = SecureRandom.hex(10) - obj.redis_value = val - obj.redis_value.should == val - obj.redis_value.key.should == 'level_seven:1:redis_value' - obj.redis.get('level_seven:1:redis_value').should == val - - DynamicClass2 = Class.new(Nested::LevelSeven) - DynamicClass2.value :redis_value2 - obj2 = DynamicClass2.new - DynamicClass2.redis_prefix.should == 'dynamic_class2' - obj2.redis_value.should.be.kind_of(Redis::Value) - obj2.redis_value2.should.be.kind_of(Redis::Value) - obj2.redis_value.key.should == 'dynamic_class2:1:redis_value' - obj2.redis_value2.key.should == 'dynamic_class2:1:redis_value2' - end - - it 'prints a warning message if the key name changes' do - module Nested - class LevelNine - include Redis::Objects - self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) - - def id - 1 - end - - value :redis_value - end - end - - captured_output = capture_stderr do - # Does not output anything directly. - obj = Nested::LevelNine.new - val = SecureRandom.hex(10) - obj.redis_value = val - obj.redis_value.should == val - end - - captured_output.should =~ /Warning:/i - end - - it 'supports a method to migrate legacy key names' do - module Nested - class Legacy - include Redis::Objects - self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) - self.redis_legacy_naming = true - - # override this for testing - need two classes as if we imagine an old and new one - # also use the legacy flat prefix that ignores the nested class name - self.redis_prefix = 'modern' - - def initialize(id) - @id = id - end - def id - @id - end - - value :redis_value - counter :redis_counter - hash_key :redis_hash - list :redis_list - set :redis_set - sorted_set :redis_sorted_set - - # global class counters - value :global_value, :global => true - counter :global_counter, :global => true - hash_key :global_hash_key, :global => true - list :global_list, :global => true - set :global_set, :global => true - sorted_set :global_sorted_set, :global => true - - #callable as key - value :global_proc_value, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" } - end - end - - module Nested - class Modern - include Redis::Objects - self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) - - def initialize(id) - @id = id - end - def id - @id - end - - value :redis_value - counter :redis_counter - hash_key :redis_hash - list :redis_list - set :redis_set - sorted_set :redis_sorted_set - - # global class counters - value :global_value, :global => true - counter :global_counter, :global => true - hash_key :global_hash_key, :global => true - list :global_list, :global => true - set :global_set, :global => true - sorted_set :global_sorted_set, :global => true - - #callable as key - value :global_proc_value, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" } - end - end - - # Iterate over them - Nested::Modern.redis_objects.length.should == 13 - Nested::Modern.redis_objects.length.should == Nested::Legacy.redis_objects.length.should - Nested::Legacy.redis_prefix.should == 'modern' - Nested::Modern.redis_prefix.should == 'nested__modern' - - # Create a whole bunch of keys using the legacy names - 30.times do |i| - # warn i.inspect - obj = Nested::Legacy.new(i) - obj.redis_value = i - obj.redis_value.to_i.should == i - obj.redis_counter.increment - obj.redis_hash[:key] = i - obj.redis_list << i - obj.redis_set << i - obj.redis_sorted_set[i] = i - end - - obj = Nested::Legacy.new(99) - obj.global_value = 42 - obj.global_counter.increment - obj.global_counter.increment - obj.global_counter.increment - obj.global_hash_key[:key] = 'value' - obj.global_set << 'a' << 'b' - obj.global_sorted_set[:key] = 2.2 - - Nested::Modern.migrate_redis_legacy_keys - - # Try to access the keys through modern names now - 30.times do |i| - # warn i.inspect - obj = Nested::Modern.new(i) - obj.redis_value.to_i.should == i - obj.redis_counter.to_i.should == 1 - obj.redis_hash[:key].to_i.should == i - obj.redis_list[0].to_i.should == i - obj.redis_set.include?(i).should == true - obj.redis_sorted_set[i].should == i - end - - obj = Nested::Modern.new(99) - obj.global_value.to_i.should == 42 - obj.global_counter.to_i.should == 3 - obj.global_hash_key[:key].should == 'value' - obj.global_set.should.include?('a').should == true - obj.global_set.should.include?('b').should == true - obj.global_sorted_set[:key].should == 2.2 - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3002d8a..3a77d91 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -24,8 +24,9 @@ #require "active_support/xml_mini" require "active_support" +require "active_support/core_ext/integer/time" # needed for 1.second 1.minute etc durations to function require "active_support/testing/time_helpers" -include ActiveSupport::Testing::TimeHelpers +include ActiveSupport::Testing::TimeHelpers # needed by one line in redis_objects_model_spec.rb REDIS_CLASS_NAMES = [:Counter, :HashKey, :List, :Lock, :Set, :SortedSet, :Value]