jim-summon 0.0.0 → 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/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  coverage
4
4
  rdoc
5
5
  pkg
6
+ test.log
data/README.rdoc CHANGED
@@ -2,7 +2,108 @@
2
2
 
3
3
  Provides a nice DSL for creating dummy data using Factory Girl factory definitions.
4
4
 
5
- Docs and examples coming soon.
5
+ == Why
6
+
7
+ Now that you've moved away from fixtures (well, you have, haven't you?) and started using factory_girl
8
+ in your tests and specs, it would be nice to have a succinct way to generate dummy data for use in development.
9
+
10
+ In the past I've just used a bunch of extra factories for this, but it's a lot nicer to be able to build an
11
+ arbitrary number of objects, each with its own set of associations.
12
+
13
+ == Example
14
+
15
+ Here is an example Rakefile from a project I'm working on:
16
+
17
+ namespace :summon do
18
+ desc "Builds a ton of dummy data"
19
+ task :build => ['environment', 'db:reset'] do
20
+
21
+ require 'spec/support/factories' # load factory definitions
22
+ require 'summon'
23
+
24
+ published_date = lambda {
25
+ method = %w(ago since)[rand(2)]
26
+ rand(100).days.send(method)
27
+ }
28
+
29
+ Summon(:label, 5)
30
+ Summon(:blog_topic, 10)
31
+
32
+ Summon(:user, 20) do |user|
33
+ user.blogs(3..8,
34
+ :topic => BlogTopic.all,
35
+ :published_at => published_date
36
+ ) do |blog|
37
+ blog.comments 0..4
38
+ end
39
+ end
40
+
41
+ Summon(:artist, 20) do |artist|
42
+ artist.events 4..6
43
+ artist.releases(0..5,
44
+ :label => Label.all
45
+ ) do |release|
46
+ release.tracks 8..12
47
+ end
48
+ end
49
+
50
+ puts "Your minions are ready!"
51
+
52
+ end
53
+ end
54
+
55
+ == Installation
56
+
57
+ I'd go for the gem.
58
+
59
+ sudo gem install jim-summon
60
+
61
+ == Usage
62
+
63
+ === Specifying how many objects to build
64
+
65
+ You can use an integer or range when specifying how many objects to build:
66
+
67
+ Summon(:monkey, 3) # build 3 monkeys
68
+ Summon(:monkey, 3..6) # build between 3 and 6 monkeys
69
+
70
+ === Object attributes
71
+
72
+ Other attributes to set on created objects (potentially overriding those defined by the factory)
73
+ are passed in as a hash:
74
+
75
+ Summon(:monkey, 42, :dangerous => true) # builds 42 dangerous monkeys
76
+
77
+ If you pass a proc in as an attribute, it will be evaluated for each object and the resulting
78
+ value used in its place.
79
+
80
+ If you pass an Array in as a value to an attribute, a value from the array will be selected at
81
+ random. This might seem odd, but I've found it's much more common to want to set an attribute
82
+ or association randomly from a set of options than set an attribute value to be an array. You
83
+ can always use a proc for this.
84
+
85
+ == Associated objects
86
+
87
+ This is where the magic really happens. Use a block to define an object's associations, and
88
+ potentially their attributes:
89
+
90
+ Summon(:car, 4) do |car| # Build 4 cars, and in each...
91
+ car.passengers 3 # Build 3 passengers
92
+ car.driver # Build one driver
93
+ end
94
+
95
+ Right now has_many and has_one associations are supported. has_many :through is not. Associations
96
+ can be nested as deep as you like:
97
+
98
+ Summon(:car, 4, :color => 'red') do |car|
99
+ car.passengers 3, :backseat_driver => true
100
+ car.driver do |driver|
101
+ driver.gloves 2
102
+ driver.jacket do |jacket|
103
+ jacket.pockets 2, :cents => [0,5,10,25,50]
104
+ end
105
+ end
106
+ end
6
107
 
7
108
  == Note on Patches/Pull Requests
