qfill 0.0.3 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/style.yml +37 -0
- data/.github/workflows/test.yml +55 -0
- data/.rspec +3 -2
- data/.rubocop.yml +26 -0
- data/.rubocop_todo.yml +163 -0
- data/.simplecov +6 -0
- data/CODE_OF_CONDUCT.md +133 -0
- data/Gemfile +31 -0
- data/Guardfile +12 -0
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +2 -2
- data/Rakefile +24 -1
- data/lib/qfill/errors/invalid_index.rb +8 -0
- data/lib/qfill/filter.rb +5 -3
- data/lib/qfill/list.rb +4 -2
- data/lib/qfill/list_set.rb +17 -7
- data/lib/qfill/manager.rb +90 -61
- data/lib/qfill/origin.rb +4 -3
- data/lib/qfill/popper.rb +31 -26
- data/lib/qfill/pusher.rb +34 -23
- data/lib/qfill/result.rb +78 -40
- data/lib/qfill/strategy/base.rb +65 -0
- data/lib/qfill/strategy/drain_to_empty.rb +73 -0
- data/lib/qfill/strategy/drain_to_limit.rb +46 -0
- data/lib/qfill/strategy/sample.rb +42 -0
- data/lib/qfill/strategy/time_slice.rb +105 -0
- data/lib/qfill/strategy.rb +13 -0
- data/lib/qfill/version.rb +3 -1
- data/lib/qfill.rb +13 -10
- data/maintenance-branch +1 -0
- data/qfill.gemspec +15 -13
- data/spec/qfill/filter_spec.rb +35 -26
- data/spec/qfill/list_set_spec.rb +28 -23
- data/spec/qfill/list_spec.rb +35 -27
- data/spec/qfill/manager_spec.rb +715 -284
- data/spec/qfill/origin_spec.rb +45 -35
- data/spec/qfill/popper_spec.rb +36 -30
- data/spec/qfill/pusher_spec.rb +32 -26
- data/spec/qfill/result_spec.rb +49 -38
- data/spec/qfill_spec.rb +6 -5
- data/spec/spec_helper.rb +11 -37
- data/spec/support/helper.rb +13 -0
- data/spec/support/random_object.rb +30 -0
- metadata +52 -23
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qfill
|
4
|
+
module Strategy
|
5
|
+
class DrainToEmpty < Qfill::Strategy::Base
|
6
|
+
NAME = :drain_to_empty
|
7
|
+
|
8
|
+
def on_fill!
|
9
|
+
preferred_potential_ratio = 0
|
10
|
+
preferred_potential = 0
|
11
|
+
result.list_ratios.each do |list_name, list_ratio|
|
12
|
+
poppy = result.preferred.select { |x| x == list_name }
|
13
|
+
next unless poppy
|
14
|
+
|
15
|
+
preferred_potential_ratio += list_ratio
|
16
|
+
num = popper[list_name].elements.length
|
17
|
+
preferred_potential += num
|
18
|
+
result.max_tracker[list_name] = num
|
19
|
+
end
|
20
|
+
result.preferred_potential = preferred_potential
|
21
|
+
result.preferred_potential_ratio = preferred_potential_ratio
|
22
|
+
end
|
23
|
+
|
24
|
+
def result_max!
|
25
|
+
result.max = if result.preferred_potential_ratio.positive?
|
26
|
+
[
|
27
|
+
(result.preferred_potential / result.preferred_potential_ratio),
|
28
|
+
primary_list_total,
|
29
|
+
remaining
|
30
|
+
].min
|
31
|
+
else
|
32
|
+
[
|
33
|
+
primary_list_total,
|
34
|
+
remaining
|
35
|
+
].min
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def fill_up_to_ratio!
|
40
|
+
popper.primary.each do |queue|
|
41
|
+
array_to_push = popper.next_objects!(queue.name, [result.max, remaining].min)
|
42
|
+
self.added = result.push(array_to_push, queue.name)
|
43
|
+
popper.current_index = popper.index_of(queue.name)
|
44
|
+
bump!
|
45
|
+
puts "[fill_up_to_ratio!]#{self}[Q:#{queue.name}][added:#{added}]" if Qfill::VERBOSE
|
46
|
+
break if is_full?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def fill_according_to_list_ratios!
|
51
|
+
# Are there any elements in preferred queues that we should add?
|
52
|
+
return unless result.preferred_potential.positive?
|
53
|
+
|
54
|
+
# Setup a ratio modifier for the non-preferred queues
|
55
|
+
result.list_ratios.each do |list_name, list_ratio|
|
56
|
+
max_from_list = if result.max_tracker[list_name]
|
57
|
+
[result.max_tracker[list_name], remaining].min
|
58
|
+
else
|
59
|
+
Qfill::Result.get_limit_from_max_and_ratio(
|
60
|
+
result.max, list_ratio, remaining
|
61
|
+
)
|
62
|
+
end
|
63
|
+
array_to_push = popper.next_objects!(list_name, max_from_list)
|
64
|
+
self.added = result.push(array_to_push, list_name)
|
65
|
+
popper.current_index = popper.index_of(list_name)
|
66
|
+
bump!
|
67
|
+
puts "[fill_according_to_list_ratios!]#{self}[#{list_name}][added:#{added}]" if Qfill::VERBOSE
|
68
|
+
break if is_full?
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qfill
|
4
|
+
module Strategy
|
5
|
+
class DrainToLimit < Qfill::Strategy::Base
|
6
|
+
NAME = :drain_to_limit
|
7
|
+
|
8
|
+
def on_fill!
|
9
|
+
# NOOP
|
10
|
+
end
|
11
|
+
|
12
|
+
def result_max!
|
13
|
+
result.max = Qfill::Result.get_limit_from_max_and_ratio(primary_list_total, result.ratio, remaining)
|
14
|
+
end
|
15
|
+
|
16
|
+
def fill_up_to_ratio!
|
17
|
+
num_primary = popper.primary.length
|
18
|
+
ratio = 1.0 / num_primary # 1 divided by the number of queues
|
19
|
+
max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, ratio, remaining)
|
20
|
+
popper.primary.each_with_index do |queue, idx|
|
21
|
+
# Are there leftovers that will be missed by a straight ratio'd iteration?
|
22
|
+
mod = result.max % num_primary
|
23
|
+
max_from_list += (mod / num_primary).ceil if idx.zero? && mod.positive?
|
24
|
+
array_to_push = popper.next_objects!(queue.name, [max_from_list, remaining].min)
|
25
|
+
self.added = result.push(array_to_push, queue.name)
|
26
|
+
popper.current_index = popper.index_of(queue.name)
|
27
|
+
puts "[fill_up_to_ratio!]#{self}[Q:#{queue.name}][added:#{added}]" if Qfill::VERBOSE
|
28
|
+
bump!
|
29
|
+
break if is_full?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def fill_according_to_list_ratios!
|
34
|
+
result.list_ratios.each do |list_name, list_ratio|
|
35
|
+
max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, list_ratio, remaining)
|
36
|
+
array_to_push = popper.next_objects!(list_name, max_from_list)
|
37
|
+
self.added = result.push(array_to_push, list_name)
|
38
|
+
popper.current_index = popper.index_of(list_name)
|
39
|
+
puts "[fill_according_to_list_ratios!]#{self}[#{list_name}][added:#{added}]" if Qfill::VERBOSE
|
40
|
+
bump!
|
41
|
+
break if is_full?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qfill
|
4
|
+
module Strategy
|
5
|
+
class Sample < Qfill::Strategy::Base
|
6
|
+
NAME = :sample
|
7
|
+
|
8
|
+
def on_fill!
|
9
|
+
# NOOP
|
10
|
+
end
|
11
|
+
|
12
|
+
def result_max!
|
13
|
+
result.max = Qfill::Result.get_limit_from_max_and_ratio(primary_list_total, result.ratio, remaining)
|
14
|
+
end
|
15
|
+
|
16
|
+
def fill_up_to_ratio!
|
17
|
+
ratio = 1.0 / popper.primary.length # 1 divided by the number of queues
|
18
|
+
max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, ratio, remaining)
|
19
|
+
while !is_full? && !result.is_full? && !popper.totally_empty? && (origin_list = popper.current_list)
|
20
|
+
array_to_push = popper.next_objects!(origin_list.name, [max_from_list, remaining].min)
|
21
|
+
self.added = result.push(array_to_push, origin_list.name)
|
22
|
+
bump!
|
23
|
+
puts "[fill_up_to_ratio!]#{self}[Added:#{added}][Max List:#{max_from_list}][ratio:#{ratio}][added:#{added}]" if Qfill::VERBOSE
|
24
|
+
popper.set_next_as_current!
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def fill_according_to_list_ratios!
|
29
|
+
# puts "#{!is_full?} && #{result.fill_count} >= #{result.max} && #{!self.popper.totally_empty?} && #{(list_ratio_tuple = result.current_list_ratio)}"
|
30
|
+
while !is_full? && !result.is_full? && !popper.totally_empty? && (list_ratio_tuple = result.current_list_ratio)
|
31
|
+
max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, list_ratio_tuple[1], remaining)
|
32
|
+
array_to_push = popper.next_objects!(list_ratio_tuple[0], max_from_list)
|
33
|
+
self.added = result.push(array_to_push, list_ratio_tuple[0])
|
34
|
+
bump!
|
35
|
+
puts "[fill_according_to_list_ratios!]#{self}[#{list_ratio_tuple[0]}][added:#{added}]" if Qfill::VERBOSE
|
36
|
+
result.set_next_as_current!
|
37
|
+
break if is_full?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qfill
|
4
|
+
module Strategy
|
5
|
+
# Qfill::Manager.new(
|
6
|
+
# :popper => popper,
|
7
|
+
# :strategy_options => {
|
8
|
+
# :window_size => 20,
|
9
|
+
# :window_units => "minutes" # "days", "hours", "minutes", "seconds",
|
10
|
+
# # NOTE: pane_size/units can't be larger than the window_size/units
|
11
|
+
# :pane_size => 2
|
12
|
+
# :pane_units => "seconds" # "days", "hours", "minutes", "seconds",
|
13
|
+
# },
|
14
|
+
# )
|
15
|
+
class TimeSlice < Qfill::Strategy::Sample
|
16
|
+
NAME = :time_slice
|
17
|
+
|
18
|
+
def on_fill!
|
19
|
+
# NOOP
|
20
|
+
end
|
21
|
+
|
22
|
+
CONVERSIONS = {
|
23
|
+
%w[seconds seconds] => 1,
|
24
|
+
%w[seconds minutes] => 60,
|
25
|
+
%w[seconds hours] => 60 * 60,
|
26
|
+
%w[seconds days] => 60 * 60 * 24,
|
27
|
+
%w[minutes minutes] => 1,
|
28
|
+
%w[minutes hours] => 60,
|
29
|
+
%w[minutes days] => 60 * 24,
|
30
|
+
%w[hours hours] => 1,
|
31
|
+
%w[hours days] => 24,
|
32
|
+
%w[days days] => 1
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
# If window_units == "minutes" and pane_units == "seconds", and
|
36
|
+
# window_size == 20 and pane_size == 2
|
37
|
+
# Then there would be (20 * CONVERSIONS[[pane_units, window_units]]) / pane_size
|
38
|
+
# i.e. (20 * 60) / 2
|
39
|
+
# i.e. 600 individual panes in the (time) window, where each pane is a "result"
|
40
|
+
def default_pusher
|
41
|
+
ratio = 1 / num_panes.to_f
|
42
|
+
array = Range.new(1, num_panes).each_with_object([]) do |pane_num, arr|
|
43
|
+
arr << { name: pane_num.to_s, ratio: ratio }
|
44
|
+
end
|
45
|
+
Qfill::Pusher.from_array_of_hashes(array)
|
46
|
+
end
|
47
|
+
|
48
|
+
def window_size
|
49
|
+
strategy_options[:window_size]
|
50
|
+
end
|
51
|
+
|
52
|
+
def window_units
|
53
|
+
strategy_options[:window_units]
|
54
|
+
end
|
55
|
+
|
56
|
+
def pane_size
|
57
|
+
strategy_options[:pane_size]
|
58
|
+
end
|
59
|
+
|
60
|
+
def pane_units
|
61
|
+
strategy_options[:pane_units]
|
62
|
+
end
|
63
|
+
|
64
|
+
def conversion
|
65
|
+
conversion_idx = [pane_units, window_units]
|
66
|
+
conv = CONVERSIONS[conversion_idx]
|
67
|
+
raise ArgumentError, "pane_units: #{pane_units} must not be larger than window_units: #{window_units}" unless conv
|
68
|
+
|
69
|
+
conv
|
70
|
+
end
|
71
|
+
|
72
|
+
def num_panes
|
73
|
+
((window_size * conversion) / pane_size)
|
74
|
+
end
|
75
|
+
|
76
|
+
def result_max!
|
77
|
+
result.max = Qfill::Result.get_limit_from_max_and_ratio(primary_list_total, result.ratio, remaining)
|
78
|
+
end
|
79
|
+
|
80
|
+
def fill_up_to_ratio!
|
81
|
+
ratio = 1.0 / popper.primary.length # 1 divided by the number of queues
|
82
|
+
max_from_list = Qfill::Result.get_limit_from_max_and_ratio(result.max, ratio, remaining)
|
83
|
+
while !is_full? && (take = [max_from_list, remaining].min) && (!result.is_full? || take == 1) && !popper.totally_empty? && (origin_list = popper.current_list)
|
84
|
+
array_to_push = popper.next_objects!(origin_list.name, take)
|
85
|
+
self.added = result.push(array_to_push, origin_list.name)
|
86
|
+
bump!
|
87
|
+
puts "[fill_up_to_ratio!]#{self}[Added:#{added}][Max List:#{max_from_list}][ratio:#{ratio}][take:#{take}]" if Qfill::VERBOSE
|
88
|
+
popper.set_next_as_current!
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def fill_according_to_list_ratios!
|
93
|
+
# puts "#{!is_full?} && #{result.fill_count} >= #{result.max} && #{!self.popper.totally_empty?} && #{result.current_list_ratio}"
|
94
|
+
while !is_full? && !popper.totally_empty? && (list_ratio_tuple = result.current_list_ratio) && (take = Qfill::Result.get_limit_from_max_and_ratio(result.max, list_ratio_tuple[1], remaining)) && (!result.is_full? || take == 1)
|
95
|
+
array_to_push = popper.next_objects!(list_ratio_tuple[0], take)
|
96
|
+
self.added = result.push(array_to_push, list_ratio_tuple[0])
|
97
|
+
bump!
|
98
|
+
puts "[fill_according_to_list_ratios!]#{self}[#{list_ratio_tuple[0]}][added:#{added}]" if Qfill::VERBOSE
|
99
|
+
result.set_next_as_current!
|
100
|
+
break if is_full?
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Qfill
|
4
|
+
# A Strategy defines how to process the elements in the queues
|
5
|
+
module Strategy
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'qfill/strategy/base'
|
10
|
+
require 'qfill/strategy/drain_to_empty'
|
11
|
+
require 'qfill/strategy/drain_to_limit'
|
12
|
+
require 'qfill/strategy/sample'
|
13
|
+
require 'qfill/strategy/time_slice'
|
data/lib/qfill/version.rb
CHANGED
data/lib/qfill.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'qfill/version'
|
4
|
+
require 'qfill/filter'
|
5
|
+
require 'qfill/list'
|
6
|
+
require 'qfill/list_set'
|
7
|
+
require 'qfill/origin'
|
8
|
+
require 'qfill/popper'
|
9
|
+
require 'qfill/pusher'
|
10
|
+
require 'qfill/manager'
|
11
|
+
require 'qfill/result'
|
12
|
+
require 'qfill/strategy'
|
10
13
|
|
11
14
|
module Qfill
|
12
|
-
|
15
|
+
VERBOSE = ENV['QFILL_VERBOSE'] == 'true'
|
13
16
|
end
|
data/maintenance-branch
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
master
|
data/qfill.gemspec
CHANGED
@@ -1,15 +1,16 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'qfill/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |gem|
|
7
|
-
gem.name =
|
8
|
+
gem.name = 'qfill'
|
8
9
|
gem.version = Qfill::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
11
|
-
gem.description =
|
12
|
-
gem.summary =
|
10
|
+
gem.authors = ['Peter Boling']
|
11
|
+
gem.email = ['peter.boling@gmail.com']
|
12
|
+
gem.description = 'Advanced Queue Transformation'
|
13
|
+
gem.summary = 'You have a set of arrays that need to be turned into a different set of arrays
|
13
14
|
according to a potentially non-uniform set of rules.
|
14
15
|
|
15
16
|
Now you can easily turn this:
|
@@ -24,13 +25,14 @@ result_b # => [3,5,7,9]
|
|
24
25
|
result_c # => [4,6,8]
|
25
26
|
|
26
27
|
by specifying filters for handling each transformation.
|
27
|
-
|
28
|
-
gem.homepage =
|
28
|
+
'
|
29
|
+
gem.homepage = 'https://github.com/pboling/qfill'
|
29
30
|
|
30
|
-
gem.files = `git ls-files`.split(
|
31
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
31
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
32
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
32
33
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
33
|
-
gem.require_paths = [
|
34
|
+
gem.require_paths = ['lib']
|
34
35
|
|
35
|
-
gem.add_development_dependency '
|
36
|
+
gem.add_development_dependency 'rake', '~> 13'
|
37
|
+
gem.add_development_dependency 'rspec', '~> 3'
|
36
38
|
end
|
data/spec/qfill/filter_spec.rb
CHANGED
@@ -1,43 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
describe Qfill::Filter do
|
3
|
-
|
4
|
-
context
|
5
|
-
before
|
6
|
-
@lambda = ->
|
5
|
+
describe '#new' do
|
6
|
+
context 'with processor' do
|
7
|
+
before do
|
8
|
+
@lambda = ->(object) { !object.nil? }
|
7
9
|
end
|
8
|
-
|
9
|
-
|
10
|
+
|
11
|
+
it 'instantiates with processor' do
|
12
|
+
expect(described_class.new(@lambda)).to be_a(described_class)
|
10
13
|
end
|
11
14
|
end
|
12
15
|
|
13
|
-
context
|
14
|
-
before
|
15
|
-
@lambda = ->
|
16
|
-
@arguments = [
|
16
|
+
context 'with processor and arguments' do
|
17
|
+
before do
|
18
|
+
@lambda = ->(object, first, second) { !object.nil? && first == first && second == 'second' }
|
19
|
+
@arguments = %w[first second]
|
17
20
|
end
|
18
|
-
|
19
|
-
|
21
|
+
|
22
|
+
it 'instantiates with processor' do
|
23
|
+
expect(described_class.new(@lambda, *@arguments)).to be_a(described_class)
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
|
-
|
25
|
-
before
|
26
|
-
@lambda = ->
|
27
|
-
@arguments = [
|
28
|
-
@filter =
|
28
|
+
describe '#run' do
|
29
|
+
before do
|
30
|
+
@lambda = ->(object, first, second) { !object.nil? && first == first && second == 'second' }
|
31
|
+
@arguments = %w[first second]
|
32
|
+
@filter = described_class.new(@lambda, *@arguments)
|
29
33
|
end
|
30
|
-
|
31
|
-
|
34
|
+
|
35
|
+
it 'returns the correct result' do
|
36
|
+
expect(@filter.run('not nil')).to eq(true)
|
32
37
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
@
|
37
|
-
|
38
|
+
|
39
|
+
context 'with extra arguments' do
|
40
|
+
before do
|
41
|
+
@lambda = lambda { |object, _special_arg1, special_arg2, first, second, third|
|
42
|
+
!object.nil? && first == first && second == 'second' && special_arg1 = 'this' && special_arg2 == 'thing' && third == 'third'
|
43
|
+
}
|
44
|
+
@arguments = %w[first second third]
|
45
|
+
@filter = described_class.new(@lambda, *@arguments)
|
38
46
|
end
|
39
|
-
|
40
|
-
|
47
|
+
|
48
|
+
it 'properlies use arity' do
|
49
|
+
expect(@filter.run('not nil', 'this', 'thing')).to eq(true)
|
41
50
|
end
|
42
51
|
end
|
43
52
|
end
|
data/spec/qfill/list_set_spec.rb
CHANGED
@@ -1,36 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
describe Qfill::ListSet do
|
3
|
-
|
4
|
-
context
|
5
|
-
it
|
6
|
-
expect {
|
5
|
+
describe '#new' do
|
6
|
+
context 'with no arguments' do
|
7
|
+
it 'raises ArgumentError' do
|
8
|
+
expect { described_class.new }.to raise_error(ArgumentError)
|
7
9
|
end
|
8
10
|
end
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
|
12
|
+
context 'with arguments' do
|
13
|
+
before do
|
14
|
+
@filter = Qfill::Filter.new(->(object) { object.is_a?(Numeric) })
|
12
15
|
@origin_queues = [
|
13
16
|
Qfill::List.new(
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
name: 'High List',
|
18
|
+
elements: [1, 2, 3, 'c'],
|
19
|
+
filter: @filter
|
20
|
+
),
|
21
|
+
Qfill::List.new(name: 'Medium List',
|
22
|
+
elements: ['e', 'f', 4, 5],
|
23
|
+
filter: @filter),
|
24
|
+
Qfill::List.new(name: 'Low List',
|
25
|
+
elements: [7, 8, 'd'],
|
26
|
+
filter: @filter)
|
23
27
|
]
|
24
28
|
end
|
25
|
-
|
26
|
-
|
29
|
+
|
30
|
+
it 'does not raise any errors' do
|
31
|
+
expect { described_class.new(*@origin_queues) }.not_to raise_error
|
27
32
|
end
|
28
|
-
|
29
|
-
|
30
|
-
popper
|
31
|
-
popper.queues.
|
33
|
+
|
34
|
+
it 'instantiates with name' do
|
35
|
+
popper = described_class.new(*@origin_queues)
|
36
|
+
expect(popper.queues.first.elements).to eq([1, 2, 3, 'c'])
|
37
|
+
expect(popper.queues.last.elements).to eq([7, 8, 'd'])
|
32
38
|
end
|
33
39
|
end
|
34
40
|
end
|
35
|
-
|
36
41
|
end
|
data/spec/qfill/list_spec.rb
CHANGED
@@ -1,44 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
describe Qfill::List do
|
3
|
-
|
4
|
-
context
|
5
|
-
it
|
6
|
-
expect {
|
5
|
+
describe '#new' do
|
6
|
+
context 'with no arguments' do
|
7
|
+
it 'raises ArgumentError' do
|
8
|
+
expect { described_class.new }.to raise_error(ArgumentError)
|
7
9
|
end
|
8
10
|
end
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
|
12
|
+
context 'with name' do
|
13
|
+
before do
|
14
|
+
@arguments = { name: 'High List' }
|
12
15
|
end
|
13
|
-
|
14
|
-
|
16
|
+
|
17
|
+
it 'does not raise any errors' do
|
18
|
+
expect { described_class.new(@arguments) }.not_to raise_error
|
15
19
|
end
|
16
|
-
|
17
|
-
|
20
|
+
|
21
|
+
it 'instantiates with name' do
|
22
|
+
expect(described_class.new(@arguments).name).to eq('High List')
|
18
23
|
end
|
19
24
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
|
26
|
+
context 'with elements' do
|
27
|
+
before do
|
28
|
+
@arguments = { name: 'High List',
|
29
|
+
elements: [1, 2] }
|
24
30
|
end
|
25
|
-
|
26
|
-
|
31
|
+
|
32
|
+
it 'instantiates with elements' do
|
33
|
+
expect(described_class.new(@arguments).elements).to eq([1, 2])
|
27
34
|
end
|
28
35
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
36
|
+
|
37
|
+
context 'with filter' do
|
38
|
+
before do
|
39
|
+
lambda = ->(object) { !object.nil? }
|
32
40
|
@filter = Qfill::Filter.new(lambda)
|
33
|
-
@arguments = { :
|
34
|
-
:
|
35
|
-
:
|
41
|
+
@arguments = { name: 'High List',
|
42
|
+
elements: [1, 2],
|
43
|
+
filter: @filter }
|
36
44
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
45
|
+
|
46
|
+
it 'instantiates with processor' do
|
47
|
+
expect(described_class.new(@arguments).filter).to be_a(Qfill::Filter)
|
48
|
+
expect(described_class.new(@arguments).filter).to eq(@filter)
|
40
49
|
end
|
41
50
|
end
|
42
51
|
end
|
43
|
-
|
44
52
|
end
|