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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.github/dependabot.yml +8 -0
  3. data/.github/workflows/style.yml +37 -0
  4. data/.github/workflows/test.yml +55 -0
  5. data/.rspec +3 -2
  6. data/.rubocop.yml +26 -0
  7. data/.rubocop_todo.yml +163 -0
  8. data/.simplecov +6 -0
  9. data/CODE_OF_CONDUCT.md +133 -0
  10. data/Gemfile +31 -0
  11. data/Guardfile +12 -0
  12. data/{LICENSE.txt → LICENSE} +1 -1
  13. data/README.md +2 -2
  14. data/Rakefile +24 -1
  15. data/lib/qfill/errors/invalid_index.rb +8 -0
  16. data/lib/qfill/filter.rb +5 -3
  17. data/lib/qfill/list.rb +4 -2
  18. data/lib/qfill/list_set.rb +17 -7
  19. data/lib/qfill/manager.rb +90 -61
  20. data/lib/qfill/origin.rb +4 -3
  21. data/lib/qfill/popper.rb +31 -26
  22. data/lib/qfill/pusher.rb +34 -23
  23. data/lib/qfill/result.rb +78 -40
  24. data/lib/qfill/strategy/base.rb +65 -0
  25. data/lib/qfill/strategy/drain_to_empty.rb +73 -0
  26. data/lib/qfill/strategy/drain_to_limit.rb +46 -0
  27. data/lib/qfill/strategy/sample.rb +42 -0
  28. data/lib/qfill/strategy/time_slice.rb +105 -0
  29. data/lib/qfill/strategy.rb +13 -0
  30. data/lib/qfill/version.rb +3 -1
  31. data/lib/qfill.rb +13 -10
  32. data/maintenance-branch +1 -0
  33. data/qfill.gemspec +15 -13
  34. data/spec/qfill/filter_spec.rb +35 -26
  35. data/spec/qfill/list_set_spec.rb +28 -23
  36. data/spec/qfill/list_spec.rb +35 -27
  37. data/spec/qfill/manager_spec.rb +715 -284
  38. data/spec/qfill/origin_spec.rb +45 -35
  39. data/spec/qfill/popper_spec.rb +36 -30
  40. data/spec/qfill/pusher_spec.rb +32 -26
  41. data/spec/qfill/result_spec.rb +49 -38
  42. data/spec/qfill_spec.rb +6 -5
  43. data/spec/spec_helper.rb +11 -37
  44. data/spec/support/helper.rb +13 -0
  45. data/spec/support/random_object.rb +30 -0
  46. metadata +52 -23
@@ -1,55 +1,65 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  describe Qfill::Origin do
3
- context "#new" do
4
- context "with no arguments" do
5
- it "should raise ArgumentError" do
6
- expect { Qfill::Origin.new() }.to raise_error(ArgumentError)
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
- context "with name" do
10
- before :each do
11
- @arguments = { :name => "High List" }
11
+
12
+ context 'with name' do
13
+ before do
14
+ @arguments = { name: 'High List' }
12
15
  end
13
- it "should not raise any errors" do
14
- expect { Qfill::Origin.new(@arguments) }.to_not raise_error
16
+
17
+ it 'does not raise any errors' do
18
+ expect { described_class.new(@arguments) }.not_to raise_error
15
19
  end
16
- it "should instantiate with name" do
17
- Qfill::Origin.new(@arguments).name.should == 'High List'
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
- context "with elements" do
21
- before :each do
22
- @arguments = { :name => "High List",
23
- :elements => [1,2] }
25
+
26
+ context 'with elements' do
27
+ before do
28
+ @arguments = { name: 'High List',
29
+ elements: [1, 2] }
24
30
  end
25
- it "should instantiate with elements" do
26
- Qfill::Origin.new(@arguments).elements.should == [1,2]
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
- context "with backfill" do
30
- before :each do
31
- @arguments = { :name => "High List",
32
- :elements => [1, 2],
33
- :backfill => "Medium List" }
36
+
37
+ context 'with backfill' do
38
+ before do
39
+ @arguments = { name: 'High List',
40
+ elements: [1, 2],
41
+ backfill: 'Medium List' }
34
42
  end
35
- it "should instantiate with elements" do
36
- Qfill::Origin.new(@arguments).backfill.should == 'Medium List'
43
+
44
+ it 'instantiates with elements' do
45
+ expect(described_class.new(@arguments).backfill).to eq('Medium List')
37
46
  end
