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.
@@ -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.
@@ -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
@@ -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
@@ -0,0 +1,2 @@
1
+ require 'foundry'
2
+ require 'dsl'
@@ -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
@@ -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
@@ -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
@@ -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
+