8
109
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "summon"
8
- gem.summary = %Q{Provided a nice DSL for creating dummy data using Factory Girl factory definitions}
8
+ gem.summary = %Q{Provides a nice DSL for creating dummy data using Factory Girl factory definitions}
9
9
  gem.description = %Q{Allows for easily setting up deeply nested associations}
10
10
  gem.email = "jim@autonomousmachine.com"
11
11
  gem.homepage = "http://github.com/jim/summon"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.1.0
data/lib/summon.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  require 'factory_girl'
2
2
 
3
3
  module Summon
4
-
4
+
5
+ (class << self; self; end).class_eval do
6
+ attr_accessor :noisy
7
+ end
8
+ self.noisy = false
9
+
5
10
  class Conjure
6
11
 
7
12
  attr :parent
@@ -11,7 +16,7 @@ module Summon
11
16
  end
12
17
 
13
18
  def log(string)
14
- if parent.nil?
19
+ if parent.nil? && Summon.noisy
15
20
  printf string; $stdout.flush
16
21
  end
17
22
  end
@@ -31,7 +36,7 @@ module Summon
31
36
  end
32
37
  end
33
38
 
34
- quantity = args.first
39
+ quantity = args.first || 1
35
40
  quantity = quantity.to_a[rand(quantity.to_a.size)] if quantity.is_a?(Range)
36
41
  options = args.extract_options!
37
42
 
@@ -46,7 +51,17 @@ module Summon
46
51
  if parent.nil?
47
52
  child = Factory(name, attributes)
48
53
  else
49
- child = parent.send(name).create(Factory.attributes_for(name.to_s.singularize, attributes))
54
+ association = @parent.class.reflect_on_association(name.to_sym)
55
+ raise "Association #{name} not found on #{@parent.class.to_s}" unless association
56
+
57
+ child = case association.macro
58
+ when :has_one:
59
+ parent.send("#{name}=", Factory(name.to_s.singularize, attributes))
60
+ when :has_many:
61
+ parent.send(name).create(Factory.attributes_for(name.to_s.singularize, attributes))
62
+ else
63
+ raise "#{association.macro} macros are not supported"
64
+ end
50
65
  end
51
66
  yield Conjure.new(child) if block_given?
52
67
  end
data/summon.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{summon}
8
- s.version = "0.0.0"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jim Benton"]
12
- s.date = %q{2009-08-25}
12
+ s.date = %q{2009-08-26}
13
13
  s.description = %q{Allows for easily setting up deeply nested associations}
14
14
  s.email = %q{jim@autonomousmachine.com}