38
47
  end
39
- context "with filter" do
40
- before :each do
41
- lambda = -> (object) { !object.nil? }
48
+
49
+ context 'with filter' do
50
+ before do
51
+ lambda = ->(object) { !object.nil? }
42
52
  @filter = Qfill::Filter.new(lambda)
43
- @arguments = { :name => "High List",
44
- :elements => [1, 2],
45
- :backfill => "Medium List",
46
- :filter => @filter }
53
+ @arguments = { name: 'High List',
54
+ elements: [1, 2],
55
+ backfill: 'Medium List',
56
+ filter: @filter }
47
57
  end
48
- it "should instantiate with processor" do
49
- Qfill::Origin.new(@arguments).filter.should be_a(Qfill::Filter)
50
- Qfill::Origin.new(@arguments).filter.should == @filter
58
+
59
+ it 'instantiates with processor' do
60
+ expect(described_class.new(@arguments).filter).to be_a(Qfill::Filter)
61
+ expect(described_class.new(@arguments).filter).to eq(@filter)
51
62
  end
52
63
  end
53
64
  end
54
-
55
65
  end
@@ -1,44 +1,50 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  describe Qfill::Popper do
3
- context "#new" do
4
- context "with no arguments" do
5
- it "should raise ArgumentError" do
6
- expect { Qfill::Popper.new() }.to raise_error(ArgumentError)
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
- context "with arguments" do
10
- before :each do
11
- @filter = Qfill::Filter.new( -> (object) { object.is_a?(Numeric)} )
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::Origin.new(
14
- :name => "High List",
15
- :elements => [1, 2, 3, 'c'],
16
- :backfill => "Medium List",
17
- :filter => @filter),
18
- Qfill::Origin.new( :name => "Medium List",
19
- :elements => ['e', 'f', 4, 5],
20
- :backfill => "Low List",
21
- :filter => @filter),
22
- Qfill::Origin.new( :name => "Low List",
23
- :elements => [7, 8, 'd'],
24
- :backfill => nil,
25
- :filter => @filter)
17
+ name: 'High List',
18
+ elements: [1, 2, 3, 'c'],
19
+ backfill: 'Medium List',
20
+ filter: @filter
21
+ ),
22
+ Qfill::Origin.new(name: 'Medium List',
23
+ elements: ['e', 'f', 4, 5],
24
+ backfill: 'Low List',
25
+ filter: @filter),
26
+ Qfill::Origin.new(name: 'Low List',
27
+ elements: [7, 8, 'd'],
28
+ backfill: nil,
29
+ filter: @filter)
26
30
  ]
27
31
  end
28
- it "should not raise any errors" do
29
- expect { Qfill::Popper.new(*@origin_queues) }.to_not raise_error
32
+
33
+ it 'does not raise any errors' do
34
+ expect { described_class.new(*@origin_queues) }.not_to raise_error
30
35
  end
31
- it "should instantiate with name" do
32
- popper = Qfill::Popper.new(*@origin_queues)
33
- popper.queues.first.name.should == "High List"
34
- popper.queues.last.name.should == "Low List"
36
+
37
+ it 'instantiates with name' do
38
+ popper = described_class.new(*@origin_queues)
39
+ expect(popper.queues.first.name).to eq('High List')
40
+ expect(popper.queues.last.name).to eq('Low List')
35
41
  end
36
- it "should instantiate with elements" do
37
- popper = Qfill::Popper.new(*@origin_queues)
38
- popper.queues.first.elements.should == [1,2,3,'c']
39
- popper.queues.last.elements.should == [7,8,'d']
42
+
43
+ it 'instantiates with elements' do
44
+ popper = described_class.new(*@origin_queues)
45
+ expect(popper.queues.first.elements).to eq([1, 2, 3, 'c'])
46
+ expect(popper.queues.last.elements).to eq([7, 8, 'd'])
40
47
  end
41
48
  end
42
49
  end
43
-
44
50
  end
