toolmantim-foundry 0.1.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/MIT-LICENSE +20 -0
- data/README.rdoc +156 -0
- data/Rakefile +23 -0
- data/init.rb +2 -0
- data/lib/dsl.rb +36 -0
- data/lib/foundry.rb +21 -0
- data/test/dsl_test.rb +56 -0
- data/test/foundry_test.rb +63 -0
- data/test/test_helper.rb +50 -0
- metadata +62 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [name of plugin creator]
|
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/README.rdoc
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
= Foundry
|
2
|
+
== by Jeremy McAnally and Nicolas Sanguinetti
|
3
|
+
|
4
|
+
Foundry is YAFRP (Yet Another Fixture Replacement Plugin), but it takes an interesting approach. It
|
5
|
+
dynamically creates named_scopes and builds objects off those.
|
6
|
+
|
7
|
+
=== Usage
|
8
|
+
|
9
|
+
To create factory scopes, you can either use the direct method:
|
10
|
+
|
11
|
+
Foundry.factory User, :valid_user, :name => "Jeremy", :login => "jeremy", :password => "1234"
|
12
|
+
Foundry.factory User, :valid_user, { {conditions => {:name => "Jeremy"}}}
|
13
|
+
|
14
|
+
...or the nifty little DSL:
|
15
|
+
|
16
|
+
model User do
|
17
|
+
factory :valid_user, :name => "Jeremy", :login => "jeremy"
|
18
|
+
factory :my_user do
|
19
|
+
{:name => "Mr. Awesome"}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Giving no name creates a factory with the name `valid`
|
23
|
+
factory do
|
24
|
+
{:login => "hello"}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
To create a record using these scopes, just do it like normal:
|
29
|
+
|
30
|
+
User.valid_user.create
|
31
|
+
|
32
|
+
Voila!
|
33
|
+
|
34
|
+
==== Parameters
|
35
|
+
|
36
|
+
Just like in normal +named_scope+ usage, you can pass parameters to these scopes:
|
37
|
+
|
38
|
+
model User do
|
39
|
+
factory :paramd do |one, two|
|
40
|
+
{:name => "#{one} - #{two}"}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Then call it like so:
|
45
|
+
|
46
|
+
User.paramd("Mr.", "User").create
|
47
|
+
|
48
|
+
==== More advanced usage
|
49
|
+
|
50
|
+
Since they're just named_scope's you can actually chain them. So if you had a user factory like this:
|
51
|
+
|
52
|
+
model User
|
53
|
+
factory do
|
54
|
+
{:name => "Jeremy", :login => "jeremy", :role => "user"}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
You could add another...
|
59
|
+
|
60
|
+
model User
|
61
|
+
factory do
|
62
|
+
{:name => "Jeremy", :login => "jeremy", :role => "hello"}
|
63
|
+
end
|
64
|
+
|
65
|
+
factory :with_role do |role|
|
66
|
+
{:role => role}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
...and then chain them:
|
71
|
+
|
72
|
+
User.valid.with_role("admin").create
|
73
|
+
|
74
|
+
You can chain as many as you want that way. Each scope is also given a +with+ scope so you can change it at will
|
75
|
+
for any arbitrary scope. For example, if you wanted to remove the +with_role+ scope from above and use the +with+
|
76
|
+
scope you could do:
|
77
|
+
|
78
|
+
User.valid.with(:role => "admin")
|
79
|
+
|
80
|
+
The +with+ scope with override any previous attribute definition with its own attributes. This makes it dead simple
|
81
|
+
to tweak a factory for just one test (f.e., testing permissions for a lot of roles).
|
82
|
+
|
83
|
+
NOTE: If you are not on Edge Rails/Rails 2.3, you need to put your +with+ scopes *first* or they will not be merged
|
84
|
+
right. There was a bug in previous versions of Rails where previous scopes took precedent over later ones.
|
85
|
+
|
86
|
+
But these are just the basic use cases, since we don't have any random data. But, since it's implemented the way
|
87
|
+
it is, you can do interesting things like this for random data:
|
88
|
+
|
89
|
+
model Page do
|
90
|
+
def unique
|
91
|
+
rand(Time.now.to_i)
|
92
|
+
end
|
93
|
+
|
94
|
+
10.times do |i|
|
95
|
+
factory "valid_#{i}".to_sym, :title => "Page #{unique}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# In your tests
|
100
|
+
Page.valid_2.create
|
101
|
+
# => #<Page id: 3, title: "Page 123872138", created_at: ..., updated_at: ...>
|
102
|
+
|
103
|
+
Or, if you're really serious about unique data...
|
104
|
+
|
105
|
+
# test_helper.rb / spec_helper.rb
|
106
|
+
require 'faker'
|
107
|
+
|
108
|
+
module Unique
|
109
|
+
def unique(attr)
|
110
|
+
if [:name, :first_name, :last_name].include?(attr)
|
111
|
+
return Faker::Name.send(attr)
|
112
|
+
elsif [:company_name, :company_bs, :company_catch_phrase].include?(attr)
|
113
|
+
return Faker::Company.send(attr.to_s.gsub(/company_/, '')) # name is in user and company
|
114
|
+
elsif [:email, :free_email, :user_name, :domain_name].include?(attr)
|
115
|
+
return Faker::Internet.send(attr)
|
116
|
+
else
|
117
|
+
raise ArgumentError, "I'm not sure what random data you want by specifying #{attr}!"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
module Foundry
|
123
|
+
class Runner
|
124
|
+
include Unique
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# In your foundries.rb or whatever
|
129
|
+
model User do
|
130
|
+
10.times do |i|
|
131
|
+
factory "user_#{i}".to_sym, :name => unique(:name), :login => unique(:user_name), :password => "1234"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# In your tests
|
136
|
+
User.user_3.create
|
137
|
+
# => #<User id: 6, name: "Florian Schuppe", login: "kenneth", :password => "1234", created_at: ..., updated_at: ...>
|
138
|
+
|
139
|
+
OR, you could take that even one step further with a block...
|
140
|
+
|
141
|
+
# In your foundries.rb or whatever
|
142
|
+
model User do
|
143
|
+
factory :unique do
|
144
|
+
{:name => unique(:name), :login => unique(:user_name), :password => "1234"}
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# In your tests
|
149
|
+
User.unique.create
|
150
|
+
# => #<User id: 12, name: "Wanda Sharp", login: "delia", :password => "1234", created_at: ..., updated_at: ...>
|
151
|
+
User.unique.create
|
152
|
+
# => #<User id: 13, name: "Alec Eichmann", login: "adam", :password => "1234", created_at: ..., updated_at: ...>
|
153
|
+
User.unique.create
|
154
|
+
# => #<User id: 14, name: "Derek Gleichner", login: "jared", :password => "1234", created_at: ..., updated_at: ...>
|
155
|
+
|
156
|
+
Copyright (c) 2009 Jeremy McAnally, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the foundry plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the foundry plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'Foundry'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
data/init.rb
ADDED
data/lib/dsl.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Foundry
|
2
|
+
def self.setup_foundries(&blk)
|
3
|
+
Runner.new.instance_eval(&blk)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Runner
|
7
|
+
def model(klass, &blk)
|
8
|
+
@klass = klass
|
9
|
+
@attrs = {}
|
10
|
+
|
11
|
+
instance_eval(&blk)
|
12
|
+
add_with_scope unless klass.respond_to?(:with)
|
13
|
+
end
|
14
|
+
|
15
|
+
def factory(name, definition=nil, &blk)
|
16
|
+
if block_given?
|
17
|
+
behavior = proc { {:conditions => blk.call} }
|
18
|
+
Foundry.factory(@klass, name, &behavior)
|
19
|
+
elsif definition || !@attrs.empty?
|
20
|
+
@attrs.merge!(definition) if definition
|
21
|
+
Foundry.factory(@klass, name, @attrs)
|
22
|
+
else
|
23
|
+
raise ArgumentError, "You need to provide a definition or a lambda/block definition!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
alias :foundry :factory
|
28
|
+
|
29
|
+
private
|
30
|
+
def add_with_scope
|
31
|
+
Foundry.factory(@klass, :with) do |opts|
|
32
|
+
{:conditions => opts}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/foundry.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Foundry
|
2
|
+
def self.factory(model, name=nil, definition=nil, &block)
|
3
|
+
name ||= :valid
|
4
|
+
|
5
|
+
raise ArgumentError, "#{model.name} already has a method/scope named #{name}" if model.respond_to?(name)
|
6
|
+
|
7
|
+
if definition.is_a? Hash
|
8
|
+
definition = { :conditions => definition }
|
9
|
+
elsif block_given?
|
10
|
+
definition = block
|
11
|
+
else
|
12
|
+
raise ArgumentError, "You need to provide a definition or a lambda/block definition!"
|
13
|
+
end
|
14
|
+
|
15
|
+
model.named_scope name, definition
|
16
|
+
end
|
17
|
+
|
18
|
+
class <<self
|
19
|
+
alias :foundry :factory
|
20
|
+
end
|
21
|
+
end
|
data/test/dsl_test.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DslTest < Test::Unit::TestCase
|
4
|
+
include FoundryHelper
|
5
|
+
|
6
|
+
# Replace this with your real tests.
|
7
|
+
context "The DSL" do
|
8
|
+
before do
|
9
|
+
@runner = Foundry::Runner.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should scope factory definitions to a model" do
|
13
|
+
@runner.model Record do
|
14
|
+
factory :da_factory, :title => "AWESOME."
|
15
|
+
end
|
16
|
+
|
17
|
+
assert Record.respond_to?(:da_factory)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should create factory scopes" do
|
21
|
+
@runner.model Record do
|
22
|
+
factory :your_factory, :title => "AWESOME."
|
23
|
+
end
|
24
|
+
|
25
|
+
assert Record.respond_to?(:your_factory)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should accept a Hash definition" do
|
29
|
+
@runner.model Record do
|
30
|
+
factory :factoree, :title => "AWESOME."
|
31
|
+
end
|
32
|
+
|
33
|
+
assert Record.respond_to?(:factoree)
|
34
|
+
assert_equal "AWESOME.", Record.factoree.new.title
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should accept a block definition" do
|
38
|
+
@runner.model Record do
|
39
|
+
factory :blked do
|
40
|
+
{:title => "w00t"}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
assert Record.respond_to?(:blked)
|
45
|
+
assert_equal "w00t", Record.blked.new.title
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should allow extra attributes" do
|
49
|
+
@runner.model Record do
|
50
|
+
factory :epic, :title => "EPIC FAIL"
|
51
|
+
end
|
52
|
+
|
53
|
+
assert_equal "EPIC WIN", Record.epic.with(:title => "EPIC WIN").new.title
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FoundryTest < Test::Unit::TestCase
|
4
|
+
include FoundryHelper
|
5
|
+
|
6
|
+
# Replace this with your real tests.
|
7
|
+
context "A foundry" do
|
8
|
+
it "should create a named scope" do
|
9
|
+
Foundry.factory(Record, :valid_record, :title => "what what")
|
10
|
+
assert Record.respond_to?(:valid_record)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should create a scope using the default name if one is not given" do
|
14
|
+
Foundry.factory(Record) { {:title => "whattttt"} }
|
15
|
+
assert Record.respond_to?(:valid)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should create a scope with a block" do
|
19
|
+
Foundry.factory(Record, :blocked_name) do
|
20
|
+
{:title => "epic"}
|
21
|
+
end
|
22
|
+
|
23
|
+
assert Record.respond_to?(:blocked_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should create a scope with a Hash definition" do
|
27
|
+
Foundry.factory(Record, :valid_name, :things => "funnnnn")
|
28
|
+
|
29
|
+
assert Record.respond_to?(:valid_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should create a scope with a block that takes args" do
|
33
|
+
Foundry.factory(Record, :my_factory) do |one, two|
|
34
|
+
{:conditions => {:title => "#{one} #{two}"}}
|
35
|
+
end
|
36
|
+
|
37
|
+
assert Record.respond_to?(:my_factory)
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when making" do
|
41
|
+
it "should fill the values correctly from a Hash" do
|
42
|
+
Foundry.factory(Record, :so_valid, :title => "hello")
|
43
|
+
assert_equal "hello", Record.so_valid.new.title
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should fill the value in correctly from a block" do
|
47
|
+
Foundry.factory(Record, :w00t) do
|
48
|
+
{:conditions => {:title => "m00g"}}
|
49
|
+
end
|
50
|
+
|
51
|
+
assert_equal "m00g", Record.w00t.new.title
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should handle a block with args" do
|
55
|
+
Foundry.factory(Record, :with_title) do |one|
|
56
|
+
{:conditions => {:title => "blah #{one}"}}
|
57
|
+
end
|
58
|
+
|
59
|
+
assert_equal "blah hoo", Record.with_title("hoo").new.title
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Helper borrowed from can_search
|
2
|
+
# and heavily modified for T::U usage
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
require 'context'
|
6
|
+
|
7
|
+
dir = File.dirname(__FILE__)
|
8
|
+
env = "#{dir}/../../../../config/environment.rb"
|
9
|
+
$:.unshift "#{dir}/../lib"
|
10
|
+
|
11
|
+
if File.exist?(env)
|
12
|
+
require env
|
13
|
+
else
|
14
|
+
gem 'activesupport'
|
15
|
+
gem 'activerecord'
|
16
|
+
|
17
|
+
require 'active_support'
|
18
|
+
require 'active_support/test_case'
|
19
|
+
|
20
|
+
require 'active_record'
|
21
|
+
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ":memory:"
|
22
|
+
require 'foundry'
|
23
|
+
end
|
24
|
+
|
25
|
+
Time.zone = "UTC"
|
26
|
+
|
27
|
+
module FoundryHelper
|
28
|
+
class Record < ActiveRecord::Base
|
29
|
+
set_table_name 'foundry_records'
|
30
|
+
|
31
|
+
def self.create_table
|
32
|
+
connection.create_table table_name, :force => true do |t|
|
33
|
+
t.string :title
|
34
|
+
t.datetime :created_at
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.drop_table
|
39
|
+
connection.drop_table table_name
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.seed_data(now = Time.now.utc)
|
43
|
+
transaction do
|
44
|
+
create :title => 'default', :created_at => now - 5.minutes
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Record.create_table
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: toolmantim-foundry
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeremy McNally
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-09 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Another fixture replacement using named_scope. It's fast and simple.
|
17
|
+
email: jeremymcanally@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- init.rb
|
26
|
+
- lib/dsl.rb
|
27
|
+
- lib/foundry.rb
|
28
|
+
- MIT-LICENSE
|
29
|
+
- Rakefile
|
30
|
+
- README.rdoc
|
31
|
+
- test/dsl_test.rb
|
32
|
+
- test/foundry_test.rb
|
33
|
+
- test/test_helper.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/jeremymcanally/foundry/
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options:
|
38
|
+
- --main
|
39
|
+
- README.rdoc
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.2.0
|
58
|
+
signing_key:
|
59
|
+
specification_version: 2
|
60
|
+
summary: Another fixture replacement using named_scope. It's fast and simple.
|
61
|
+
test_files: []
|
62
|
+
|