15
15
  s.extra_rdoc_files = [
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
32
32
  s.rdoc_options = ["--charset=UTF-8"]
33
33
  s.require_paths = ["lib"]
34
34
  s.rubygems_version = %q{1.3.3}
35
- s.summary = %q{Provided a nice DSL for creating dummy data using Factory Girl factory definitions}
35
+ s.summary = %q{Provides a nice DSL for creating dummy data using Factory Girl factory definitions}
36
36
  s.test_files = [
37
37
  "test/summon_test.rb",
38
38
  "test/test_helper.rb"
data/test/summon_test.rb CHANGED
@@ -1,7 +1,53 @@
1
1
  require 'test_helper'
2
2
 
3
- class SummonTest < Test::Unit::TestCase
4
- def test_pass
5
- assert true, 'had better pass'
3
+ class SummonTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ Summon.noisy = false
7
+ Corner.delete_all
8
+ Compartment.delete_all
9
+ Handle.delete_all
10
+ Box.delete_all
11
+ Secret.delete_all
6
12
  end
7
- end
13
+
14
+ test "building a number of objects" do
15
+ Summon(:corner, 3)
16
+ assert_equal 3, Corner.count
17
+ end
18
+
19
+ test "building a variable number of objects" do
20
+ Summon(:corner, 3..5)
21
+ assert_operator 3..5, :===, Corner.count
22
+ end
23
+
24
+ test "overriding default factory attributes" do
25
+ Summon(:corner, 1, :sharp => false)
26
+ assert_equal false, Corner.first.sharp
27
+ end
28
+
29
+ test "building has_many associations" do
30
+ Summon(:box, 1) do |b|
31
+ b.corners 3
32
+ b.compartments 2 do |c|
33
+ c.secrets 4
34
+ end
35
+ end
36
+ assert_equal 3, Box.first.corners.count
37
+ assert_equal 3, Corner.count
38
+ assert_equal 2, Box.first.compartments.count
39
+ assert_equal 2, Compartment.count
40
+ assert_equal 8, Secret.count
41
+ end
42
+
43
+ test "building has_one associations" do
44
+ Summon(:box, 1) do |b|
45
+ b.compartments 2 do |c|
46
+ c.handle
47
+ end
48
+ end
49
+ assert_equal 2, Compartment.count
50
+ assert_equal 2, Handle.count
51
+ end
52
+
53
+ end
data/test/test_helper.rb CHANGED
@@ -1,9 +1,78 @@
1
1
  require 'rubygems'
2
+ gem 'test-unit'
2
3
  require 'test/unit'
4
+ require 'active_support'
5
+ require 'active_support/test_case'
6
+ require 'active_record'
7
+ require 'factory_girl'
3
8
 
4
9
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
10
  $LOAD_PATH.unshift(File.dirname(__FILE__))
6
11
  require 'summon'
7
12
 
8
- class Test::Unit::TestCase
13
+ ActiveRecord::Base.logger = Logger.new(File.open('test.log', 'a'))
14
+ ActiveRecord::Base.logger.level = Logger::DEBUG
15
+ ActiveRecord::Base.colorize_logging = false
16
+
17
+ ActiveRecord::Base.establish_connection(
18
+ :adapter => 'sqlite3',
19
+ :database => ":memory:"
20
+ )
21
+
22
+ ActiveRecord::Schema.define do
23
+ create_table :boxes, :force => true do |t|
24
+ t.string :name
25
+ t.integer :depth
26
+ end
27
+ create_table :corners, :force => true do |t|
28
+ t.integer :box_id
29
+ t.boolean :sharp
30
+ end
31
+ create_table :compartments, :force => true do |t|
32
+ t.integer :box_id
33
+ t.boolean :hidden
34
+ end
35
+ create_table :handles, :force => true do |h|
36
+ h.integer :compartment_id
37
+ h.boolean :metal
38
+ end
39
+ create_table :secrets, :force => true do |s|
40
+ s.integer :compartment_id
41
+ s.boolean :valuable
42
+ end
43
+ end
44
+
45
+ class Corner < ActiveRecord::Base; end
46
+ class Secret < ActiveRecord::Base; end
47
+ class Handle < ActiveRecord::Base; end
48
+
49
+ class Compartment < ActiveRecord::Base
50
+ has_many :secrets
51
+ has_one :handle
52
+ end
53
+
54
+ class Box < ActiveRecord::Base
55
+ has_many :compartments
56
+ has_many :corners
57
+ end
58
+
59
+ Factory.define(:box) do |b|
60
+ b.name 'A box'
61
+ b.depth 12
62
+ end
63
+
64
+ Factory.define(:corner) do |c|
65
+ c.sharp true
66
+ end
67
+
68
+ Factory.define(:compartment) do |c|
69
+ c.hidden true
70
+ end
71
+
72
+ Factory.define(:handle) do |h|
73
+ h.metal true
9
74
  end
75
+
76
+ Factory.define(:secret) do |c|
77
+ c.valuable true
78
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jim-summon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Benton
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-25 00:00:00 -07:00
12
+ date: 2009-08-26 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -67,7 +67,7 @@ rubyforge_project:
67
67
  rubygems_version: 1.2.0
68
68
  signing_key:
69
69
  specification_version: 3
70
- summary: Provided a nice DSL for creating dummy data using Factory Girl factory definitions
70
+ summary: Provides a nice DSL for creating dummy data using Factory Girl factory definitions
71
71
  test_files:
72
72
  - test/summon_test.rb
73
73
  - test/test_helper.rb