@@ -1,38 +1,44 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  describe Qfill::Pusher do
3
- context "#new" do
4
- context "with no arguments" do
5
- it "should raise ArgumentError" do
6
- expect { Qfill::Pusher.new() }.to raise_error(ArgumentError)
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
- context "with arguments" do
10
- before :each do
11
- @filter = Qfill::Filter.new( -> (object) { object.is_a?(Numeric)} )
11
+
12
+ context 'with arguments' do
13
+ before do
14
+ @filter = Qfill::Filter.new(->(object) { object.is_a?(Numeric) })
12
15
  @origin_queues = [
13
- Qfill::Result.new({ :name => "Top Results",
14
- :ratio => 0.4,
15
- :list_ratios => {
16
- "High Price" => 0.2,
17
- "Medium Price" => 0.3,
18
- "Low Price" => 0.5 } }),
19
- Qfill::Result.new( { :name => "Page Results",
20
- :ratio => 0.6,
21
- :list_ratios => {
22
- "High Price" => 0.5,
23
- "Medium Price" => 0.3,
24
- "Low Price" => 0.2 } })
16
+ Qfill::Result.new({ name: 'Top Results',
17
+ ratio: 0.4,
18
+ list_ratios: {
19
+ 'High Price' => 0.2,
20
+ 'Medium Price' => 0.3,
21
+ 'Low Price' => 0.5
22
+ } }),
23
+ Qfill::Result.new({ name: 'Page Results',
24
+ ratio: 0.6,
25
+ list_ratios: {
26
+ 'High Price' => 0.5,
27
+ 'Medium Price' => 0.3,
28
+ 'Low Price' => 0.2
29
+ } })
25
30
  ]
26
31
  end
27
- it "should not raise any errors" do
28
- expect { Qfill::Pusher.new(*@origin_queues) }.to_not raise_error
32
+
33
+ it 'does not raise any errors' do
34
+ expect { described_class.new(*@origin_queues) }.not_to raise_error
29
35
  end
30
- it "should instantiate with name" do
31
- popper = Qfill::Pusher.new(*@origin_queues)
32
- popper.queues.first.name.should == "Top Results"
33
- popper.queues.last.name.should == "Page Results"
36
+
37
+ it 'instantiates with name' do
38
+ popper = described_class.new(*@origin_queues)
39
+ expect(popper.queues.first.name).to eq('Top Results')
40
+ expect(popper.queues.last.name).to eq('Page Results')
34
41
  end
35
42
  end
36
43
  end
37
-
38
44
  end
@@ -1,57 +1,68 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  describe Qfill::Result do
3
- context "#new" do
4
- context "with no arguments" do
5
- it "should raise ArgumentError" do
6
- expect { Qfill::Result.new() }.to raise_error(ArgumentError)
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
- context "with name" do
10
- before :each do
11
- @arguments = { :name => "Best Results" }
11
+
12
+ context 'with name' do
13
+ before do
14
+ @arguments = { name: 'Best Results' }
12
15
  end
13
- it "should not raise any errors" do
14
- expect { Qfill::Result.new(@arguments) }.to_not raise_error
16
+
17
+ it 'does not raise any errors' do
18
+ expect { described_class.new(@arguments) }.not_to raise_error
15
19
  end
16
- it "should instantiate with name" do
17
- Qfill::Result.new(@arguments).name.should == 'Best Results'
20
+
21
+ it 'instantiates with name' do
22
+ expect(described_class.new(@arguments).name).to eq('Best Results')
18
23
  end
19
24
  end
20
- context "with ratio" do
21
- before :each do
22
- @arguments = { :name => "Best Results",
23
- :ratio => 0.5 }
25
+
26
+ context 'with ratio' do
27
+ before do
28
+ @arguments = { name: 'Best Results',
29
+ ratio: 0.5 }
24
30
  end
25
- it "should instantiate with elements" do
26
- Qfill::Result.new(@arguments).ratio.should == 0.5
31
+
32
+ it 'instantiates with elements' do
33
+ expect(described_class.new(@arguments).ratio).to eq(0.5)
27
34
  end
28
35
  end
29
- context "with filter" do
30
- before :each do
31
- lambda = -> (object) { !object.nil? }
36
+
37
+ context 'with filter' do
38
+ before do
39
+ lambda = ->(object) { !object.nil? }
32
40
  @filter = Qfill::Filter.new(lambda)
33
- @arguments = { :name => "Best Results",
34
- :ratio => 0.5,
35
- :filter => @filter }
41
+ @arguments = { name: 'Best Results',
42
+ ratio: 0.5,
43
+ filter: @filter }
36
44
  end
