Class: ConsistentRandom
- Inherits:
-
Object
- Object
- ConsistentRandom
- Defined in:
- lib/consistent_random.rb,
lib/consistent_random/testing.rb,
lib/consistent_random/active_job.rb,
lib/consistent_random/rack_middleware.rb,
lib/consistent_random/sidekiq_middleware.rb,
lib/consistent_random/sidekiq_client_middleware.rb
Defined Under Namespace
Modules: ActiveJob Classes: RackMiddleware, SidekiqClientMiddleware, SidekiqMiddleware
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Class Method Summary collapse
-
.current_seed ⇒ String?
Get the current seed used to generate random numbers.
-
.scope(seed = nil) { ... } ⇒ Object
Define a scope where consistent random values will be generated.
- .testing ⇒ Object
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
True if the other object is a ConsistentRandom that returns the same random number generator.
-
#bytes(size) ⇒ String
Generate a random array of bytes.
-
#initialize(name) ⇒ ConsistentRandom
constructor
A new instance of ConsistentRandom.
-
#rand(max = nil) ⇒ Numeric
Generate a random number.
-
#random ⇒ Random
Generate a random number generator for the given name.
-
#seed ⇒ Integer
Generate a seed that can be used to generate random numbers.
Constructor Details
#initialize(name) ⇒ ConsistentRandom
Returns a new instance of ConsistentRandom.
66 67 68 |
# File 'lib/consistent_random.rb', line 66 def initialize(name) @name = (name.is_a?(String) ? name.dup : name.to_s).freeze end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
63 64 65 |
# File 'lib/consistent_random.rb', line 63 def name @name end |
Class Method Details
.current_seed ⇒ String?
Get the current seed used to generate random numbers. This will return nil if called outside of a scope. The value can be passed to a new scope to generate the same random values in another thread or fiber.
54 55 56 |
# File 'lib/consistent_random.rb', line 54 def current_seed Thread.current[:consistent_random_seed] end |
.scope(seed = nil) { ... } ⇒ Object
Define a scope where consistent random values will be generated.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/consistent_random.rb', line 27 def scope(seed = nil) existing_seed = Thread.current[:consistent_random_seed] seed_value = case seed when nil existing_seed || SecureRandom.hex when String, Symbol, Integer seed.to_s when Array seed.join("\x1C") else raise ArgumentError, "Invalid seed value: #{seed.inspect}" end begin Thread.current[:consistent_random_seed] = seed_value yield ensure Thread.current[:consistent_random_seed] = existing_seed end end |
Instance Method Details
#==(other) ⇒ Boolean
Returns true if the other object is a ConsistentRandom that returns the same random number generator. If called outside of a scope, then it will always return false. The functionality is designed to be similar to the same behavior as Random.
123 124 125 |
# File 'lib/consistent_random.rb', line 123 def ==(other) other.is_a?(self.class) && other.seed == seed end |
#bytes(size) ⇒ String
Generate a random array of bytes. The same number will be generated within a scope block. This method works the same as Random#bytes.
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/consistent_random.rb', line 96 def bytes(size) test_bytes = Testing.current&.bytes_for(name) chunk_size = (test_bytes ? test_bytes.length : 20) bytes = [] (size / chunk_size.to_f).ceil.times do |i| bytes << (test_bytes || seed_hash("#{name}#{i}").to_s) end bytes.join[0, size] end |
#rand(max = nil) ⇒ Numeric
Generate a random number. The same number will be generated within a scope block. This method works the same as Kernel#rand. It will generate a consistent value even across Ruby versions and platforms.
79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/consistent_random.rb', line 79 def rand(max = nil) value = Testing.current&.rand_for(name) || (seed >> 11) / FLOAT_DIVISOR case max when nil value when Numeric (value * max.to_i).to_i when Range cap_to_range(value, max) end end |
#random ⇒ Random
Generate a random number generator for the given name. The generator will always have the same seed within a scope.
This value is dependent on the Ruby Random class and may not generate consistent values across Ruby versions and platforms.
134 135 136 |
# File 'lib/consistent_random.rb', line 134 def random Random.new(seed) end |
#seed ⇒ Integer
Generate a seed that can be used to generate random numbers. This seed will be return a consistent value when called within a scope.
111 112 113 114 115 116 117 |
# File 'lib/consistent_random.rb', line 111 def seed test_seed = Testing.current&.seed_for(name) return test_seed if test_seed hash = seed_hash(name) hash.byteslice(0, 8).unpack1("Q>") end |