machinist 1.0.6 → 2.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.
- data/.gitignore +7 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +47 -0
- data/MIT-LICENSE +2 -1
- data/README.markdown +182 -204
- data/Rakefile +22 -29
- data/VERSION +1 -1
- data/lib/generators/machinist/install/USAGE +2 -0
- data/lib/generators/machinist/install/install_generator.rb +46 -0
- data/lib/generators/machinist/install/templates/blueprints.rb +9 -0
- data/lib/generators/machinist/install/templates/machinist.rb.erb +7 -0
- data/lib/generators/machinist/model/model_generator.rb +13 -0
- data/lib/machinist/active_record/blueprint.rb +16 -0
- data/lib/machinist/active_record/lathe.rb +24 -0
- data/lib/machinist/active_record.rb +8 -93
- data/lib/machinist/blueprint.rb +89 -0
- data/lib/machinist/exceptions.rb +32 -0
- data/lib/machinist/lathe.rb +68 -0
- data/lib/machinist/machinable.rb +95 -0
- data/lib/machinist/version.rb +3 -0
- data/lib/machinist.rb +4 -109
- data/machinist.gemspec +20 -65
- data/spec/active_record_spec.rb +85 -171
- data/spec/blueprint_spec.rb +76 -0
- data/spec/exceptions_spec.rb +20 -0
- data/spec/inheritance_spec.rb +104 -0
- data/spec/machinable_spec.rb +101 -0
- data/spec/spec_helper.rb +4 -6
- data/spec/support/active_record_environment.rb +65 -0
- metadata +125 -37
- data/.autotest +0 -7
- data/FAQ.markdown +0 -18
- data/init.rb +0 -2
- data/lib/machinist/blueprints.rb +0 -25
- data/lib/machinist/data_mapper.rb +0 -83
- data/lib/machinist/object.rb +0 -30
- data/lib/machinist/sequel.rb +0 -62
- data/lib/sham.rb +0 -77
- data/spec/data_mapper_spec.rb +0 -134
- data/spec/db/.gitignore +0 -1
- data/spec/db/schema.rb +0 -20
- data/spec/log/.gitignore +0 -1
- data/spec/machinist_spec.rb +0 -190
- data/spec/sequel_spec.rb +0 -146
- data/spec/sham_spec.rb +0 -95
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'machinist/active_record'
|
3
|
+
|
4
|
+
ActiveRecord::Base.establish_connection(
|
5
|
+
:adapter => "mysql",
|
6
|
+
:database => "machinist",
|
7
|
+
:username => "root",
|
8
|
+
:password => ""
|
9
|
+
)
|
10
|
+
|
11
|
+
ActiveRecord::Schema.define(:version => 0) do
|
12
|
+
create_table :users, :force => true do |t|
|
13
|
+
t.column :username, :string
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :posts, :force => true do |t|
|
17
|
+
t.column :title, :string
|
18
|
+
t.column :author_id, :integer
|
19
|
+
t.column :body, :text
|
20
|
+
end
|
21
|
+
|
22
|
+
create_table :comments, :force => true do |t|
|
23
|
+
t.column :post_id, :integer
|
24
|
+
t.column :body, :text
|
25
|
+
end
|
26
|
+
|
27
|
+
create_table :tags, :force => true do |t|
|
28
|
+
t.column :name, :string
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :posts_tags, :id => false, :force => true do |t|
|
32
|
+
t.column :post_id, :integer
|
33
|
+
t.column :tag_id, :integer
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class User < ActiveRecord::Base
|
38
|
+
validates_presence_of :username
|
39
|
+
validates_uniqueness_of :username
|
40
|
+
end
|
41
|
+
|
42
|
+
class Post < ActiveRecord::Base
|
43
|
+
has_many :comments
|
44
|
+
belongs_to :author, :class_name => "User"
|
45
|
+
has_and_belongs_to_many :tags
|
46
|
+
end
|
47
|
+
|
48
|
+
class Comment < ActiveRecord::Base
|
49
|
+
belongs_to :post
|
50
|
+
end
|
51
|
+
|
52
|
+
class Tag < ActiveRecord::Base
|
53
|
+
has_and_belongs_to_many :posts
|
54
|
+
end
|
55
|
+
|
56
|
+
module ActiveRecordEnvironment
|
57
|
+
|
58
|
+
def empty_database!
|
59
|
+
[User, Post, Comment].each do |klass|
|
60
|
+
klass.delete_all
|
61
|
+
klass.clear_blueprints!
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: machinist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 3
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: "2.0"
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Pete Yandell
|
@@ -9,86 +14,169 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
13
|
-
default_executable:
|
17
|
+
date: 2012-01-13 00:00:00 Z
|
14
18
|
dependencies:
|
19
|
+
- !ruby/object:Gem::Dependency
|
20
|
+
name: activerecord
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: mysql
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
hash: 3
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
version: "0"
|
45
|
+
type: :development
|
46
|
+
version_requirements: *id002
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
hash: 3
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
type: :development
|
60
|
+
version_requirements: *id003
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rcov
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
type: :development
|
74
|
+
version_requirements: *id004
|
15
75
|
- !ruby/object:Gem::Dependency
|
16
76
|
name: rspec
|
77
|
+
prerelease: false
|
78
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
hash: 3
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
version: "0"
|
17
87
|
type: :development
|
18
|
-
|
19
|
-
|
88
|
+
version_requirements: *id005
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rdoc
|
91
|
+
prerelease: false
|
92
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
20
94
|
requirements:
|
21
95
|
- - ">="
|
22
96
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
97
|
+
hash: 3
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
version: "0"
|
101
|
+
type: :development
|
102
|
+
version_requirements: *id006
|
25
103
|
description:
|
26
|
-
email:
|
104
|
+
email:
|
105
|
+
- pete@notahat.com
|
27
106
|
executables: []
|
28
107
|
|
29
108
|
extensions: []
|
30
109
|
|
31
|
-
extra_rdoc_files:
|
32
|
-
|
110
|
+
extra_rdoc_files: []
|
111
|
+
|
33
112
|
files:
|
34
|
-
- .autotest
|
35
113
|
- .gitignore
|
36
|
-
-
|
114
|
+
- Gemfile
|
115
|
+
- Gemfile.lock
|
37
116
|
- MIT-LICENSE
|
38
117
|
- README.markdown
|
39
118
|
- Rakefile
|
40
119
|
- VERSION
|
41
|
-
-
|
120
|
+
- lib/generators/machinist/install/USAGE
|
121
|
+
- lib/generators/machinist/install/install_generator.rb
|
122
|
+
- lib/generators/machinist/install/templates/blueprints.rb
|
123
|
+
- lib/generators/machinist/install/templates/machinist.rb.erb
|
124
|
+
- lib/generators/machinist/model/model_generator.rb
|
42
125
|
- lib/machinist.rb
|
43
126
|
- lib/machinist/active_record.rb
|
44
|
-
- lib/machinist/
|
45
|
-
- lib/machinist/
|
46
|
-
- lib/machinist/
|
47
|
-
- lib/machinist/
|
48
|
-
- lib/
|
127
|
+
- lib/machinist/active_record/blueprint.rb
|
128
|
+
- lib/machinist/active_record/lathe.rb
|
129
|
+
- lib/machinist/blueprint.rb
|
130
|
+
- lib/machinist/exceptions.rb
|
131
|
+
- lib/machinist/lathe.rb
|
132
|
+
- lib/machinist/machinable.rb
|
133
|
+
- lib/machinist/version.rb
|
49
134
|
- machinist.gemspec
|
50
135
|
- spec/active_record_spec.rb
|
51
|
-
- spec/
|
52
|
-
- spec/
|
53
|
-
- spec/
|
54
|
-
- spec/
|
55
|
-
- spec/machinist_spec.rb
|
56
|
-
- spec/sequel_spec.rb
|
57
|
-
- spec/sham_spec.rb
|
136
|
+
- spec/blueprint_spec.rb
|
137
|
+
- spec/exceptions_spec.rb
|
138
|
+
- spec/inheritance_spec.rb
|
139
|
+
- spec/machinable_spec.rb
|
58
140
|
- spec/spec_helper.rb
|
59
|
-
|
141
|
+
- spec/support/active_record_environment.rb
|
60
142
|
homepage: http://github.com/notahat/machinist
|
61
143
|
licenses: []
|
62
144
|
|
63
145
|
post_install_message:
|
64
|
-
rdoc_options:
|
65
|
-
|
146
|
+
rdoc_options: []
|
147
|
+
|
66
148
|
require_paths:
|
67
149
|
- lib
|
68
150
|
required_ruby_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
69
152
|
requirements:
|
70
153
|
- - ">="
|
71
154
|
- !ruby/object:Gem::Version
|
155
|
+
hash: 3
|
156
|
+
segments:
|
157
|
+
- 0
|
72
158
|
version: "0"
|
73
|
-
version:
|
74
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
none: false
|
75
161
|
requirements:
|
76
162
|
- - ">="
|
77
163
|
- !ruby/object:Gem::Version
|
164
|
+
hash: 3
|
165
|
+
segments:
|
166
|
+
- 0
|
78
167
|
version: "0"
|
79
|
-
version:
|
80
168
|
requirements: []
|
81
169
|
|
82
|
-
rubyforge_project:
|
83
|
-
rubygems_version: 1.
|
170
|
+
rubyforge_project: machinist
|
171
|
+
rubygems_version: 1.8.10
|
84
172
|
signing_key:
|
85
173
|
specification_version: 3
|
86
174
|
summary: Fixtures aren't fun. Machinist is.
|
87
175
|
test_files:
|
88
176
|
- spec/active_record_spec.rb
|
89
|
-
- spec/
|
90
|
-
- spec/
|
91
|
-
- spec/
|
92
|
-
- spec/
|
93
|
-
- spec/sham_spec.rb
|
177
|
+
- spec/blueprint_spec.rb
|
178
|
+
- spec/exceptions_spec.rb
|
179
|
+
- spec/inheritance_spec.rb
|
180
|
+
- spec/machinable_spec.rb
|
94
181
|
- spec/spec_helper.rb
|
182
|
+
- spec/support/active_record_environment.rb
|
data/.autotest
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
Autotest.add_hook :initialize do |at|
|
2
|
-
at.clear_mappings
|
3
|
-
|
4
|
-
at.add_mapping(%r%^spec/(.*)_spec.rb$%) {|filename, _| filename }
|
5
|
-
at.add_mapping(%r%^lib/(.*).rb$%) {|_, match| "spec/#{match[1]}_spec.rb" }
|
6
|
-
at.add_mapping(%r%^spec/spec_helper.rb$%) { at.files_matching(%r%^spec/(.*)_spec.rb$%) }
|
7
|
-
end
|
data/FAQ.markdown
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
Machinist FAQ
|
2
|
-
=============
|
3
|
-
|
4
|
-
### My blueprint is giving me really weird errors. Any ideas?
|
5
|
-
|
6
|
-
If your object has an attribute that happens to correspond to a Ruby standard function, it won't work properly in a blueprint.
|
7
|
-
|
8
|
-
For example:
|
9
|
-
|
10
|
-
OpeningHours.blueprint do
|
11
|
-
open { Time.now }
|
12
|
-
end
|
13
|
-
|
14
|
-
This will result in Machinist attempting to run ruby's open command. To work around this use self.open instead.
|
15
|
-
|
16
|
-
OpeningHours.blueprint do
|
17
|
-
self.open { Time.now }
|
18
|
-
end
|
data/init.rb
DELETED
data/lib/machinist/blueprints.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Machinist
|
2
|
-
# Include this in a class to allow defining blueprints for that class.
|
3
|
-
module Blueprints
|
4
|
-
def self.included(base)
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
end
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
def blueprint(name = :master, &blueprint)
|
10
|
-
@blueprints ||= {}
|
11
|
-
@blueprints[name] = blueprint if block_given?
|
12
|
-
@blueprints[name]
|
13
|
-
end
|
14
|
-
|
15
|
-
def named_blueprints
|
16
|
-
@blueprints.reject{|name,_| name == :master }.keys
|
17
|
-
end
|
18
|
-
|
19
|
-
def clear_blueprints!
|
20
|
-
@blueprints = {}
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'machinist'
|
2
|
-
require 'machinist/blueprints'
|
3
|
-
require 'dm-core'
|
4
|
-
|
5
|
-
module Machinist
|
6
|
-
|
7
|
-
class DataMapperAdapter
|
8
|
-
def self.has_association?(object, attribute)
|
9
|
-
object.class.relationships.has_key?(attribute)
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.class_for_association(object, attribute)
|
13
|
-
association = object.class.relationships[attribute]
|
14
|
-
association && association.parent_model
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.association_is_many_to_one?(association)
|
18
|
-
if defined?(DataMapper::Associations::ManyToOne::Relationship)
|
19
|
-
# We're using the next branch of DM
|
20
|
-
association.class == DataMapper::Associations::ManyToOne::Relationship
|
21
|
-
else
|
22
|
-
# We're using the 0.9 or less branch.
|
23
|
-
association.options[:max].nil?
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# This method takes care of converting any associated objects,
|
28
|
-
# in the hash returned by Lathe#assigned_attributes, into their
|
29
|
-
# object ids.
|
30
|
-
#
|
31
|
-
# For example, let's say we have blueprints like this:
|
32
|
-
#
|
33
|
-
# Post.blueprint { }
|
34
|
-
# Comment.blueprint { post }
|
35
|
-
#
|
36
|
-
# Lathe#assigned_attributes will return { :post => ... }, but
|
37
|
-
# we want to pass { :post_id => 1 } to a controller.
|
38
|
-
#
|
39
|
-
# This method takes care of cleaning this up.
|
40
|
-
def self.assigned_attributes_without_associations(lathe)
|
41
|
-
attributes = {}
|
42
|
-
lathe.assigned_attributes.each_pair do |attribute, value|
|
43
|
-
association = lathe.object.class.relationships[attribute]
|
44
|
-
if association && association_is_many_to_one?(association)
|
45
|
-
# DataMapper child_key can have more than one property, but I'm not
|
46
|
-
# sure in what circumstances this would be the case. I'm assuming
|
47
|
-
# here that there's only one property.
|
48
|
-
key = association.child_key.map(&:field).first.to_sym
|
49
|
-
attributes[key] = value.id
|
50
|
-
else
|
51
|
-
attributes[attribute] = value
|
52
|
-
end
|
53
|
-
end
|
54
|
-
attributes
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
module DataMapperExtensions
|
59
|
-
def make(*args, &block)
|
60
|
-
lathe = Lathe.run(Machinist::DataMapperAdapter, self.new, *args)
|
61
|
-
unless Machinist.nerfed?
|
62
|
-
lathe.object.save || raise("Save failed")
|
63
|
-
lathe.object.reload
|
64
|
-
end
|
65
|
-
lathe.object(&block)
|
66
|
-
end
|
67
|
-
|
68
|
-
def make_unsaved(*args)
|
69
|
-
object = Machinist.with_save_nerfed { make(*args) }
|
70
|
-
yield object if block_given?
|
71
|
-
object
|
72
|
-
end
|
73
|
-
|
74
|
-
def plan(*args)
|
75
|
-
lathe = Lathe.run(Machinist::DataMapperAdapter, self.new, *args)
|
76
|
-
Machinist::DataMapperAdapter.assigned_attributes_without_associations(lathe)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
DataMapper::Model.append_extensions(Machinist::Blueprints::ClassMethods)
|
83
|
-
DataMapper::Model.append_extensions(Machinist::DataMapperExtensions)
|
data/lib/machinist/object.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'machinist'
|
2
|
-
require 'machinist/blueprints'
|
3
|
-
|
4
|
-
module Machinist
|
5
|
-
|
6
|
-
module ObjectExtensions
|
7
|
-
def self.included(base)
|
8
|
-
base.extend(ClassMethods)
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
def make(*args, &block)
|
13
|
-
lathe = Lathe.run(Machinist::ObjectAdapter, self.new, *args)
|
14
|
-
lathe.object(&block)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class ObjectAdapter
|
20
|
-
def self.has_association?(object, attribute)
|
21
|
-
false
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
class Object
|
28
|
-
include Machinist::Blueprints
|
29
|
-
include Machinist::ObjectExtensions
|
30
|
-
end
|
data/lib/machinist/sequel.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
require 'machinist'
|
2
|
-
require 'machinist/blueprints'
|
3
|
-
require 'sequel'
|
4
|
-
|
5
|
-
module Machinist
|
6
|
-
class SequelAdapter
|
7
|
-
def self.has_association?(object, attribute)
|
8
|
-
object.class.associations.include?(attribute)
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.class_for_association(object, attribute)
|
12
|
-
object.class.association_reflection(attribute).associated_class
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.assigned_attributes_without_associations(lathe)
|
16
|
-
attributes = {}
|
17
|
-
lathe.assigned_attributes.each_pair do |attribute, value|
|
18
|
-
association = lathe.object.class.association_reflection(attribute)
|
19
|
-
if association && association[:type] == :many_to_one
|
20
|
-
key = association[:key] || association.default_key
|
21
|
-
attributes[key] = value.send(association.primary_key)
|
22
|
-
else
|
23
|
-
attributes[attribute] = value
|
24
|
-
end
|
25
|
-
end
|
26
|
-
attributes
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
module SequelExtensions
|
31
|
-
def self.included(base)
|
32
|
-
base.extend(ClassMethods)
|
33
|
-
end
|
34
|
-
|
35
|
-
module ClassMethods
|
36
|
-
def make(*args, &block)
|
37
|
-
lathe = Lathe.run(Machinist::SequelAdapter, self.new, *args)
|
38
|
-
unless Machinist.nerfed?
|
39
|
-
lathe.object.save
|
40
|
-
lathe.object.refresh
|
41
|
-
end
|
42
|
-
lathe.object(&block)
|
43
|
-
end
|
44
|
-
|
45
|
-
def make_unsaved(*args)
|
46
|
-
returning(Machinist.with_save_nerfed { make(*args) }) do |object|
|
47
|
-
yield object if block_given?
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def plan(*args)
|
52
|
-
lathe = Lathe.run(Machinist::SequelAdapter, self.new, *args)
|
53
|
-
Machinist::SequelAdapter.assigned_attributes_without_associations(lathe)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class Sequel::Model
|
60
|
-
include Machinist::Blueprints
|
61
|
-
include Machinist::SequelExtensions
|
62
|
-
end
|
data/lib/sham.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
class Sham
|
2
|
-
@@shams = {}
|
3
|
-
|
4
|
-
# Over-ride module's built-in name method, so we can re-use it for
|
5
|
-
# generating names. This is a bit of a no-no, but we get away with
|
6
|
-
# it in this context.
|
7
|
-
def self.name(*args, &block)
|
8
|
-
method_missing(:name, *args, &block)
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.method_missing(symbol, *args, &block)
|
12
|
-
if block_given?
|
13
|
-
@@shams[symbol] = Sham.new(symbol, args.pop || {}, &block)
|
14
|
-
else
|
15
|
-
sham = @@shams[symbol]
|
16
|
-
raise "No sham defined for #{symbol}" if sham.nil?
|
17
|
-
sham.fetch_value
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.clear
|
22
|
-
@@shams = {}
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.reset(scope = :before_all)
|
26
|
-
@@shams.values.each { |sham| sham.reset(scope) }
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.define(&block)
|
30
|
-
Sham.instance_eval(&block)
|
31
|
-
end
|
32
|
-
|
33
|
-
def initialize(name, options = {}, &block)
|
34
|
-
@name = name
|
35
|
-
@generator = block
|
36
|
-
@offset = 0
|
37
|
-
@unique = options.has_key?(:unique) ? options[:unique] : true
|
38
|
-
generate_values(12)
|
39
|
-
end
|
40
|
-
|
41
|
-
def reset(scope)
|
42
|
-
if scope == :before_all
|
43
|
-
@offset, @before_offset = 0, nil
|
44
|
-
elsif @before_offset
|
45
|
-
@offset = @before_offset
|
46
|
-
else
|
47
|
-
@before_offset = @offset
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def fetch_value
|
52
|
-
# Generate more values if we need them.
|
53
|
-
if @offset >= @values.length
|
54
|
-
generate_values(2 * @values.length)
|
55
|
-
raise "Can't generate more unique values for Sham.#{@name}" if @offset >= @values.length
|
56
|
-
end
|
57
|
-
result = @values[@offset]
|
58
|
-
@offset += 1
|
59
|
-
result
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
def generate_values(count)
|
65
|
-
@values = seeded { (1..count).map(&@generator) }
|
66
|
-
@values.uniq! if @unique
|
67
|
-
end
|
68
|
-
|
69
|
-
def seeded
|
70
|
-
begin
|
71
|
-
srand(1)
|
72
|
-
yield
|
73
|
-
ensure
|
74
|
-
srand
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|