blueprints 0.8.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +82 -18
- data/LICENSE +1 -1
- data/README.rdoc +38 -8
- data/Rakefile +11 -35
- data/blueprints.gemspec +29 -123
- data/features/support/env.rb +7 -10
- data/lib/blueprints.rb +68 -12
- data/lib/blueprints/blueprint.rb +39 -19
- data/lib/blueprints/buildable.rb +92 -74
- data/lib/blueprints/configuration.rb +18 -4
- data/lib/blueprints/context.rb +148 -5
- data/lib/blueprints/database_cleaner_fix.rb +9 -0
- data/lib/blueprints/dependency.rb +32 -21
- data/lib/blueprints/eval_context.rb +51 -0
- data/lib/blueprints/extensions.rb +115 -0
- data/lib/blueprints/extensions/rspec.rb +3 -1
- data/lib/blueprints/helper.rb +52 -20
- data/lib/blueprints/namespace.rb +31 -12
- data/lib/blueprints/root_namespace.rb +24 -25
- data/lib/blueprints/version.rb +3 -0
- data/spec/{active_record/blueprint.rb → blueprint.rb} +14 -17
- data/spec/{active_record/blueprints_spec.rb → blueprints_spec.rb} +40 -59
- data/spec/spec_helper.rb +34 -0
- data/spec/support/active_record/database.yml.example +7 -0
- data/spec/support/active_record/initializer.rb +15 -0
- data/spec/{active_record/fixtures → support/active_record}/schema.rb +0 -0
- data/spec/support/dm-core/initializer.rb +31 -0
- data/spec/support/mongo_mapper/database.yml.example +2 -0
- data/spec/support/mongo_mapper/initializer.rb +20 -0
- data/spec/support/mongoid/database.yml.example +2 -0
- data/spec/support/mongoid/initializer.rb +23 -0
- data/spec/support/none/initializer.rb +63 -0
- data/spec/unit/active_record_spec.rb +1 -6
- data/spec/unit/blueprint_spec.rb +91 -20
- data/spec/unit/blueprints_spec.rb +44 -0
- data/spec/unit/buildable_spec.rb +37 -6
- data/spec/unit/configuration_spec.rb +11 -0
- data/spec/unit/context_spec.rb +100 -0
- data/spec/unit/dependency_spec.rb +24 -19
- data/spec/unit/eval_context_spec.rb +56 -0
- data/spec/unit/fixtures.rb +61 -0
- data/spec/unit/namespace_spec.rb +59 -11
- data/spec/unit/spec_helper.rb +8 -16
- data/test/blueprints_test.rb +40 -59
- data/test/test_helper.rb +6 -16
- data/test_all.sh +45 -0
- metadata +178 -61
- data/VERSION +0 -1
- data/lib/blueprints/core_ext.rb +0 -69
- data/lib/blueprints/file_context.rb +0 -37
- data/spec/active_record/fixtures/database.yml.example +0 -8
- data/spec/active_record/fixtures/fruit.rb +0 -3
- data/spec/active_record/fixtures/tree.rb +0 -4
- data/spec/active_record/spec_helper.rb +0 -37
- data/spec/no_db/blueprint.rb +0 -9
- data/spec/no_db/blueprints_spec.rb +0 -45
- data/spec/no_db/fixtures/fruit.rb +0 -15
- data/spec/no_db/spec_helper.rb +0 -14
- data/spec/test_all.sh +0 -39
@@ -1,10 +1,12 @@
|
|
1
1
|
module DescribeHelper
|
2
2
|
# Creates new before filter that builds blueprints before each spec.
|
3
|
+
# @param names (see Helper#build)
|
3
4
|
def build_blueprint(*names)
|
4
5
|
before { build_blueprint *names }
|
5
6
|
end
|
6
7
|
|
7
|
-
# Same as #build_blueprint except that you can use it to build same blueprint several times.
|
8
|
+
# Same as DescribeHelper#build_blueprint except that you can use it to build same blueprint several times.
|
9
|
+
# @param names (see Helper#build)
|
8
10
|
def build_blueprint!(*names)
|
9
11
|
before { build_blueprint! *names }
|
10
12
|
end
|
data/lib/blueprints/helper.rb
CHANGED
@@ -2,42 +2,74 @@ module Blueprints
|
|
2
2
|
# A helper module that should be included in test framework. Adds methods <tt>build</tt> and <tt>demolish</tt>
|
3
3
|
module Helper
|
4
4
|
# Builds one or more blueprints by their names. You can pass names as symbols or strings. You can also pass additional
|
5
|
-
# options hash which will be available by calling <tt>options</tt> in blueprint block. Returns result of blueprint block.
|
6
|
-
#
|
5
|
+
# options hash which will be available by calling <tt>options</tt> in blueprint block. Returns result of last blueprint block.
|
6
|
+
# @example build :apple and :orange blueprints.
|
7
7
|
# build :apple, :orange
|
8
|
-
#
|
9
|
-
# # build :apple scenario with additional options
|
8
|
+
# @example build :apple blueprint with additional options.
|
10
9
|
# build :apple => {:color => 'red'}
|
11
|
-
#
|
12
|
-
# # options can also be passed for several blueprints
|
10
|
+
# @example passing options to several blueprints.
|
13
11
|
# build :pear, :apple => {:color => 'red'}, :orange => {:color => 'orange'}
|
14
|
-
|
12
|
+
# @param [Array<Symbol, String, Hash>] names Names of blueprints/namespaces to build. Pass Hash if you want to pass additional options.
|
13
|
+
# @return Return value of last blueprint
|
14
|
+
def build(*names)
|
15
15
|
Namespace.root.build(names, self, true)
|
16
16
|
end
|
17
17
|
|
18
|
-
# Same as #
|
19
|
-
|
20
|
-
|
18
|
+
# Same as #build except that you can use it to build same blueprint several times.
|
19
|
+
# @overload build!(*names)
|
20
|
+
# @param [Array<Symbol, String, Hash>] names Names of blueprints/namespaces to build. Pass Hash if you want to pass additional options.
|
21
|
+
# @return Return value of last blueprint
|
22
|
+
# @overload build!(count, *names)
|
23
|
+
# @param [Integer] count Times to build passed blueprint
|
24
|
+
# @param [Array<Symbol, String, Hash>] names Names of blueprints/namespaces to build. Pass Hash if you want to pass additional options.
|
25
|
+
# @return [Array] Array of return values of last blueprint, which is same size as count that you pass
|
26
|
+
def build!(*names)
|
27
|
+
if names.first.is_a?(Integer)
|
28
|
+
(0...names.shift).collect { build! *names }
|
29
|
+
else
|
30
|
+
Namespace.root.build(names, self, false)
|
31
|
+
end
|
21
32
|
end
|
22
33
|
|
23
|
-
# Returns attributes that are used to build blueprint.
|
24
|
-
#
|
25
|
-
# blueprint
|
34
|
+
# Returns attributes that are used to build blueprint.
|
35
|
+
# @example Setting and retrieving attributes.
|
36
|
+
# # In blueprint.rb file
|
37
|
+
# attributes(:name => 'apple').blueprint :apple do
|
26
38
|
# Fruit.build attributes
|
27
|
-
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# # In spec/test file
|
42
|
+
# build_attributes :apple #=> {:name => 'apple'}
|
43
|
+
# @param [Symbol, String] name Name of blueprint/namespace.
|
44
|
+
# @return [Hash] Normalized attributes of blueprint/namespace
|
28
45
|
def build_attributes(name)
|
29
|
-
Namespace.root[name]
|
30
|
-
|
46
|
+
blueprint = Namespace.root[name]
|
47
|
+
blueprint.build_parents(Namespace.root.eval_context)
|
48
|
+
Namespace.root.eval_context.normalize_hash(blueprint.attributes).tap { Namespace.root.eval_context.copy_instance_variables(self) }
|
31
49
|
end
|
32
50
|
|
33
|
-
|
34
|
-
|
51
|
+
# Returns Blueprint::Dependency object that can be used to define dependencies on other blueprints.
|
52
|
+
# @example Building :post blueprint with different user.
|
53
|
+
# build :post => {:user => d(:admin)}
|
54
|
+
# @example Building :post blueprint by first building :user_profile with :name => 'John', then taking value of @profile and calling +user+ on it.
|
55
|
+
# build :post => {:user => d(:user_profile, :profile, :name => 'John').user}
|
56
|
+
# @see Blueprints::Dependency#initialize Blueprints::Dependency for accepted arguments.
|
57
|
+
# @return [Blueprints::Dependency] Dependency object that can be passed as option when building blueprint/namespace.
|
58
|
+
def d(*args)
|
59
|
+
Dependency.new(*args)
|
60
|
+
end
|
35
61
|
|
36
62
|
# Demolishes built blueprints (by default simply calls destroy method on result of blueprint, but can be customized).
|
37
|
-
#
|
63
|
+
# @example Demolish :apple and :pear blueprints
|
38
64
|
# demolish :apple, :pear
|
65
|
+
# @param [Array<Symbol, String>] names Names of blueprints/namespaces to demolish.
|
39
66
|
def demolish(*names)
|
40
|
-
names.each { |name| Namespace.root[name].demolish }
|
67
|
+
names.each { |name| Namespace.root[name].demolish(Namespace.root.eval_context) }
|
41
68
|
end
|
69
|
+
|
70
|
+
alias :build_blueprint :build
|
71
|
+
alias :build_blueprint! :build!
|
72
|
+
alias :blueprint_dependency :d
|
73
|
+
alias :blueprint_demolish :demolish
|
42
74
|
end
|
43
75
|
end
|
data/lib/blueprints/namespace.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Blueprints
|
2
|
-
# Namespace class, inherits from
|
2
|
+
# Namespace class, inherits from Buildable. Allows adding and finding child blueprints/namespaces and building
|
3
3
|
# all it's children.
|
4
4
|
class Namespace < Buildable
|
5
5
|
cattr_accessor :root
|
@@ -7,20 +7,27 @@ module Blueprints
|
|
7
7
|
delegate :empty?, :size, :to => :@children
|
8
8
|
|
9
9
|
# Creates namespace by name. See Buildable#new.
|
10
|
-
|
11
|
-
|
10
|
+
# @param name (see Buildable#initialize)
|
11
|
+
# @param context (see Buildable#initialize)
|
12
|
+
def initialize(name, context)
|
12
13
|
@children = {}
|
14
|
+
super(name, context)
|
13
15
|
end
|
14
16
|
|
15
|
-
# Adds child to namespaces children.
|
17
|
+
# Adds child to namespaces children. Warns if this will overwrite existing child.
|
18
|
+
# @param [Blueprints::Buildable] child Namespace or blueprint to add as a child.
|
16
19
|
def add_child(child)
|
20
|
+
Blueprints.warn("Overwriting existing blueprint", child) if @children[child.name]
|
17
21
|
@children[child.name] = child
|
18
|
-
child.namespace = self
|
19
22
|
end
|
20
23
|
|
21
|
-
# Finds child by relative name.
|
24
|
+
# Finds child by relative name.
|
25
|
+
# @param [String] path Path to child. Path parts should be joined with '.' symbol.
|
26
|
+
# @return [Blueprints::Buildable] Blueprint or namespace that matches path.
|
27
|
+
# @raise [BlueprintNotFoundError] If child can't be found.
|
22
28
|
def [](path)
|
23
29
|
child_name, path = path.to_s.split('.', 2)
|
30
|
+
|
24
31
|
child = @children[child_name.to_sym] or raise BlueprintNotFoundError, child_name
|
25
32
|
if path
|
26
33
|
child[path]
|
@@ -29,14 +36,26 @@ module Blueprints
|
|
29
36
|
end
|
30
37
|
end
|
31
38
|
|
32
|
-
# Builds all children and sets instance variable named by name of namespace with the results.
|
33
|
-
|
34
|
-
|
39
|
+
# Builds all children and sets an instance variable named by name of namespace with the results.
|
40
|
+
# @param eval_context (see Buildable#build)
|
41
|
+
# @param build_once (see Buildable#build)
|
42
|
+
# @param options (see Buildable#build)
|
43
|
+
# @return [Array] Results of all blueprints.
|
44
|
+
def build_self(eval_context, build_once, options)
|
45
|
+
result(eval_context) { @children.values.collect { |child| child.build(eval_context, build_once, options) }.uniq }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Demolishes all child blueprints and namespaces.
|
49
|
+
# @param [Blueprints::EvalContext] eval_context Eval context that this namespace was built in.
|
50
|
+
def demolish(eval_context)
|
51
|
+
@children.each_value { |blueprint| blueprint.demolish(eval_context) }
|
35
52
|
end
|
36
53
|
|
37
|
-
|
38
|
-
|
39
|
-
|
54
|
+
protected
|
55
|
+
|
56
|
+
def update_context(options)
|
57
|
+
@children.each_value { |child| child.update_context(options) }
|
58
|
+
super
|
40
59
|
end
|
41
60
|
end
|
42
61
|
end
|
@@ -1,68 +1,67 @@
|
|
1
|
+
|
1
2
|
module Blueprints
|
2
3
|
# Defines a root namespace that is used when no other namespace is. Apart from functionality in namespace it also allows
|
3
4
|
# building blueprints/namespaces by name. Is also used for copying instance variables between blueprints/contexts/global
|
4
5
|
# context.
|
5
6
|
class RootNamespace < Namespace
|
6
|
-
|
7
|
+
# Lists of executed blueprints (to prevent executing twice). Cleared before each test.
|
8
|
+
attr_reader :executed_blueprints
|
9
|
+
# Context that blueprints/namespaces are built against. Reset before each test.
|
10
|
+
attr_writer :eval_context
|
7
11
|
|
12
|
+
# Initialized new root context.
|
8
13
|
def initialize
|
9
14
|
@executed_blueprints = @global_executed_blueprints = []
|
10
15
|
@auto_iv_list = Set.new
|
11
16
|
|
12
|
-
super ''
|
17
|
+
super '', Context.new
|
13
18
|
end
|
14
19
|
|
15
|
-
# Loads all instance variables from global context to current one.
|
20
|
+
# Loads all instance variables from global context to current one. Creates new eval context.
|
16
21
|
def setup
|
22
|
+
@eval_context = EvalContext.new
|
17
23
|
(@executed_blueprints - @global_executed_blueprints).each(&:undo!)
|
18
24
|
@executed_blueprints = @global_executed_blueprints.clone
|
19
|
-
@context = Blueprints::Context.new
|
20
25
|
|
21
26
|
if Blueprints.config.transactions
|
22
|
-
Marshal.load(@global_variables).each { |name, value|
|
27
|
+
Marshal.load(@global_variables).each { |name, value| eval_context.instance_variable_set(name, value) }
|
23
28
|
else
|
24
29
|
build(Blueprints.config.prebuild)
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
28
|
-
# Copies all instance variables from current context to another one.
|
29
|
-
def copy_ivars(to)
|
30
|
-
@context.instance_variables.each do |iv|
|
31
|
-
to.instance_variable_set(iv, @context.instance_variable_get(iv))
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
33
|
# Sets up global context and executes prebuilt blueprints against it.
|
34
|
+
# @param [Array<Symbol, String>] blueprints Names of blueprints that are prebuilt.
|
36
35
|
def prebuild(blueprints)
|
37
|
-
@context = Blueprints::Context.new
|
38
36
|
build(blueprints) if blueprints
|
39
37
|
|
40
38
|
@global_executed_blueprints = @executed_blueprints
|
41
|
-
@global_variables = Marshal.dump(
|
39
|
+
@global_variables = Marshal.dump(eval_context.instance_variables.each_with_object({}) { |iv, hash| hash[iv] = eval_context.instance_variable_get(iv) })
|
42
40
|
end
|
43
41
|
|
44
42
|
# Builds blueprints that are passed against current context. Copies instance variables to context given if one is given.
|
45
|
-
|
43
|
+
# @param [Array<Symbol, String>] names List of blueprints/namespaces to build.
|
44
|
+
# @param current_context Object to copy instance variables from eval context after building to.
|
45
|
+
# @param build_once (see Buildable.build)
|
46
|
+
# @return Result of last blueprint/namespace.
|
47
|
+
def build(names, current_context = nil, build_once = true)
|
46
48
|
names = [names] unless names.is_a?(Array)
|
47
49
|
result = names.inject(nil) do |result, member|
|
48
50
|
if member.is_a?(Hash)
|
49
|
-
member.map { |name, options| self[name].build(build_once, options) }.last
|
51
|
+
member.map { |name, options| self[name].build(eval_context, build_once, options) }.last
|
50
52
|
else
|
51
|
-
self[member].build(build_once)
|
53
|
+
self[member].build(eval_context, build_once)
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
|
-
|
57
|
+
eval_context.copy_instance_variables(current_context) if current_context
|
56
58
|
result
|
57
59
|
end
|
58
60
|
|
59
|
-
#
|
60
|
-
#
|
61
|
-
def
|
62
|
-
|
63
|
-
@auto_iv_list << name
|
64
|
-
@context.instance_variable_set(name, value)
|
65
|
-
end
|
61
|
+
# Return current eval context or creates a new one.
|
62
|
+
# @return [Blueprints::EvalContext] Eval context to be used to build blueprints.
|
63
|
+
def eval_context
|
64
|
+
@eval_context ||= EvalContext.new
|
66
65
|
end
|
67
66
|
|
68
67
|
@@root = RootNamespace.new
|
@@ -1,19 +1,15 @@
|
|
1
|
-
blueprint :error do
|
2
|
-
raise 'error'
|
3
|
-
end
|
4
|
-
|
5
1
|
blueprint :apple do
|
6
|
-
Fruit.
|
2
|
+
Fruit.blueprint :species => 'apple'
|
7
3
|
end
|
8
4
|
|
9
5
|
blueprint :many_apples => [:apple, :apple, :apple]
|
10
6
|
|
11
7
|
blueprint :bananas_and_apples => :apple do
|
12
|
-
@banana = Fruit.
|
8
|
+
@banana = Fruit.blueprint :species => 'banana'
|
13
9
|
end
|
14
10
|
|
15
11
|
blueprint :orange do
|
16
|
-
Fruit.
|
12
|
+
Fruit.blueprint :species => 'orange'
|
17
13
|
end
|
18
14
|
|
19
15
|
blueprint :fruit => [:apple, :orange] do
|
@@ -25,11 +21,11 @@ blueprint :bananas_and_apples_and_oranges => [:bananas_and_apples, :orange] do
|
|
25
21
|
end
|
26
22
|
|
27
23
|
blueprint :cherry do
|
28
|
-
Fruit.
|
24
|
+
Fruit.blueprint :species => 'cherry', :average_diameter => 3
|
29
25
|
end
|
30
26
|
|
31
27
|
blueprint :big_cherry => :cherry do
|
32
|
-
Fruit.
|
28
|
+
Fruit.blueprint options.reverse_merge(:species => @cherry.species, :average_diameter => 7)
|
33
29
|
end
|
34
30
|
|
35
31
|
blueprint :cherry_basket => [:big_cherry, :cherry] do
|
@@ -49,15 +45,15 @@ end
|
|
49
45
|
|
50
46
|
Fruit.blueprint(:acorn, :species => 'Acorn', :tree => d(:oak))
|
51
47
|
blueprint :small_acorn do
|
52
|
-
@small_acorn = build :acorn => {:average_diameter => 1}
|
53
48
|
@small_acorn_options = options
|
49
|
+
build :acorn => {:average_diameter => 1}
|
54
50
|
end
|
55
51
|
blueprint(:huge_acorn => :huge_oak).extends(:acorn, :average_diameter => 100)
|
56
52
|
|
57
53
|
namespace :pitted => :pine do
|
58
54
|
Tree.blueprint :peach_tree, :name => 'pitted peach tree'
|
59
|
-
Fruit.blueprint
|
60
|
-
Fruit.blueprint
|
55
|
+
Fruit.blueprint :peach, :species => 'pitted peach', :tree => d(:'pitted.peach_tree')
|
56
|
+
Fruit.blueprint :acorn, :species => 'pitted acorn', :tree => d(:oak)
|
61
57
|
|
62
58
|
namespace :red => :orange do
|
63
59
|
Fruit.blueprint(:apple, :species => 'pitted red apple')
|
@@ -65,18 +61,19 @@ namespace :pitted => :pine do
|
|
65
61
|
end
|
66
62
|
|
67
63
|
blueprint :apple_with_params do
|
68
|
-
Fruit.
|
64
|
+
Fruit.blueprint options.reverse_merge(:species => 'apple')
|
69
65
|
end
|
70
66
|
|
71
|
-
namespace :attributes do
|
67
|
+
attributes(:average_diameter => 10, :species => 'fruit with attributes').namespace :attributes do
|
72
68
|
blueprint :cherry do
|
73
69
|
Fruit.blueprint attributes
|
74
70
|
end.attributes(:species => 'cherry')
|
75
71
|
|
76
72
|
Fruit.blueprint :shortened_cherry, :species => 'cherry'
|
77
73
|
|
78
|
-
Fruit.blueprint :
|
79
|
-
|
80
|
-
end.attributes(:average_diameter => 10, :species => 'fruit with attributes')
|
74
|
+
Fruit.blueprint :dependent_cherry, :tree => d(:pine, :the_pine)
|
75
|
+
end
|
81
76
|
|
82
77
|
blueprint :circular_reference => :circular_reference
|
78
|
+
|
79
|
+
Tree.blueprint :name => 'infered'
|
@@ -67,16 +67,30 @@ describe Blueprints do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
describe "build per describe" do
|
71
|
+
unless File.dirname(__FILE__) =~ /test$/
|
72
|
+
build_blueprint :apple
|
73
|
+
|
74
|
+
it "should have cherry" do
|
75
|
+
@apple.should_not be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should have correct cherry species" do
|
79
|
+
@apple.species.should == 'apple'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
70
84
|
describe 'with preloaded cherry scenario' do
|
71
85
|
it "should have correct size after changed by second test" do
|
72
86
|
@cherry.average_diameter.should == 3
|
73
|
-
@cherry.
|
87
|
+
@cherry.blueprint(:average_diameter => 1)
|
74
88
|
@cherry.average_diameter.should == 1
|
75
89
|
end
|
76
90
|
|
77
91
|
it "should have correct size" do
|
78
92
|
@cherry.average_diameter.should == 3
|
79
|
-
@cherry.
|
93
|
+
@cherry.blueprint(:average_diameter => 5)
|
80
94
|
@cherry.average_diameter.should == 5
|
81
95
|
end
|
82
96
|
|
@@ -94,7 +108,7 @@ describe Blueprints do
|
|
94
108
|
demolish :apple
|
95
109
|
Fruit.all.should_not include(@apple)
|
96
110
|
build :apple
|
97
|
-
Fruit.
|
111
|
+
Fruit.all.should include(@apple)
|
98
112
|
end
|
99
113
|
|
100
114
|
it "should overwrite auto created instance variable with another auto created one" do
|
@@ -120,11 +134,11 @@ describe Blueprints do
|
|
120
134
|
end
|
121
135
|
|
122
136
|
it "should create only one apple" do
|
123
|
-
Fruit.all(:conditions =>
|
137
|
+
Fruit.all(:conditions => {:species => "apple"}).size.should == 1
|
124
138
|
end
|
125
139
|
|
126
140
|
it "should create only two cherries even if they were preloaded" do
|
127
|
-
Fruit.all(:conditions =>
|
141
|
+
Fruit.all(:conditions => {:species => "cherry"}).size.should == 2
|
128
142
|
end
|
129
143
|
|
130
144
|
it "should contain cherries in basket if basket is loaded in test and cherries preloaded" do
|
@@ -132,26 +146,6 @@ describe Blueprints do
|
|
132
146
|
end
|
133
147
|
end
|
134
148
|
|
135
|
-
describe 'transactions' do
|
136
|
-
before do
|
137
|
-
build :apple
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should drop only inner transaction" do
|
141
|
-
@apple.reload.should_not be_nil
|
142
|
-
begin
|
143
|
-
ActiveRecord::Base.transaction do
|
144
|
-
f = Fruit.create(:species => 'orange')
|
145
|
-
f.reload.should_not be_nil
|
146
|
-
raise 'some error'
|
147
|
-
end
|
148
|
-
rescue
|
149
|
-
end
|
150
|
-
@apple.reload.should_not be_nil
|
151
|
-
Fruit.find_by_species('orange').should be_nil
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
149
|
describe 'errors' do
|
156
150
|
it 'should raise ScenarioNotFoundError when scenario could not be found' do
|
157
151
|
lambda {
|
@@ -164,12 +158,6 @@ describe Blueprints do
|
|
164
158
|
build :parent_not_existing
|
165
159
|
}.should raise_error(Blueprints::BlueprintNotFoundError)
|
166
160
|
end
|
167
|
-
|
168
|
-
it 'should raise TypeError when scenario name is not symbol or string' do
|
169
|
-
lambda {
|
170
|
-
Blueprints::Blueprint.new(1, __FILE__)
|
171
|
-
}.should raise_error(TypeError, "Pass blueprint names as strings or symbols only, cannot define blueprint 1")
|
172
|
-
end
|
173
161
|
end
|
174
162
|
|
175
163
|
describe 'with active record blueprints extensions' do
|
@@ -202,7 +190,7 @@ describe Blueprints do
|
|
202
190
|
|
203
191
|
it "should normalize attributes when updating with blueprint method" do
|
204
192
|
build :cherry, :oak
|
205
|
-
|
193
|
+
build :cherry => {:tree => d(:oak)}
|
206
194
|
@cherry.tree.should == @oak
|
207
195
|
end
|
208
196
|
|
@@ -213,8 +201,7 @@ describe Blueprints do
|
|
213
201
|
end
|
214
202
|
|
215
203
|
it "should allow to pass array of hashes to blueprint method" do
|
216
|
-
Fruit.
|
217
|
-
fruits = Fruit.blueprint([{:species => 'fruit1'}, {:species => 'fruit2'}])
|
204
|
+
fruits = Fruit.blueprint({:species => 'fruit1'}, {:species => 'fruit2'})
|
218
205
|
fruits.collect(&:species).should == %w{fruit1 fruit2}
|
219
206
|
end
|
220
207
|
|
@@ -331,23 +318,27 @@ describe Blueprints do
|
|
331
318
|
end
|
332
319
|
end
|
333
320
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
321
|
+
describe "build!" do
|
322
|
+
it "should allow to building same blueprint again" do
|
323
|
+
build! :big_cherry, :big_cherry => {:species => 'not so big cherry'}
|
324
|
+
Fruit.count.should == 4
|
325
|
+
Fruit.first(:conditions => {:species => 'not so big cherry'}).should_not be_nil
|
326
|
+
end
|
339
327
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
328
|
+
it "should allow building same blueprint n times" do
|
329
|
+
oaks = build! 5, :oak
|
330
|
+
oaks.should have(5).items
|
331
|
+
oaks.each do |oak|
|
332
|
+
oak.should be_instance_of(Tree)
|
333
|
+
oak.name.should == 'Oak'
|
334
|
+
end
|
335
|
+
end
|
345
336
|
end
|
346
337
|
|
347
338
|
describe 'attributes' do
|
348
339
|
it "should allow to extract attributes from blueprint" do
|
349
|
-
build_attributes('attributes.cherry').should == {:species => 'cherry'}
|
350
|
-
build_attributes('attributes.shortened_cherry').should == {:species => 'cherry'}
|
340
|
+
build_attributes('attributes.cherry').should == {:species => 'cherry', :average_diameter => 10}
|
341
|
+
build_attributes('attributes.shortened_cherry').should == {:species => 'cherry', :average_diameter => 10}
|
351
342
|
build_attributes(:big_cherry).should == {}
|
352
343
|
end
|
353
344
|
|
@@ -367,13 +358,7 @@ describe Blueprints do
|
|
367
358
|
end
|
368
359
|
|
369
360
|
it "should return build attributes for dependencies" do
|
370
|
-
attrs = build_attributes('attributes.
|
371
|
-
@the_pine.should_not be_nil
|
372
|
-
attrs[:tree].should == @the_pine
|
373
|
-
end
|
374
|
-
|
375
|
-
it "should return build attributes for :@var" do
|
376
|
-
attrs = build_attributes('attributes.dependent_cherry2')
|
361
|
+
attrs = build_attributes('attributes.dependent_cherry')
|
377
362
|
@the_pine.should_not be_nil
|
378
363
|
attrs[:tree].should == @the_pine
|
379
364
|
end
|
@@ -383,11 +368,7 @@ describe Blueprints do
|
|
383
368
|
build :circular_reference
|
384
369
|
end
|
385
370
|
|
386
|
-
it "should
|
387
|
-
|
388
|
-
build :error
|
389
|
-
rescue RuntimeError => e
|
390
|
-
e.backtrace[0].should == "spec/active_record/blueprint.rb:2:in blueprint 'error'"
|
391
|
-
end
|
371
|
+
it "should allow inferring blueprint name" do
|
372
|
+
build(:infered).name.should == 'infered'
|
392
373
|
end
|
393
374
|
end
|