Module: DataMapper::Sweatshop::Unique
- Included in:
- DataMapper::Sweatshop
- Defined in:
- lib/dm-sweatshop/unique.rb
Defined Under Namespace
Classes: TooManyTriesException
Instance Method Summary collapse
-
#unique(key = nil, &block) ⇒ Object
Yields a value to the block.
Instance Method Details
#unique(key = nil, &block) ⇒ Object
Yields a value to the block. The value is unique for each invocation with the same block. Alternatively, you may provide an explicit key to identify the block.
If a block with no parameter is supplied, unique keeps track of previous invocations, and will continue yielding until a unique value is generated. If a unique value is not generated after @UniqueWorker::MAX_TRIES@, an exception is raised.
ParseTree is required unless an explicit key is provided
(1..3).collect { unique {|x| x }} # => [0, 1, 2]
(1..3).collect { unique {|x| x + 1 }} # => [1, 2, 3]
(1..3).collect { unique {|x| x }} # => [3, 4, 5] # Continued on from above
(1..3).collect { unique(:a) {|x| x }} # => [0, 1, 2] # Explicit key overrides block identity
a = [1, 1, 1, 2, 2, 3]
(1..3).collect { unique { a.shift }} # => [1, 2, 3]
(1..3).collect { unique { 1 }} # raises TooManyTriesException
return
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/dm-sweatshop/unique.rb', line 27 def unique(key = nil, &block) if block.arity < 1 UniqueWorker.unique_map ||= {} key ||= UniqueWorker.key_for(&block) set = UniqueWorker.unique_map[key] || Set.new result = block[] tries = 0 while set.include?(result) result = block[] tries += 1 raise TooManyTriesException.new("Could not generate unique value after #{tries} attempts") if tries >= UniqueWorker::MAX_TRIES end set << result UniqueWorker.unique_map[key] = set else UniqueWorker.count_map ||= Hash.new() { 0 } key ||= UniqueWorker.key_for(&block) result = block[UniqueWorker.count_map[key]] UniqueWorker.count_map[key] += 1 end result end |