random-set 0.0.2 → 1.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5ad4d2dc9bcb1b5ae42bae76fbbe5cae3c29a4df
4
- data.tar.gz: 51912ae6cdc5572a07e0ee431cab8caaba93910c
3
+ metadata.gz: de80dcedc3dbdcc3bbe1257059617cbda64f2c7a
4
+ data.tar.gz: 13005ce042de59de432963a064e481952bfe8e97
5
5
  SHA512:
6
- metadata.gz: b70d391565cc6a1ee4e4b51af0a3d78e59e518d55e38642c08c4bd83392900cf2f3a39a92ff85014f2840b082d07ddc8d7526423a21b51a1addbe9b1ab773535
7
- data.tar.gz: bf473e2f91d385005447da3e79f1bc00bc1955b4f80b76424f61b30d81afcc7a279fb06a977a3be534463ea4a5a654cd25a94961a73895802b0fb1b00c44b7e3
6
+ metadata.gz: a6eb17de0c6ec5c0409f8a726c1cc55d9457d00409ef0f26026080a705d05ead885f5d2b8db3a59371bef0880b51d81407238ecbf4fc571b5a06aa6c0a716fab
7
+ data.tar.gz: 8e6d39b2dabb9d73f64c8b12fb08304f781495703b6584caaad002e23eae29c04e45b408e1f8da9fcd96a92bb7ec5404e6ad8941848181e99af0a5aaed389e7c
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ script: bundle exec rake
2
+ rvm:
3
+ - 2.0.0
4
+ branches:
5
+ only:
6
+ - master
data/Gemfile.lock CHANGED
@@ -1,12 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- random_set (0.0.1)
4
+ random-set (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ diff-lcs (1.2.5)
10
+ multi_json (1.8.2)
9
11
  rake (10.1.0)
12
+ rspec (2.14.1)
13
+ rspec-core (~> 2.14.0)
14
+ rspec-expectations (~> 2.14.0)
15
+ rspec-mocks (~> 2.14.0)
16
+ rspec-core (2.14.7)
17
+ rspec-expectations (2.14.4)
18
+ diff-lcs (>= 1.1.3, < 2.0)
19
+ rspec-mocks (2.14.4)
20
+ simplecov (0.7.1)
21
+ multi_json (~> 1.0)
22
+ simplecov-html (~> 0.7.1)
23
+ simplecov-html (0.7.1)
10
24
 
11
25
  PLATFORMS
12
26
  ruby
@@ -14,4 +28,6 @@ PLATFORMS
14
28
  DEPENDENCIES
15
29
  bundler (~> 1.3)
16
30
  rake
17
- random_set!
31
+ random-set!
32
+ rspec
33
+ simplecov
data/README.md CHANGED
@@ -7,6 +7,8 @@ Conversely, if an array is given, the output is an array of arrays.
7
7
  Each item in the given template corresponds to an attribute of each item in the result
8
8
  set, and specifies how its data should be generated.
9
9
 
10
+ [<img src="https://secure.travis-ci.org/yoazt/random-set.png?branch=master" alt="Build Status" />](http://travis-ci.org/yoazt/random-set)
11
+
10
12
  ## Installation
11
13
 
12
14
  Add this line to your application's Gemfile:
@@ -54,7 +56,7 @@ If you have only infinitely sized templates, you need to specify a count:
54
56
  The following templates are supported:
55
57
 
56
58
  * Anything with an `each` method that returns an Enumerator.
57
- * Procs or lambdas. One argument is passed: the number of the current iteration.
59
+ * Procs or lambdas. One (optional) argument is passed: the number of the current iteration.
58
60
  * An instance of any class that has a `next` method. If this class also has a `count` method,
59
61
  it is considered a fixed-size template.
60
62
 
@@ -1,77 +1,92 @@
1
1
  module RandomSet
2
2
 
3
- # A template for the random set.
4
- # @api internal
3
+ # @api private
5
4
  class Template
6
5
 
7
- def initialize(templates)
8
- @hash = templates.is_a?(Hash)
9
- @generators = resolve_generators(templates)
10
- end
11
-
12
- def hash?
13
- @hash
14
- end
6
+ ######
7
+ # Initialization & attributes
15
8
 
16
- def resolve_generators(templates)
17
- hash = {}
18
-
19
- process = proc do |key, template|
20
- hash[key] = create_generator(template)
9
+ def initialize(templates)
10
+ @hash = templates.is_a?(Hash)
11
+ @generators = resolve_generators(templates)
21
12
  end
22
13
 
23
- if hash?
24
- templates.each &process
25
- else
26
- templates.each_with_index { |template, index| process[index, template] }
14
+ def hash?
15
+ @hash
27
16
  end
28
17
 
29
- hash
30
- end
18
+ attr_reader :generators
31
19
 
32
- def create_generator(template)
33
- case template
34
- when nil then nil
35
- when ->(t){ t.respond_to?(:next) } then template
36
- when ->(t){ t.respond_to?(:each) } then template.each
37
- when Proc then CustomGenerator.new(template)
38
- else raise UnsupportedTemplate, "cannot create a generator for a template of class #{template.class}"
20
+ def count
21
+ max = nil
22
+ generators.each do |_key, generator|
23
+ next unless generator && generator.respond_to?(:count)
24
+ max = [ max.to_i, generator.count ].max
25
+ end
26
+ max
39
27
  end
40
- end
41
28
 
42
- attr_reader :generators
29
+ ######
30
+ # Generation
31
+
32
+ def generate(count = self.count)
33
+ raise CannotInferCount, "no count was specified or could be inferred" unless count
43
34
 
44
- # Gives a count for the items in this template. If no count can be inferred, +nil+ is returned.
45
- def count
46
- max = nil
47
- generators.each do |_key, generator|
48
- next unless generator && generator.respond_to?(:count)
49
- max = [ max.to_i, generator.count ].max
35
+ data = []
36
+ count.times.each { data << generate_next(data) }
37
+ data
50
38
  end
51
- max
52
- end
53
39
 
54
- def generate(count = self.count)
55
- raise CannotInferCount, "no count was specified or could be inferred" unless count
40
+ ######
41
+ # Support
56
42
 
57
- data = []
58
- count.times.each { data << generate_next(data) }
59
- data
60
- end
43
+ private
44
+
45
+ def resolve_generators(templates)
46
+ hash = {}
47
+
48
+ process = proc do |key, template|
49
+ hash[key] = create_generator(template)
50
+ end
51
+
52
+ if hash?
53
+ templates.each &process
54
+ else
55
+ templates.each_with_index { |template, index| process[index, template] }
56
+ end
57
+
58
+ hash
59
+ end
60
+
61
+ def create_generator(template)
62
+ case template
63
+ when nil then nil
64
+ when ->(t){ t.respond_to?(:next) } then template
65
+ when ->(t){ t.respond_to?(:each) } then template.each
66
+ when Proc then CustomGenerator.new(template)
67
+ else raise UnsupportedTemplate, "cannot create a generator for a template of class #{template.class}"
68
+ end
69
+ end
61
70
 
62
- def generate_next(data)
63
- item = hash? ? {} : []
64
- generators.each do |key, generator|
65
- begin
66
- item[key] = generator.try(:next)
67
- rescue StopIteration
68
- # If some enumerator came to the end, we just leave the rest of the keys blank.
69
- item[key] = nil
71
+ def generate_next(data)
72
+ item = hash? ? {} : []
73
+ generators.each do |key, generator|
74
+ begin
75
+ item[key] = generator ? generator.next : nil
76
+ rescue StopIteration
77
+ # If some enumerator came to the end, we just leave the rest of the keys blank.
78
+ item[key] = nil
79
+ end
70
80
  end
81
+ item
71
82
  end
72
- item
83
+
73
84
  end
74
85
 
86
+ ######
87
+ # CustomGenerator class
88
+
89
+ # @api private
75
90
  class CustomGenerator
76
91
 
77
92
  def initialize(block)
@@ -82,13 +97,15 @@ module RandomSet
82
97
  attr_reader :block
83
98
 
84
99
  def next
85
- block.call @iteration
100
+ if block.arity == 1
101
+ block.call @iteration
102
+ else
103
+ block.call
104
+ end
86
105
  ensure
87
106
  @iteration += 1
88
107
  end
89
108
 
90
109
  end
91
110
 
92
- end
93
-
94
111
  end
@@ -1,3 +1,3 @@
1
1
  module RandomSet
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0"
3
3
  end
data/random-set.gemspec CHANGED
@@ -20,4 +20,6 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "simplecov"
23
25
  end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe "RandomSet generation" do
4
+
5
+ context "specifying an empty template" do
6
+
7
+ it "should require a count" do
8
+ expect{ RandomSet.generate([]) }.to raise_error(RandomSet::CannotInferCount)
9
+ end
10
+
11
+ it "should output X empty records" do
12
+ data = RandomSet.generate(5, [])
13
+
14
+ expect(data).to have(5).items
15
+ expect(data[0]).to be_empty
16
+ expect(data[1]).to be_empty
17
+ expect(data[2]).to be_empty
18
+ expect(data[3]).to be_empty
19
+ expect(data[4]).to be_empty
20
+ end
21
+
22
+ end
23
+
24
+ context "specifying a hash template" do
25
+
26
+ it "should output a list of hashes" do
27
+ expect(RandomSet.generate(5, {})).to eql([ {}, {}, {}, {}, {} ])
28
+ end
29
+
30
+ it "should fill in key-by-key" do
31
+ expect(RandomSet.generate(2, { :name => -> { 'Test' }, :age => (1..2) })).to eql([
32
+ { :name => 'Test', :age => 1 },
33
+ { :name => 'Test', :age => 2 }
34
+ ])
35
+ end
36
+
37
+ end
38
+
39
+ context "specifying an array template" do
40
+
41
+ it "should output a list of arrays" do
42
+ expect(RandomSet.generate(5, [])).to eql([ [], [], [], [], [] ])
43
+ end
44
+
45
+ it "should fill in index by index" do
46
+ expect(RandomSet.generate(2, [ -> { 'Test' }, (1..2) ])).to eql([
47
+ ['Test', 1], ['Test', 2]
48
+ ])
49
+ end
50
+
51
+ end
52
+
53
+ describe 'full example' do
54
+
55
+ let(:custom_generator1) do
56
+ Class.new do
57
+ def initialize
58
+ @iteration = 0
59
+ end
60
+ def next
61
+ "Iteration #{@iteration}"
62
+ ensure
63
+ @iteration += 1
64
+ end
65
+ end.new
66
+ end
67
+
68
+ let :custom_generator2 do
69
+ Class.new do
70
+ def next; 'Same' end
71
+ def count; 3 end
72
+ end.new
73
+ end
74
+
75
+ it "should infer the count from all generators that support counts" do
76
+ data = RandomSet.generate([custom_generator1, custom_generator2])
77
+ expect(data).to have(3).items
78
+ end
79
+
80
+ it "should generate ranges, arrays, procs, and custom generators" do
81
+ data = RandomSet.generate(5, [ custom_generator1, (1..10), [1,2,3], ->(n) { "Item #{n}" } ])
82
+ expect(data).to eql([
83
+ ['Iteration 0', 1, 1, 'Item 0'],
84
+ ['Iteration 1', 2, 2, 'Item 1'],
85
+ ['Iteration 2', 3, 3, 'Item 2'],
86
+ ['Iteration 3', 4, nil, 'Item 3'],
87
+ ['Iteration 4', 5, nil, 'Item 4']
88
+ ])
89
+ end
90
+
91
+
92
+ end
93
+
94
+
95
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+ include RandomSet
3
+
4
+ describe Template do
5
+
6
+ let(:template) { Template.new([]) }
7
+
8
+ describe '#hash?' do
9
+ it "should be true if the passed in argument was a hash" do
10
+ expect(Template.new({})).to be_hash
11
+ end
12
+ it "should be false if anything else was passed in" do
13
+ expect(Template.new([])).not_to be_hash
14
+ end
15
+ end
16
+
17
+ describe '#generators' do
18
+
19
+ it "should be a hash, regardless of the template's input" do
20
+ expect(Template.new({}).generators).to be_a(Hash)
21
+ expect(Template.new([]).generators).to be_a(Hash)
22
+ end
23
+
24
+ it "should contain a resolved generator for each item in the templates" do
25
+ item1 = (1..5)
26
+ item2 = ->{}
27
+
28
+ generators = Template.new([item1, item2]).generators
29
+ expect(generators).to have(2).items
30
+ expect(generators[0]).to be_a(Enumerator)
31
+ expect(generators[1]).to be_a(CustomGenerator)
32
+ end
33
+
34
+ it "should contain a resolved generator for each item in the templates" do
35
+ item1 = (1..5)
36
+ item2 = ->{}
37
+
38
+ generators = Template.new(:item1 => item1, :item2 => item2).generators
39
+ expect(generators).to have(2).items
40
+ expect(generators[:item1]).to be_a(Enumerator)
41
+ expect(generators[:item2]).to be_a(CustomGenerator)
42
+ end
43
+
44
+ end
45
+
46
+ describe '#count' do
47
+ it "should be the maximum count for all generators that return a count" do
48
+ generator1 = double(:count => 2, :next => nil)
49
+ generator2 = double(:count => 5, :next => nil)
50
+ generator3 = double(:next => nil)
51
+ template = Template.new([generator1, generator2, generator3])
52
+ expect(template.count).to eql(5)
53
+ end
54
+
55
+ it "should return nil if no generators had a count method" do
56
+ generator1 = double(:next => nil)
57
+ generator2 = double(:next => nil)
58
+ generator3 = double(:next => nil)
59
+ template = Template.new([generator1, generator2, generator3])
60
+ expect(template.count).to be_nil
61
+ end
62
+ end
63
+
64
+ describe '#generate' do
65
+ let(:template) { Template.new([]) }
66
+
67
+ it "should raise an error if no count was provided, and no count could be inferred" do
68
+ expect(template).to receive(:count).and_return(nil)
69
+ expect{ template.generate }.to raise_error(CannotInferCount, 'no count was specified or could be inferred')
70
+ end
71
+
72
+ it "should output <template.count> records if no count is specified" do
73
+ expect(template).to receive(:count).and_return(5)
74
+ expect(template.generate).to have(5).items
75
+ end
76
+
77
+ it "should output <count> records if a count is specified" do
78
+ allow(template).to receive(:count).and_return(5)
79
+ expect(template.generate(10)).to have(10).items
80
+ end
81
+
82
+ # Other generation examples in the integration specs.
83
+ end
84
+
85
+ describe 'generator resolution' do
86
+
87
+ it "should resolve a range to its enumerator" do
88
+ generator = Template.new([ (1..5) ]).generators[0]
89
+ expect(generator).to be_a(Enumerator)
90
+ expect(generator.map { |i| i }).to eql([1,2,3,4,5])
91
+ end
92
+
93
+ it "should resolve an array to its enumerator" do
94
+ generator = Template.new([ [1,2,3] ]).generators[0]
95
+ expect(generator).to be_a(Enumerator)
96
+ expect(generator.map { |i| i }).to eql([1,2,3])
97
+ end
98
+
99
+ it "should resolve a block into a CustomGenerator" do
100
+ block = ->{}
101
+ generator = Template.new([ block ]).generators[0]
102
+ expect(generator).to be_a(CustomGenerator)
103
+ expect(generator.block).to be(block)
104
+ end
105
+
106
+ it "should resolve anything with an 'each' method to the result of that method" do
107
+ enumerator = double()
108
+ generator = Template.new([ double(:each => enumerator) ]).generators[0]
109
+ expect(generator).to be(enumerator)
110
+ end
111
+
112
+ it "should resolve anything with a 'next' method to itself" do
113
+ generator = double(:next => nil)
114
+ expect(Template.new([ generator ]).generators[0]).to be(generator)
115
+ end
116
+
117
+ it "should raise an error for something else" do
118
+ expect{ Template.new([ Object.new ]) }
119
+ .to raise_error(UnsupportedTemplate, "cannot create a generator for a template of class Object")
120
+ end
121
+
122
+ end
123
+
124
+
125
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe RandomSet do
4
+
5
+ describe '.generate' do
6
+
7
+ it "should require a template argument" do
8
+ expect{ RandomSet.generate }
9
+ .to raise_error(ArgumentError, "template required")
10
+ end
11
+
12
+ it "should not accept more than two arguments" do
13
+ expect{ RandomSet.generate :one, :two, :template }
14
+ .to raise_error(ArgumentError, "too many arguments (1..2 expected)")
15
+ end
16
+
17
+ it "should create a template from the last argument and call its generate with the rest of the arguments" do
18
+ template = double(:template)
19
+ expect(RandomSet::Template).to receive(:new).with(:template).and_return(template)
20
+
21
+ result = double(:result)
22
+ expect(template).to receive(:generate).with(10).and_return(result)
23
+ expect(RandomSet.generate 10, :template).to be(result)
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,18 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter "spec/"
4
+ add_filter "gaussian*" # cannot really test randomizers
5
+ end
6
+
7
+ require 'random-set'
8
+ require 'rspec/autorun'
9
+
10
+ RSpec.configure do |config|
11
+ config.mock_with :rspec do |config|
12
+ config.syntax = :expect
13
+ end
14
+ end
15
+
16
+ # Requires supporting ruby files with custom matchers and macros, etc,
17
+ # in spec/support/ and its subdirectories.
18
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: random-set
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joost Lubach
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  description: Generates a series of data based on a template.
42
70
  email:
43
71
  - joost@yoazt.com
@@ -48,6 +76,7 @@ files:
48
76
  - .gitignore
49
77
  - .ruby-gemset
50
78
  - .ruby-version
79
+ - .travis.yml
51
80
  - Gemfile
52
81
  - Gemfile.lock
53
82
  - LICENSE.txt
@@ -60,6 +89,10 @@ files:
60
89
  - lib/random_set/template.rb
61
90
  - lib/random_set/version.rb
62
91
  - random-set.gemspec
92
+ - spec/generation_spec.rb
93
+ - spec/random_set/template_spec.rb
94
+ - spec/random_set_spec.rb
95
+ - spec/spec_helper.rb
63
96
  homepage: ''
64
97
  licenses:
65
98
  - MIT
@@ -84,5 +117,9 @@ rubygems_version: 2.1.4
84
117
  signing_key:
85
118
  specification_version: 4
86
119
  summary: Generates a series of data based on a template.
87
- test_files: []
120
+ test_files:
121
+ - spec/generation_spec.rb
122
+ - spec/random_set/template_spec.rb
123
+ - spec/random_set_spec.rb
124
+ - spec/spec_helper.rb
88
125
  has_rdoc: