has_fixtures 0.0.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.
- data/.gitignore +1 -0
- data/History.txt +0 -0
- data/LICENSE +20 -0
- data/Manifest.txt +17 -0
- data/README.textile +224 -0
- data/README.txt +3 -0
- data/Rakefile +57 -0
- data/TODO +0 -0
- data/lib/has_fixtures.rb +10 -0
- data/lib/has_fixtures/base.rb +42 -0
- data/lib/has_fixtures/sweatshop.rb +64 -0
- data/lib/has_fixtures/version.rb +5 -0
- data/spec/has_fixtures/base_spec.rb +77 -0
- data/spec/has_fixtures/sweatshop_spec.rb +144 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +12 -0
- data/tasks/hoe.rb +40 -0
- metadata +92 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*~
|
data/History.txt
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Ben Burkert
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
.gitignore
|
2
|
+
History.txt
|
3
|
+
LICENSE
|
4
|
+
Manifest.txt
|
5
|
+
README.textile
|
6
|
+
README.txt
|
7
|
+
Rakefile
|
8
|
+
TODO
|
9
|
+
lib/has_fixtures.rb
|
10
|
+
lib/has_fixtures/base.rb
|
11
|
+
lib/has_fixtures/sweatshop.rb
|
12
|
+
lib/has_fixtures/version.rb
|
13
|
+
spec/has_fixtures/base_spec.rb
|
14
|
+
spec/has_fixtures/sweatshop_spec.rb
|
15
|
+
spec/spec.opts
|
16
|
+
spec/spec_helper.rb
|
17
|
+
tasks/hoe.rb
|
data/README.textile
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
h1. dm-sweatshop
|
2
|
+
|
3
|
+
h2. Overview
|
4
|
+
|
5
|
+
dm-sweatshop is a model factory for DataMapper. It makes it easy & painless to crank out complex pseudo random models -- useful for tests and seed data. Production Goals:
|
6
|
+
|
7
|
+
* Easy generation of random models with data that fits the application domain.
|
8
|
+
* Simple syntax for declaring and generating model patterns.
|
9
|
+
* Add context to model patterns, allowing grouping and
|
10
|
+
* Effortlessly generate or fill in associations for creating complex models with few lines of code.
|
11
|
+
|
12
|
+
h2. Examples
|
13
|
+
|
14
|
+
Starting off with a simple user model.
|
15
|
+
<pre>
|
16
|
+
<code>
|
17
|
+
class User
|
18
|
+
include DataMapper::Resource
|
19
|
+
|
20
|
+
property :id, Serial
|
21
|
+
property :username, String
|
22
|
+
property :email, String
|
23
|
+
property :password, String
|
24
|
+
end
|
25
|
+
</code>
|
26
|
+
</pre>
|
27
|
+
|
28
|
+
A fixture for the user model can be defined using the @fixture@ method.
|
29
|
+
<pre>
|
30
|
+
<code>
|
31
|
+
User.fixture {{
|
32
|
+
:username => (username = /\w+/.gen),
|
33
|
+
:email => "#{username}@example.com",
|
34
|
+
:password => (password = /\w+/.gen),
|
35
|
+
:pasword_confirmation => password
|
36
|
+
|
37
|
+
# The /\w+/.gen notation is part of the randexp gem:
|
38
|
+
# http://github.com/benburkert/randexp/
|
39
|
+
}}
|
40
|
+
</code>
|
41
|
+
</pre>
|
42
|
+
|
43
|
+
Notice the double curly brace (@{{@), a quick little way to pass a block that returns a hash to the fixture method. This is important because it ensures the data is random when we generate a new instance of the model, by calling the block every time.
|
44
|
+
|
45
|
+
And here's how you generate said model.
|
46
|
+
<pre>
|
47
|
+
<code>
|
48
|
+
User.generate
|
49
|
+
</code>
|
50
|
+
</pre>
|
51
|
+
|
52
|
+
That's it. In fact, it can even be shortened.
|
53
|
+
<pre>
|
54
|
+
<code>
|
55
|
+
User.gen
|
56
|
+
</code>
|
57
|
+
</pre>
|
58
|
+
|
59
|
+
h3. Associations
|
60
|
+
|
61
|
+
The real power of sweatshop is generating working associations.
|
62
|
+
<pre>
|
63
|
+
<code>
|
64
|
+
DataMapper.setup(:default, "sqlite3::memory:")
|
65
|
+
|
66
|
+
class Tweet
|
67
|
+
include DataMapper::Resource
|
68
|
+
|
69
|
+
property :id, Serial
|
70
|
+
property :message, String, :length => 140
|
71
|
+
property :user_id, Integer
|
72
|
+
|
73
|
+
belongs_to :user
|
74
|
+
has n, :tags, :through => Resource
|
75
|
+
end
|
76
|
+
|
77
|
+
class Tag
|
78
|
+
include DataMapper::Resource
|
79
|
+
|
80
|
+
property :id, Serial
|
81
|
+
property :name, String
|
82
|
+
|
83
|
+
has n, :tweets, :through => Resource
|
84
|
+
end
|
85
|
+
|
86
|
+
class User
|
87
|
+
include DataMapper::Resource
|
88
|
+
|
89
|
+
property :id, Serial
|
90
|
+
property :username, String
|
91
|
+
|
92
|
+
has n, :tweets
|
93
|
+
end
|
94
|
+
|
95
|
+
DataMapper.auto_migrate!
|
96
|
+
|
97
|
+
User.fix {{
|
98
|
+
:username => /\w+/.gen,
|
99
|
+
:tweets => 500.of {Tweet.make}
|
100
|
+
}}
|
101
|
+
|
102
|
+
Tweet.fix {{
|
103
|
+
:message => /[:sentence:]/.gen[0..140],
|
104
|
+
:tags => (0..10).of {Tag.make}
|
105
|
+
}}
|
106
|
+
|
107
|
+
Tag.fix {{
|
108
|
+
:name => /\w+/.gen
|
109
|
+
}}
|
110
|
+
|
111
|
+
# now lets generate 100 users, each with 500 tweets. Also, the tweet's have 0 to 10 tags!
|
112
|
+
users = 10.of {User.gen}
|
113
|
+
</code>
|
114
|
+
</pre>
|
115
|
+
|
116
|
+
That's going to generate alot of tags, way more than you would see in the production app. Let's recylce some already generated tags instead.
|
117
|
+
|
118
|
+
<pre>
|
119
|
+
<code>
|
120
|
+
User.fix {{
|
121
|
+
:username => /\w+/.gen,
|
122
|
+
:tweets => 500.of {Tweet.make}
|
123
|
+
}}
|
124
|
+
|
125
|
+
Tweet.fix {{
|
126
|
+
:message => /[:sentence:]/.gen[0..140],
|
127
|
+
:tags => (0..10).of {Tag.pick} #lets pick, not make this time
|
128
|
+
}}
|
129
|
+
|
130
|
+
Tag.fix {{
|
131
|
+
:name => /\w+/.gen
|
132
|
+
}}
|
133
|
+
|
134
|
+
50.times {Tag.gen}
|
135
|
+
|
136
|
+
users = 10.of {User.gen}
|
137
|
+
</code>
|
138
|
+
</pre>
|
139
|
+
|
140
|
+
h3. Contexts
|
141
|
+
|
142
|
+
You can add multiple fixtures to a mode, dm-sweatshop will randomly pick between the available fixtures when it generates a new model.
|
143
|
+
|
144
|
+
<pre>
|
145
|
+
<code>
|
146
|
+
Tweet.fix {{
|
147
|
+
:message => /\@#{User.pick.name} [:sentence:]/.gen[0..140], #an @reply for some user
|
148
|
+
:tags => (0..10).of {Tag.pick}
|
149
|
+
}}
|
150
|
+
</code>
|
151
|
+
</pre>
|
152
|
+
|
153
|
+
To keep track of all of our new fixtures, we can even give them a context.
|
154
|
+
|
155
|
+
<pre>
|
156
|
+
<code>
|
157
|
+
Tweet.fix(:at_reply) {{
|
158
|
+
:message => /\@#{User.pick.name} [:sentence:]/.gen[0..140],
|
159
|
+
:tags => (0..10).of {Tag.pick}
|
160
|
+
}}
|
161
|
+
|
162
|
+
Tweet.fix(:conversation) {{
|
163
|
+
:message => /\@#{(tweet = Tweet.pick(:at_reply)).user.name} [:sentence:]/.gen[0..140],
|
164
|
+
:tags => tweet.tags
|
165
|
+
}}
|
166
|
+
</code>
|
167
|
+
</pre>
|
168
|
+
|
169
|
+
h3. Overriding a fixture
|
170
|
+
|
171
|
+
Sometimes you will want to change one of your fixtures a little bit. You create a new fixture with a whole new context, but this can be overkill. The other option is to specify attributes in the call to @generate@.
|
172
|
+
|
173
|
+
<pre>
|
174
|
+
<code>
|
175
|
+
User.gen(:username => 'datamapper') #uses 'datamapper' as the user name instead of the randomly generated word
|
176
|
+
</code>
|
177
|
+
</pre>
|
178
|
+
|
179
|
+
This works with contexts too.
|
180
|
+
|
181
|
+
<pre>
|
182
|
+
<code>
|
183
|
+
User.gen(:conversation, :tags => Tag.all) #a very, very broad conversation
|
184
|
+
</code>
|
185
|
+
</pre>
|
186
|
+
|
187
|
+
Go forth, and populate your data.
|
188
|
+
|
189
|
+
h2. Best Practices
|
190
|
+
|
191
|
+
h3. Specs
|
192
|
+
|
193
|
+
The suggested way to use dm-sweatshop with test specs is to create a @spec/spec_fixtures.rb@ file, then declare your fixtures in there. Next, @require@ it in your @spec/spec_helper.rb@ file, after your models have loaded.
|
194
|
+
|
195
|
+
<pre>
|
196
|
+
<code>
|
197
|
+
Merb.start_environment(:testing => true, :adapter => 'runner', :environment => ENV['MERB_ENV'] || 'test')
|
198
|
+
|
199
|
+
require File.join(File.dirname(__FILE__), 'spec_fixtures')
|
200
|
+
</code>
|
201
|
+
</pre>
|
202
|
+
|
203
|
+
Add the @.generate@ calls in your @before@ setup. Make sure to clear your tables or @auto_migrate@ your models after each spec!
|
204
|
+
|
205
|
+
h2. Possible Improvements
|
206
|
+
|
207
|
+
h3. Enforcing Validations
|
208
|
+
|
209
|
+
Enforce validations at generation time, before the call to @new@/@create@.
|
210
|
+
|
211
|
+
<pre>
|
212
|
+
<code>
|
213
|
+
User.fix {{
|
214
|
+
:username.unique => /\w+/.gen,
|
215
|
+
:tweets => 500.of {Tweet.make}
|
216
|
+
}}
|
217
|
+
</code>
|
218
|
+
</pre>
|
219
|
+
|
220
|
+
h3. Better Exception Handling
|
221
|
+
|
222
|
+
h3. Smarter @pick@
|
223
|
+
|
224
|
+
Add multiple contexts to pick, or an ability to _fall back_ if one context has no generated models.
|
data/README.txt
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'spec/rake/spectask'
|
4
|
+
require "rake/gempackagetask"
|
5
|
+
|
6
|
+
require 'pathname'
|
7
|
+
|
8
|
+
ROOT = Pathname(__FILE__).dirname.expand_path
|
9
|
+
require ROOT + 'lib/has_fixtures/version'
|
10
|
+
|
11
|
+
AUTHOR = "David Cuadrado"
|
12
|
+
EMAIL = "krawek@gmail.com"
|
13
|
+
GEM_NAME = "has_fixtures"
|
14
|
+
GEM_VERSION = HasFixtures::Sweatshop::VERSION
|
15
|
+
GEM_DEPENDENCIES = ["randexp"]
|
16
|
+
GEM_CLEAN = ["log", "pkg"]
|
17
|
+
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.textile LICENSE TODO ] }
|
18
|
+
|
19
|
+
PROJECT_NAME = "has_fixtures"
|
20
|
+
PROJECT_URL = "http://rubyforge.net"
|
21
|
+
PROJECT_DESCRIPTION = PROJECT_SUMMARY = "agnostic plugin for building pseudo random models. fork of dm-sweatshop by Ben Burkert <ben@benburkert.com>"
|
22
|
+
|
23
|
+
task :default => [ :spec ]
|
24
|
+
|
25
|
+
WIN32 = (RUBY_PLATFORM =~ /win32|mingw|cygwin/) rescue nil
|
26
|
+
SUDO = WIN32 ? '' : ('sudo' unless ENV['SUDOLESS'])
|
27
|
+
|
28
|
+
desc "Install #{GEM_NAME} #{GEM_VERSION} (default ruby)"
|
29
|
+
task :install => [ :package, :install_randexp ] do
|
30
|
+
sh "#{SUDO} gem install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources", :verbose => false
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'tasks/hoe.rb'
|
34
|
+
|
35
|
+
desc "Install the randexp gem from rubyforge"
|
36
|
+
task :install_randexp do
|
37
|
+
sh "#{SUDO} gem install randexp --no-update-sources", :verbose => false
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Uninstall #{GEM_NAME} #{GEM_VERSION} (default ruby)"
|
41
|
+
task :uninstall => [ :clobber ] do
|
42
|
+
sh "#{SUDO} gem uninstall #{GEM_NAME} -v#{GEM_VERSION} -I -x", :verbose => false
|
43
|
+
end
|
44
|
+
|
45
|
+
namespace :jruby do
|
46
|
+
desc "Install #{GEM_NAME} #{GEM_VERSION} with JRuby"
|
47
|
+
task :install => [ :package ] do
|
48
|
+
sh %{#{SUDO} jruby -S gem install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources}, :verbose => false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'Run specifications'
|
53
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
54
|
+
t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
|
55
|
+
t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s)
|
56
|
+
end
|
57
|
+
|
data/TODO
ADDED
File without changes
|
data/lib/has_fixtures.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module HasFixtures
|
2
|
+
module Base
|
3
|
+
def self.included(klass)
|
4
|
+
klass.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def fixture(name = default_fauxture_name, &blk)
|
9
|
+
Sweatshop.add(self, name, &blk)
|
10
|
+
end
|
11
|
+
|
12
|
+
alias_method :fix, :fixture
|
13
|
+
|
14
|
+
def generate(name = default_fauxture_name, attributes = {})
|
15
|
+
name, attributes = default_fauxture_name, name if name.is_a? Hash
|
16
|
+
Sweatshop.create(self, name, attributes)
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method :gen, :generate
|
20
|
+
|
21
|
+
def generate_attributes(name = default_fauxture_name)
|
22
|
+
Sweatshop.attributes(self, name)
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :gen_attrs, :generate_attributes
|
26
|
+
|
27
|
+
def make(name = default_fauxture_name, attributes = {})
|
28
|
+
name, attributes = default_fauxture_name, name if name.is_a? Hash
|
29
|
+
Sweatshop.make(self, name, attributes)
|
30
|
+
end
|
31
|
+
|
32
|
+
def pick(name = default_fauxture_name)
|
33
|
+
Sweatshop.pick(self, name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_fauxture_name
|
37
|
+
:default
|
38
|
+
end
|
39
|
+
end # class methods
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module HasFixtures
|
2
|
+
class Sweatshop
|
3
|
+
class << self
|
4
|
+
attr_accessor :model_map
|
5
|
+
attr_accessor :record_map
|
6
|
+
end
|
7
|
+
|
8
|
+
self.model_map = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = []}}
|
9
|
+
self.record_map = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = []}}
|
10
|
+
|
11
|
+
def self.add(klass, name, &proc)
|
12
|
+
self.model_map[klass][name.to_sym] << proc
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.record(klass, name, instance)
|
16
|
+
self.record_map[klass][name.to_sym] << instance
|
17
|
+
instance
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.create(klass, name, attributes = {})
|
21
|
+
begin
|
22
|
+
record(klass, name, klass.create(attributes(klass, name).merge(attributes)))
|
23
|
+
rescue StandardError => e
|
24
|
+
retry if e.message =~ /^column \w+ is not unique$/
|
25
|
+
raise e
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.make(klass, name, attributes = {})
|
30
|
+
record(klass, name, klass.new(attributes(klass, name).merge(attributes)))
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.pick(klass, name)
|
34
|
+
self.record_map[klass][name.to_sym].pick || raise(NoFixturesExist, "no #{name} context fixtures have been generated for the #{klass} class")
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.attributes(klass, name)
|
38
|
+
proc = model_map[klass][name.to_sym].pick
|
39
|
+
|
40
|
+
if !proc.nil?
|
41
|
+
proc.call
|
42
|
+
elsif klass.superclass.include?(HasFixtures::Base)
|
43
|
+
attributes(klass.superclass, name)
|
44
|
+
else
|
45
|
+
raise "#{name} fixture was not found"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.load_all(options = {}) # TODO: spec
|
50
|
+
HasFixtures::Sweatshop.model_map.each do |klass, keys|
|
51
|
+
keys.each do |key, procs|
|
52
|
+
procs.each do |p|
|
53
|
+
values = p.call
|
54
|
+
$stderr.puts ">> #{klass}: #{key}" if options[:verbose]
|
55
|
+
values.each do |k, v|
|
56
|
+
$stderr.puts " #{k+(' '*(30-k.size).abs)}#{v}" if options[:verbose]
|
57
|
+
end
|
58
|
+
klass.create(values)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe HasFixtures::Base do
|
4
|
+
|
5
|
+
class Widget
|
6
|
+
include DataMapper::Resource
|
7
|
+
|
8
|
+
property :id, Integer, :serial => true
|
9
|
+
property :type, Discriminator
|
10
|
+
property :name, String
|
11
|
+
property :price, Integer
|
12
|
+
|
13
|
+
belongs_to :order
|
14
|
+
end
|
15
|
+
|
16
|
+
class Wonket < Widget
|
17
|
+
property :size, String
|
18
|
+
end
|
19
|
+
|
20
|
+
class Order
|
21
|
+
include DataMapper::Resource
|
22
|
+
|
23
|
+
property :id, Integer, :serial => true
|
24
|
+
|
25
|
+
has n, :widgets
|
26
|
+
end
|
27
|
+
|
28
|
+
before(:each) do
|
29
|
+
DataMapper.auto_migrate!
|
30
|
+
HasFixtures::Sweatshop.model_map.clear
|
31
|
+
HasFixtures::Sweatshop.record_map.clear
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".fixture" do
|
35
|
+
it "should add a fixture proc for the model" do
|
36
|
+
Widget.fixture {{
|
37
|
+
:name => /\w+/.gen.capitalize,
|
38
|
+
:price => /\d{4,5}/.gen.to_i
|
39
|
+
}}
|
40
|
+
|
41
|
+
HasFixtures::Sweatshop.model_map[Widget][:default].should_not be_empty
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should allow handle complex named fixtures" do
|
46
|
+
Wonket.fix {{
|
47
|
+
:name => /\w+ Wonket/.gen.capitalize,
|
48
|
+
:price => /\d{2,3}99/.gen.to_i,
|
49
|
+
:size => %w[small medium large xl].pick
|
50
|
+
}}
|
51
|
+
|
52
|
+
Order.fix {{
|
53
|
+
:widgets => (1..5).of { Widget.gen }
|
54
|
+
}}
|
55
|
+
|
56
|
+
Order.fix(:wonket_order) {{
|
57
|
+
:widgets => (5..10).of { Wonket.gen }
|
58
|
+
}}
|
59
|
+
|
60
|
+
wonket_order = Order.gen(:wonket_order)
|
61
|
+
wonket_order.widgets.should_not be_empty
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should allow for STI fixtures" do
|
65
|
+
Widget.fix {{
|
66
|
+
:name => /\w+/.gen.capitalize,
|
67
|
+
:price => /\d{4,5}/.gen.to_i
|
68
|
+
}}
|
69
|
+
|
70
|
+
Order.fix {{
|
71
|
+
:widgets => (1..5).of { Wonket.gen }
|
72
|
+
}}
|
73
|
+
|
74
|
+
Order.gen.widgets.should_not be_empty
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe HasFixtures::Sweatshop do
|
4
|
+
|
5
|
+
class Parent
|
6
|
+
include DataMapper::Resource
|
7
|
+
|
8
|
+
property :id, Integer, :serial => true
|
9
|
+
property :type, Discriminator
|
10
|
+
property :first_name, String
|
11
|
+
property :last_name, String
|
12
|
+
end
|
13
|
+
|
14
|
+
class Child < Parent
|
15
|
+
property :age, Integer
|
16
|
+
end
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
DataMapper.auto_migrate!
|
20
|
+
HasFixtures::Sweatshop.model_map.clear
|
21
|
+
HasFixtures::Sweatshop.record_map.clear
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".model_map" do
|
25
|
+
it "should return a Hash if the model is not mapped" do
|
26
|
+
HasFixtures::Sweatshop.model_map[Class.new].should be_is_a(Hash)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return a map for names to an array of procs if the model is not mapped" do
|
30
|
+
HasFixtures::Sweatshop.model_map[Class.new][:unnamed].should be_is_a(Array)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".add" do
|
35
|
+
it "should app a generator proc to the model map" do
|
36
|
+
proc = lambda {}
|
37
|
+
lambda {
|
38
|
+
HasFixtures::Sweatshop.add(Parent, :default, &proc)
|
39
|
+
}.should change {
|
40
|
+
HasFixtures::Sweatshop.model_map[Parent][:default].first
|
41
|
+
}.from(nil).to(proc)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should push repeat procs onto the mapped array" do
|
45
|
+
proc1, proc2 = lambda {}, lambda {}
|
46
|
+
|
47
|
+
HasFixtures::Sweatshop.add(Parent, :default, &proc1)
|
48
|
+
HasFixtures::Sweatshop.add(Parent, :default, &proc2)
|
49
|
+
|
50
|
+
HasFixtures::Sweatshop.model_map[Parent][:default].first.should == proc1
|
51
|
+
HasFixtures::Sweatshop.model_map[Parent][:default].last.should == proc2
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe ".attributes" do
|
56
|
+
it "should return an attributes hash" do
|
57
|
+
HasFixtures::Sweatshop.add(Parent, :default) {{
|
58
|
+
:first_name => /\w+/.gen.capitalize,
|
59
|
+
:last_name => /\w+/.gen.capitalize
|
60
|
+
}}
|
61
|
+
|
62
|
+
HasFixtures::Sweatshop.attributes(Parent, :default).should be_is_a(Hash)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should call the attribute proc on each call to attributes" do
|
66
|
+
calls = 0
|
67
|
+
proc = lambda {{:calls => (calls += 1)}}
|
68
|
+
|
69
|
+
HasFixtures::Sweatshop.add(Parent, :default, &proc)
|
70
|
+
HasFixtures::Sweatshop.attributes(Parent, :default).should == {:calls => 1}
|
71
|
+
HasFixtures::Sweatshop.attributes(Parent, :default).should == {:calls => 2}
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should call attributes with the superclass if the class is not mapped" do
|
75
|
+
HasFixtures::Sweatshop.add(Parent, :default) {{:first_name => 'Bob'}}
|
76
|
+
HasFixtures::Sweatshop.attributes(Child, :default).should == {:first_name => 'Bob'}
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should raise an error if neither the class or it's parent class(es) have been mapped" do
|
80
|
+
lambda { HasFixtures::Sweatshop.attributes(Child, :default) }.should raise_error("default fixture was not found")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe ".create" do
|
85
|
+
it "should call create on the model class with the attributes generated from a mapped proc" do
|
86
|
+
HasFixtures::Sweatshop.add(Parent, :default) {{
|
87
|
+
:first_name => 'Kenny',
|
88
|
+
:last_name => 'Rogers'
|
89
|
+
}}
|
90
|
+
|
91
|
+
Parent.should_receive(:create).with(:first_name => 'Kenny', :last_name => 'Rogers')
|
92
|
+
|
93
|
+
HasFixtures::Sweatshop.create(Parent, :default)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should call create on the model with a parent class' mapped attributes proc when the original class has not been maped" do
|
97
|
+
HasFixtures::Sweatshop.add(Parent, :default) {{
|
98
|
+
:first_name => 'Kenny',
|
99
|
+
:last_name => 'Rogers'
|
100
|
+
}}
|
101
|
+
|
102
|
+
Child.should_receive(:create).with(:first_name => 'Kenny', :last_name => 'Rogers')
|
103
|
+
|
104
|
+
HasFixtures::Sweatshop.create(Child, :default)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should merge in any attributes as an argument" do
|
108
|
+
HasFixtures::Sweatshop.add(Parent, :default) {{
|
109
|
+
:first_name => 'Kenny',
|
110
|
+
:last_name => 'Rogers'
|
111
|
+
}}
|
112
|
+
|
113
|
+
Parent.should_receive(:create).with(:first_name => 'Roddy', :last_name => 'Rogers')
|
114
|
+
|
115
|
+
HasFixtures::Sweatshop.create(Parent, :default, :first_name => 'Roddy')
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe ".make" do
|
120
|
+
it "should call new on the model class with the attributes generated from a mapped proc" do
|
121
|
+
HasFixtures::Sweatshop.add(Parent, :default) {{
|
122
|
+
:first_name => 'Kenny',
|
123
|
+
:last_name => 'Rogers'
|
124
|
+
}}
|
125
|
+
|
126
|
+
Parent.should_receive(:new).with(:first_name => 'Kenny', :last_name => 'Rogers')
|
127
|
+
|
128
|
+
HasFixtures::Sweatshop.make(Parent, :default)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe ".pick" do
|
133
|
+
it "should return a pre existing instance of a model from the record map" do
|
134
|
+
HasFixtures::Sweatshop.add(Parent, :default) {{
|
135
|
+
:first_name => 'George',
|
136
|
+
:last_name => 'Clinton'
|
137
|
+
}}
|
138
|
+
|
139
|
+
HasFixtures::Sweatshop.create(Parent, :default)
|
140
|
+
|
141
|
+
HasFixtures::Sweatshop.pick(Parent, :default).should be_is_a(Parent)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$TESTING=true
|
2
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
|
4
|
+
require 'has_fixtures'
|
5
|
+
require 'dm-core'
|
6
|
+
|
7
|
+
DataMapper.setup(:default, 'sqlite3::memory:')
|
8
|
+
DataMapper::Resource.send(:include, HasFixtures::Base)
|
9
|
+
|
10
|
+
Spec::Runner.configure do |config|
|
11
|
+
end
|
12
|
+
|
data/tasks/hoe.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'hoe'
|
2
|
+
|
3
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
4
|
+
@config = nil
|
5
|
+
RUBYFORGE_USERNAME = "unknown"
|
6
|
+
def rubyforge_username
|
7
|
+
unless @config
|
8
|
+
begin
|
9
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
10
|
+
rescue
|
11
|
+
puts <<-EOS
|
12
|
+
ERROR: No rubyforge config file found: #{@config_file}
|
13
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
14
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
15
|
+
EOS
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
end
|
19
|
+
RUBYFORGE_USERNAME.replace @config["username"]
|
20
|
+
end
|
21
|
+
|
22
|
+
hoe = Hoe.new(GEM_NAME, GEM_VERSION) do |p|
|
23
|
+
|
24
|
+
p.developer(AUTHOR, EMAIL)
|
25
|
+
|
26
|
+
p.description = PROJECT_DESCRIPTION
|
27
|
+
p.summary = PROJECT_SUMMARY
|
28
|
+
p.url = PROJECT_URL
|
29
|
+
|
30
|
+
p.rubyforge_name = PROJECT_NAME if PROJECT_NAME
|
31
|
+
|
32
|
+
p.clean_globs |= GEM_CLEAN
|
33
|
+
p.spec_extras = GEM_EXTRAS if GEM_EXTRAS
|
34
|
+
|
35
|
+
GEM_DEPENDENCIES.each do |dep|
|
36
|
+
p.extra_deps << dep
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: has_fixtures
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Cuadrado
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-09-22 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: randexp
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.7.0
|
34
|
+
version:
|
35
|
+
description: agnostic plugin for building pseudo random models. fork of dm-sweatshop by Ben Burkert <ben@benburkert.com>
|
36
|
+
email:
|
37
|
+
- krawek@gmail.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- README.textile
|
44
|
+
- LICENSE
|
45
|
+
- TODO
|
46
|
+
files:
|
47
|
+
- .gitignore
|
48
|
+
- History.txt
|
49
|
+
- LICENSE
|
50
|
+
- Manifest.txt
|
51
|
+
- README.textile
|
52
|
+
- README.txt
|
53
|
+
- Rakefile
|
54
|
+
- TODO
|
55
|
+
- lib/has_fixtures.rb
|
56
|
+
- lib/has_fixtures/base.rb
|
57
|
+
- lib/has_fixtures/sweatshop.rb
|
58
|
+
- lib/has_fixtures/version.rb
|
59
|
+
- spec/has_fixtures/base_spec.rb
|
60
|
+
- spec/has_fixtures/sweatshop_spec.rb
|
61
|
+
- spec/spec.opts
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- tasks/hoe.rb
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://rubyforge.net
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options:
|
68
|
+
- --main
|
69
|
+
- README.txt
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
version:
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project: has_fixtures
|
87
|
+
rubygems_version: 1.2.0
|
88
|
+
signing_key:
|
89
|
+
specification_version: 2
|
90
|
+
summary: agnostic plugin for building pseudo random models. fork of dm-sweatshop by Ben Burkert <ben@benburkert.com>
|
91
|
+
test_files: []
|
92
|
+
|