toolmantim-foundry 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+