37
- it "should instantiate with filter" do
38
- Qfill::Result.new(@arguments).filter.should be_a(Qfill::Filter)
39
- Qfill::Result.new(@arguments).filter.should == @filter
45
+
46
+ it 'instantiates with filter' 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
- context "with list_ratios" do
43
- before :each do
44
- @arguments = { :name => "Best Results",
45
- :ratio => 0.5,
46
- :list_ratios => {
47
- "High Price" => 0.4,
48
- "Medium Price" => 0.3,
49
- "Low Price" => 0.3 } }
50
- end
51
- it "should instantiate with elements" do
52
- Qfill::Result.new(@arguments).list_ratios["High Price"].should == 0.4
51
+
52
+ context 'with list_ratios' do
53
+ before do
54
+ @arguments = { name: 'Best Results',
55
+ ratio: 0.5,
56
+ list_ratios: {
57
+ 'High Price' => 0.4,
58
+ 'Medium Price' => 0.3,
59
+ 'Low Price' => 0.3
60
+ } }
61
+ end
62
+
63
+ it 'instantiates with elements' do
64
+ expect(described_class.new(@arguments).list_ratios['High Price']).to eq(0.4)
53
65
  end
54
66
  end
55
67
  end
56
-
57
68
  end
data/spec/qfill_spec.rb CHANGED
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  describe Qfill do
3
- it "should have string version" do
4
- Qfill::VERSION.should be_a(String)
5
+ it 'has string version' do
6
+ expect(Qfill::VERSION).to be_a(String)
5
7
  end
6
8
 
7
- it "should have major, minor & patch version levels" do
8
- Qfill::VERSION.should =~ /\d+\.\d+\.\d+/
9
+ it 'has major, minor & patch version levels' do
10
+ expect(Qfill::VERSION).to match(/\d+\.\d+\.\d+/)
9
11
  end
10
-
11
12
  end
data/spec/spec_helper.rb CHANGED
@@ -1,48 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'qfill'
2
- # This file was generated by the `rspec --init` command. Conventionally, all
3
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
4
- # Require this file using `require "spec_helper"` to ensure that it is only
5
- # loaded once.
6
- #
7
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
4
+
5
+ require 'byebug' if RUBY_ENGINE == 'ruby'
6
+ require 'support/helper'
7
+ require 'support/random_object'
8
+
8
9
  RSpec.configure do |config|
9
- config.treat_symbols_as_metadata_keys_with_true_values = true
10
10
  config.run_all_when_everything_filtered = true
11
11
  config.filter_run :focus
12
+ config.include Support::Helper
12
13
 
13
14
  # Run specs in random order to surface order dependencies. If you find an
14
15
  # order dependency and want to debug it, you can fix the order by providing
15
16
  # the seed, which is printed after each run.
16
17
  # --seed 1234
17
18
  config.order = 'random'
19
+ config.before do
20
+ stub_const('Qfill::VERBOSE', false)
21
+ end
18
22
  end
19
-
20
- # TODO: Write some specs with this dude:
21
- #class RandomObject
22
- #
23
- # attr_accessor :rating, :queue
24
- # def initialize(options = {})
25
- # @rating = options[:rating] || RandomObject.random_rating
26
- # @queue = RandomObject.list_designation(self.rating)
27
- # end
28
- #
29
- # def self.random_rating
30
- # rand(101) # 0 - 100
31
- # end
32
- #
33
- # def self.list_designation(rating)
34
- # if rating == 0
35
- # 'none'
36
- # elsif rating < 34
37
- # 'low'
38
- # elsif rating < 67
39
- # 'medium'
40
- # else
41
- # 'high'
42
- # end
43
- # end
44
- #
45
- # def to_s
46
- # "RO:#{rating}:#{queue}"
47
- # end
48
- #end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Support
4
+ module Helper
5
+ def build_elements(name, num)
6
+ array = []
7
+ Array.new(num).each_with_index.map do |_x, i|
8
+ array << "#{name}-#{i}"
9
+ end
10
+ array
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RandomObject
4
+ attr_accessor :rating, :queue
5
+
6
+ def initialize(options = {})
7
+ @rating = options[:rating] || RandomObject.random_rating
8
+ @queue = RandomObject.list_designation(rating)
9
+ end
10
+
11
+ def self.random_rating
12
+ rand(101) # 0 - 100
13
+ end
14
+
15
+ def self.list_designation(rating)
16
+ if rating == 0
17
+ 'none'
18
+ elsif rating < 34
19
+ 'low'
20
+ elsif rating < 67
21
+ 'medium'
22
+ else
23
+ 'high'
24
+ end
25
+ end
26
+
27
+ def to_s
28
+ "RO:#{rating}:#{queue}"
29
+ end
30
+ end
metadata CHANGED
@@ -1,32 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qfill
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Peter Boling
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-03-12 00:00:00.000000000 Z
11
+ date: 2022-02-25 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13'
14
27
  - !ruby/object:Gem::Dependency
15
28
  name: rspec
16
29
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
30
  requirements:
19
- - - '>='
31
+ - - "~>"
20
32
  - !ruby/object:Gem::Version
21
- version: '0'
33
+ version: '3'
22
34
  type: :development
23
35
  prerelease: false
24
36
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
37
  requirements:
27
- - - '>='
38
+ - - "~>"
28
39
  - !ruby/object:Gem::Version
29
- version: '0'
40
+ version: '3'
30
41
  description: Advanced Queue Transformation
31
42
  email:
32
43
  - peter.boling@gmail.com
@@ -34,13 +45,22 @@ executables: []
34
45
  extensions: []
35
46
  extra_rdoc_files: []
36
47
  files:
37
- - .gitignore
38
- - .rspec
48
+ - ".github/dependabot.yml"
49
+ - ".github/workflows/style.yml"
50
+ - ".github/workflows/test.yml"
51
+ - ".gitignore"
52
+ - ".rspec"
53
+ - ".rubocop.yml"
54
+ - ".rubocop_todo.yml"
55
+ - ".simplecov"
56
+ - CODE_OF_CONDUCT.md
39
57
  - Gemfile
40
- - LICENSE.txt
58
+ - Guardfile
59
+ - LICENSE
41
60
  - README.md
42
61
  - Rakefile
43
62
  - lib/qfill.rb
63
+ - lib/qfill/errors/invalid_index.rb
44
64
  - lib/qfill/filter.rb
45
65
  - lib/qfill/list.rb
46
66
  - lib/qfill/list_set.rb
@@ -49,7 +69,14 @@ files:
49
69
  - lib/qfill/popper.rb
50
70
  - lib/qfill/pusher.rb
51
71
  - lib/qfill/result.rb
72
+ - lib/qfill/strategy.rb
73
+ - lib/qfill/strategy/base.rb
74
+ - lib/qfill/strategy/drain_to_empty.rb
75
+ - lib/qfill/strategy/drain_to_limit.rb
76
+ - lib/qfill/strategy/sample.rb
77
+ - lib/qfill/strategy/time_slice.rb
52
78
  - lib/qfill/version.rb
79
+ - maintenance-branch
53
80
  - qfill.gemspec
54
81
  - spec/qfill/filter_spec.rb
55
82
  - spec/qfill/list_set_spec.rb
@@ -61,29 +88,29 @@ files:
61
88
  - spec/qfill/result_spec.rb
62
89
  - spec/qfill_spec.rb
63
90
  - spec/spec_helper.rb
64
- homepage: ''
91
+ - spec/support/helper.rb
92
+ - spec/support/random_object.rb
93
+ homepage: https://github.com/pboling/qfill
65
94
  licenses: []
66
- post_install_message:
95
+ metadata: {}
96
+ post_install_message:
67
97
  rdoc_options: []
68
98
  require_paths:
69
99
  - lib
70
100
  required_ruby_version: !ruby/object:Gem::Requirement
71
- none: false
72
101
  requirements:
73
- - - '>='
102
+ - - ">="
74
103
  - !ruby/object:Gem::Version
75
104
  version: '0'
76
105
  required_rubygems_version: !ruby/object:Gem::Requirement
77
- none: false
78
106
  requirements:
79
- - - '>='
107
+ - - ">="
80
108
  - !ruby/object:Gem::Version
81
109
  version: '0'
82
110
  requirements: []
83
- rubyforge_project:
84
- rubygems_version: 1.8.25
85
- signing_key:
86
- specification_version: 3
111
+ rubygems_version: 3.2.29
112
+ signing_key:
113
+ specification_version: 4
87
114
  summary: 'You have a set of arrays that need to be turned into a different set of
88
115
  arrays according to a potentially non-uniform set of rules. Now you can easily
89
116
  turn this: source_a # => [1,2,3,4] source_b # => [5,6,7,8,9] into this: result_a
@@ -100,3 +127,5 @@ test_files:
100
127
  - spec/qfill/result_spec.rb
101
128
  - spec/qfill_spec.rb
102
129
  - spec/spec_helper.rb
130
+ - spec/support/helper.rb
131
+ - spec/support/random_object.rb