blueprints 0.9.0 → 1.0.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 +1 -0
- data/Gemfile +14 -1
- data/README.rdoc +3 -173
- data/Rakefile +32 -15
- data/blueprints.gemspec +2 -16
- data/lib/blueprints.rb +17 -10
- data/lib/blueprints/blueprint.rb +85 -41
- data/lib/blueprints/blueprint_name_proxy.rb +34 -0
- data/lib/blueprints/buildable.rb +53 -26
- data/lib/blueprints/context.rb +8 -0
- data/lib/blueprints/extensions.rb +22 -4
- data/lib/blueprints/extensions/rspec.rb +28 -14
- data/lib/blueprints/helper.rb +17 -9
- data/lib/blueprints/namespace.rb +20 -14
- data/lib/blueprints/railtie.rb +3 -0
- data/lib/blueprints/root_namespace.rb +16 -23
- data/lib/blueprints/version.rb +1 -1
- data/lib/generators/blueprints/model/model_generator.rb +29 -0
- data/spec/blueprints_spec.rb +18 -1
- data/spec/support/active_record/initializer.rb +9 -5
- data/spec/support/none/initializer.rb +4 -0
- data/spec/unit/active_record_spec.rb +58 -4
- data/spec/unit/blueprint_name_proxy_spec.rb +31 -0
- data/spec/unit/blueprint_spec.rb +160 -22
- data/spec/unit/blueprints_spec.rb +4 -4
- data/spec/unit/context_spec.rb +8 -1
- data/spec/unit/dependency_spec.rb +1 -5
- data/spec/unit/fixtures.rb +69 -47
- data/spec/unit/namespace_spec.rb +23 -5
- data/spec/unit/root_namespace_spec.rb +9 -0
- data/spec/unit/spec_helper.rb +3 -4
- data/test/blueprints_test.rb +18 -1
- data/test/test_helper.rb +1 -0
- data/test_all.sh +6 -33
- metadata +43 -276
- data/Gemfile.lock +0 -108
- data/lib/blueprints/database_cleaner_fix.rb +0 -9
- data/lib/blueprints/eval_context.rb +0 -51
- data/spec/unit/eval_context_spec.rb +0 -56
@@ -0,0 +1,34 @@
|
|
1
|
+
# Acts as a proxy to buildables with regexp names. Used for caching purposes. Remembers name used and always uses it later.
|
2
|
+
# Allows building and demolishing it's buildable.
|
3
|
+
class Blueprints::BlueprintNameProxy
|
4
|
+
# Initializes new instance of proxy.
|
5
|
+
# @param [Symbol] name Name of buildable that this proxy uses.
|
6
|
+
# @param [Blueprints::Buildable] buildable Buildable itself, that can later be built of demolished.
|
7
|
+
def initialize(name, buildable)
|
8
|
+
@buildable = buildable
|
9
|
+
@name = name
|
10
|
+
|
11
|
+
match_data = buildable.name.match(name.to_s)
|
12
|
+
names = match_data.names.collect(&:to_sym) if match_data.respond_to?(:names)
|
13
|
+
names = (0...match_data.captures.size).collect { |ind| :"arg#{ind}" } if names.blank?
|
14
|
+
@options = Hash[names.zip(match_data.captures)]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Allows building buildable. Merges regexp match data into options. If named regexp captures are used (Ruby 1.9 only),
|
18
|
+
# it will merge those names with appropriate values into options, otherwise options will be named arg0..n.
|
19
|
+
# @param environment (see Buildable#build)
|
20
|
+
# @param options (see Buildable#build)
|
21
|
+
# @return (see Buildable#build)
|
22
|
+
def build(environment, options = {})
|
23
|
+
options[:options] ||= {}
|
24
|
+
options[:options].merge!(@options)
|
25
|
+
options.merge!(:name => @name)
|
26
|
+
@buildable.build(environment, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Allows demolishing buildable. Uses remembered name to determine name of variable to call destroy on.
|
30
|
+
# @param [Object] environment Eval context that this buildable was built in.
|
31
|
+
def demolish(environment)
|
32
|
+
@buildable.demolish(environment, @name)
|
33
|
+
end
|
34
|
+
end
|
data/lib/blueprints/buildable.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Blueprints
|
2
2
|
class Buildable
|
3
|
+
BUILDING_MESSAGE = 'While building blueprint'
|
4
|
+
|
3
5
|
delegate :namespace, :dependencies, :to => :@context
|
4
6
|
attr_reader :name
|
5
7
|
|
@@ -11,10 +13,7 @@ module Blueprints
|
|
11
13
|
def initialize(name, context)
|
12
14
|
@context = context
|
13
15
|
|
14
|
-
if name.nil?
|
15
|
-
default_attribute = Blueprints.config.default_attributes.detect { |attribute| attributes.has_key?(attribute) }
|
16
|
-
name = attributes[default_attribute].parameterize('_') if default_attribute
|
17
|
-
end
|
16
|
+
name = self.class.infer_name(attributes) if name.nil?
|
18
17
|
@name, parents = parse_name(name)
|
19
18
|
depends_on(*parents)
|
20
19
|
|
@@ -47,22 +46,28 @@ module Blueprints
|
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
|
-
# Builds dependencies of
|
51
|
-
# @param [
|
52
|
-
# @param [
|
53
|
-
# @
|
54
|
-
|
55
|
-
|
49
|
+
# Builds dependencies of buildable and then buildable itself.
|
50
|
+
# @param [Object] environment Context to build buildable object in.
|
51
|
+
# @param [Hash] options List of options to build this buildable with.
|
52
|
+
# @option options [Hash] :options ({}) List of options to be accessible in the body of a blueprint.
|
53
|
+
# @option options [true, false] :rebuild (false) If true this buildable is treated as not built yet and is rebuilt even if it was built before.
|
54
|
+
# @option options [Symbol] :strategy (:default) Strategy to use when building.
|
55
|
+
# @option options [Symbol] :name Name of blueprint to use when building. Is usually passed for blueprints with regexp names.
|
56
|
+
def build(environment, options = {})
|
57
|
+
return result(environment) if @building or (built? and not options[:rebuild] and options[:options].blank?)
|
56
58
|
@building = true
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
result = nil
|
61
|
+
surface_errors do
|
62
|
+
each_namespace { |namespace| namespace.build_parents(environment) }
|
63
|
+
build_parents(environment)
|
64
|
+
result = build_self(environment, options)
|
65
|
+
end
|
62
66
|
Namespace.root.executed_blueprints << self
|
63
67
|
|
64
|
-
@building = false
|
65
68
|
result
|
69
|
+
ensure
|
70
|
+
@building = false
|
66
71
|
end
|
67
72
|
|
68
73
|
# Returns if blueprint has been built
|
@@ -78,9 +83,12 @@ module Blueprints
|
|
78
83
|
|
79
84
|
# Returns full path to this buildable
|
80
85
|
# @param [String] join_with Separator used to join names of parent namespaces and buildable itself.
|
86
|
+
# @param [#to_s] current_name Current name of this buildable. Used for regexp named buildables. Defaults to @name.
|
81
87
|
# @return [String] full path to this buildable joined with separator
|
82
|
-
def path(join_with = '_')
|
83
|
-
|
88
|
+
def path(join_with = '_', current_name = nil)
|
89
|
+
current_name ||= @name
|
90
|
+
namespace_path = namespace.path(join_with) if namespace
|
91
|
+
[namespace_path.presence, current_name].compact.join(join_with)
|
84
92
|
end
|
85
93
|
|
86
94
|
# Returns full name for this buildable
|
@@ -90,9 +98,9 @@ module Blueprints
|
|
90
98
|
end
|
91
99
|
|
92
100
|
# Builds all dependencies. Should be called before building itself. Searches dependencies first in parent then in root namespace.
|
93
|
-
# @param [
|
101
|
+
# @param [Object] environment Context to build parents against.
|
94
102
|
# @raise [Blueprints::BlueprintNotFoundError] If one of dependencies can't be found.
|
95
|
-
def build_parents(
|
103
|
+
def build_parents(environment)
|
96
104
|
@context.dependencies.each do |name|
|
97
105
|
parent = begin
|
98
106
|
namespace[name]
|
@@ -100,10 +108,18 @@ module Blueprints
|
|
100
108
|
Namespace.root[name]
|
101
109
|
end
|
102
110
|
|
103
|
-
parent.build(
|
111
|
+
parent.build(environment)
|
104
112
|
end
|
105
113
|
end
|
106
114
|
|
115
|
+
# Infers name of buildable using default attributes from Blueprints.config
|
116
|
+
# @param [Hash] attributes Attributes of buildable object to infer the name from.
|
117
|
+
# @return [String] Inferred name
|
118
|
+
def self.infer_name(attributes)
|
119
|
+
default_attribute = Blueprints.config.default_attributes.detect { |attribute| attributes.has_key?(attribute) }
|
120
|
+
attributes[default_attribute].parameterize('_') if default_attribute
|
121
|
+
end
|
122
|
+
|
107
123
|
protected
|
108
124
|
|
109
125
|
def each_namespace
|
@@ -111,8 +127,8 @@ module Blueprints
|
|
111
127
|
yield(namespace) while namespace = namespace.namespace
|
112
128
|
end
|
113
129
|
|
114
|
-
def variable_name
|
115
|
-
:"@#{path}"
|
130
|
+
def variable_name(current_name = nil)
|
131
|
+
:"@#{path('_', current_name || @name)}"
|
116
132
|
end
|
117
133
|
|
118
134
|
def parse_name(name)
|
@@ -121,6 +137,8 @@ module Blueprints
|
|
121
137
|
elsif name.respond_to?(:to_sym)
|
122
138
|
name = name.to_sym unless name == ''
|
123
139
|
return name, []
|
140
|
+
elsif name.is_a? Regexp
|
141
|
+
return name, []
|
124
142
|
else
|
125
143
|
raise TypeError, "Pass blueprint names as strings or symbols only, cannot define blueprint #{name.inspect}"
|
126
144
|
end
|
@@ -133,17 +151,26 @@ module Blueprints
|
|
133
151
|
|
134
152
|
private
|
135
153
|
|
136
|
-
def result(
|
154
|
+
def result(environment, current_name = nil)
|
155
|
+
variable_name = self.variable_name(current_name)
|
137
156
|
if block_given?
|
138
157
|
yield.tap do |result|
|
139
|
-
if @auto_variable or not
|
140
|
-
|
158
|
+
if @auto_variable or not environment.instance_variable_defined?(variable_name)
|
159
|
+
environment.instance_variable_set(variable_name, result)
|
141
160
|
@auto_variable = true
|
142
161
|
end
|
143
162
|
end
|
144
163
|
else
|
145
|
-
|
164
|
+
environment.instance_variable_get(variable_name)
|
146
165
|
end
|
147
166
|
end
|
167
|
+
|
168
|
+
def surface_errors
|
169
|
+
yield
|
170
|
+
rescue StandardError => error
|
171
|
+
insert_at = error.backtrace.index { |line| line !~ /^#{BUILDING_MESSAGE}/ }
|
172
|
+
error.backtrace.insert(insert_at, "#{BUILDING_MESSAGE} '#{path}'")
|
173
|
+
raise
|
174
|
+
end
|
148
175
|
end
|
149
176
|
end
|
data/lib/blueprints/context.rb
CHANGED
@@ -133,6 +133,14 @@ module Blueprints
|
|
133
133
|
Dependency.new(*args)
|
134
134
|
end
|
135
135
|
|
136
|
+
# Finds blueprint/namespace by it's path
|
137
|
+
# @param path (see Namespace#[])
|
138
|
+
# @return (see Namespace#[])
|
139
|
+
def find(path)
|
140
|
+
@namespace[path]
|
141
|
+
end
|
142
|
+
alias [] find
|
143
|
+
|
136
144
|
# Return current context.
|
137
145
|
# @return [Blueprints::Context] Current context.
|
138
146
|
def self.current
|
@@ -33,7 +33,7 @@ module Blueprints::Extensions
|
|
33
33
|
def blueprint(*args)
|
34
34
|
if Blueprints::Context.current
|
35
35
|
attrs = args.extract_options!
|
36
|
-
define_blueprint(args.first, attrs)
|
36
|
+
define_blueprint(args.first || Blueprints::Buildable.infer_name(attrs) || name.underscore, attrs)
|
37
37
|
else
|
38
38
|
objects = args.collect { |attrs| blueprint_object(attrs) }
|
39
39
|
args.size == 1 ? objects.first : objects
|
@@ -44,7 +44,11 @@ module Blueprints::Extensions
|
|
44
44
|
|
45
45
|
def define_blueprint(name, attrs)
|
46
46
|
klass = self
|
47
|
-
Blueprints::Context.current.attributes(attrs).blueprint(name)
|
47
|
+
Blueprints::Context.current.attributes(attrs).blueprint(name) do
|
48
|
+
klass.blueprint attributes
|
49
|
+
end.blueprint(:new) do
|
50
|
+
klass.new.tap { |object| object.blueprint_without_save(attributes) }
|
51
|
+
end
|
48
52
|
end
|
49
53
|
|
50
54
|
def blueprint_object(attrs)
|
@@ -59,6 +63,7 @@ module Blueprints::Extensions
|
|
59
63
|
blueprint_attribute attribute, value
|
60
64
|
end
|
61
65
|
end
|
66
|
+
alias blueprint_without_save blueprint
|
62
67
|
|
63
68
|
private
|
64
69
|
|
@@ -109,7 +114,20 @@ module Blueprints::Extensions
|
|
109
114
|
end
|
110
115
|
end
|
111
116
|
|
112
|
-
|
117
|
+
if defined?(ActiveRecord)
|
118
|
+
ActiveRecord::Base.send(:include, Blueprints::Extensions::Saveable)
|
119
|
+
# AssociationCollection for ActiveRecord 3.0, Collection::Association for ActiveRecord 3.1
|
120
|
+
collection_class = defined?(ActiveRecord::Associations::CollectionProxy) ? ActiveRecord::Associations::CollectionProxy : ActiveRecord::Associations::AssociationCollection
|
121
|
+
collection_class.class_eval do
|
122
|
+
include Blueprints::Extensions::Blueprintable::ClassMethods
|
123
|
+
|
124
|
+
def blueprint_object(attrs)
|
125
|
+
create! do |object|
|
126
|
+
object.blueprint_without_save(attrs)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
113
131
|
Mongoid::Document.send(:include, Blueprints::Extensions::DynamicSaveable) if defined?(Mongoid)
|
114
|
-
MongoMapper::Document.send(:
|
132
|
+
MongoMapper::Document.send(:plugin, Blueprints::Extensions::DynamicSaveable) if defined?(MongoMapper)
|
115
133
|
DataMapper::Model.send(:append_inclusions, Blueprints::Extensions::SoftSaveable) if defined?(DataMapper)
|
@@ -1,24 +1,38 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Blueprints
|
2
|
+
module DescribeHelper
|
3
|
+
# Creates new before filter that builds blueprints before each spec.
|
4
|
+
# @param names (see Helper#build)
|
5
|
+
def build_blueprint(*names)
|
6
|
+
before { build_blueprint *names }
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
# Same as DescribeHelper#build_blueprint except that you can use it to build same blueprint several times.
|
10
|
+
# @param names (see Helper#build)
|
11
|
+
def build_blueprint!(*names)
|
12
|
+
before { build_blueprint! *names }
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
# Returns Blueprint::Dependency object that can be used to define dependencies on other blueprints.
|
16
|
+
# @example Building :post blueprint with different user.
|
17
|
+
# build :post => {:user => d(:admin)}
|
18
|
+
# @example Building :post blueprint by first building :user_profile with :name => 'John', then taking value of @profile and calling +user+ on it.
|
19
|
+
# build :post => {:user => d(:user_profile, :profile, :name => 'John').user}
|
20
|
+
# @see Blueprints::Dependency#initialize Blueprints::Dependency for accepted arguments.
|
21
|
+
# @return [Blueprints::Dependency] Dependency object that can be passed as option when building blueprint/namespace.
|
22
|
+
def d(*args)
|
23
|
+
Dependency.new(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
alias :build :build_blueprint
|
27
|
+
alias :blueprint_dependency :d
|
28
|
+
alias :build! :build_blueprint!
|
29
|
+
end
|
16
30
|
end
|
17
31
|
|
18
32
|
config_class = defined?(RSpec) ? RSpec : Spec::Runner
|
19
33
|
config_class.configure do |config|
|
20
34
|
config.include(Blueprints::Helper)
|
21
|
-
config.extend(DescribeHelper)
|
35
|
+
config.extend(Blueprints::DescribeHelper)
|
22
36
|
config.before do
|
23
37
|
Blueprints.setup(self)
|
24
38
|
end
|
data/lib/blueprints/helper.rb
CHANGED
@@ -12,25 +12,33 @@ module Blueprints
|
|
12
12
|
# @param [Array<Symbol, String, Hash>] names Names of blueprints/namespaces to build. Pass Hash if you want to pass additional options.
|
13
13
|
# @return Return value of last blueprint
|
14
14
|
def build(*names)
|
15
|
-
Namespace.root.build(names, self
|
15
|
+
Namespace.root.build(names, self)
|
16
16
|
end
|
17
17
|
|
18
|
-
# Same as #build except that you can use it to build same blueprint several times.
|
18
|
+
# Same as Blueprints::Helper#build except that you can use it to build same blueprint several times.
|
19
19
|
# @overload build!(*names)
|
20
|
-
# @param
|
21
|
-
# @return
|
20
|
+
# @param names (see Helper#build)
|
21
|
+
# @return (see Helper#build)
|
22
22
|
# @overload build!(count, *names)
|
23
23
|
# @param [Integer] count Times to build passed blueprint
|
24
|
-
# @param
|
24
|
+
# @param names (see Helper#build)
|
25
25
|
# @return [Array] Array of return values of last blueprint, which is same size as count that you pass
|
26
26
|
def build!(*names)
|
27
27
|
if names.first.is_a?(Integer)
|
28
28
|
(0...names.shift).collect { build! *names }
|
29
29
|
else
|
30
|
-
Namespace.root.build(names, self,
|
30
|
+
Namespace.root.build(names, self, :rebuild => true)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
# Same as Blueprints::Helper#build except it also allows you to pass strategy to use (#build always uses default strategy).
|
35
|
+
# @param [Symbol] strategy Strategy to use when building blueprint/namespace.
|
36
|
+
# @param names (see Helper#build)
|
37
|
+
# @return (see Helper#build)
|
38
|
+
def build_with(strategy, *names)
|
39
|
+
Namespace.root.build(names, self, :strategy => strategy)
|
40
|
+
end
|
41
|
+
|
34
42
|
# Returns attributes that are used to build blueprint.
|
35
43
|
# @example Setting and retrieving attributes.
|
36
44
|
# # In blueprint.rb file
|
@@ -44,8 +52,8 @@ module Blueprints
|
|
44
52
|
# @return [Hash] Normalized attributes of blueprint/namespace
|
45
53
|
def build_attributes(name)
|
46
54
|
blueprint = Namespace.root[name]
|
47
|
-
blueprint.build_parents(
|
48
|
-
|
55
|
+
blueprint.build_parents(self)
|
56
|
+
blueprint.normalized_attributes(self)
|
49
57
|
end
|
50
58
|
|
51
59
|
# Returns Blueprint::Dependency object that can be used to define dependencies on other blueprints.
|
@@ -64,7 +72,7 @@ module Blueprints
|
|
64
72
|
# demolish :apple, :pear
|
65
73
|
# @param [Array<Symbol, String>] names Names of blueprints/namespaces to demolish.
|
66
74
|
def demolish(*names)
|
67
|
-
names.each { |name| Namespace.root[name].demolish(
|
75
|
+
names.each { |name| Namespace.root[name].demolish(self) }
|
68
76
|
end
|
69
77
|
|
70
78
|
alias :build_blueprint :build
|
data/lib/blueprints/namespace.rb
CHANGED
@@ -3,14 +3,18 @@ module Blueprints
|
|
3
3
|
# all it's children.
|
4
4
|
class Namespace < Buildable
|
5
5
|
cattr_accessor :root
|
6
|
-
attr_reader :children
|
7
6
|
delegate :empty?, :size, :to => :@children
|
8
7
|
|
9
8
|
# Creates namespace by name. See Buildable#new.
|
10
9
|
# @param name (see Buildable#initialize)
|
11
10
|
# @param context (see Buildable#initialize)
|
12
11
|
def initialize(name, context)
|
13
|
-
@children =
|
12
|
+
@children = Hash.new do |hash, search_key|
|
13
|
+
pair = hash.detect do |name,|
|
14
|
+
name.is_a?(Regexp) and search_key.to_s =~ name
|
15
|
+
end
|
16
|
+
hash[search_key] = BlueprintNameProxy.new(search_key, pair[1]) if pair
|
17
|
+
end
|
14
18
|
super(name, context)
|
15
19
|
end
|
16
20
|
|
@@ -21,6 +25,12 @@ module Blueprints
|
|
21
25
|
@children[child.name] = child
|
22
26
|
end
|
23
27
|
|
28
|
+
# Returns all direct children blueprints and namespaces of this namespace.
|
29
|
+
# @return [Array<Blueprints::Buildable>] Array of direct children
|
30
|
+
def children
|
31
|
+
@children.values
|
32
|
+
end
|
33
|
+
|
24
34
|
# Finds child by relative name.
|
25
35
|
# @param [String] path Path to child. Path parts should be joined with '.' symbol.
|
26
36
|
# @return [Blueprints::Buildable] Blueprint or namespace that matches path.
|
@@ -36,23 +46,19 @@ module Blueprints
|
|
36
46
|
end
|
37
47
|
end
|
38
48
|
|
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
49
|
# Demolishes all child blueprints and namespaces.
|
49
|
-
# @param [
|
50
|
-
def demolish(
|
51
|
-
@children.each_value { |blueprint| blueprint.demolish(
|
50
|
+
# @param [Object] environment Eval context that this namespace was built in.
|
51
|
+
def demolish(environment)
|
52
|
+
@children.each_value { |blueprint| blueprint.demolish(environment) }
|
52
53
|
end
|
53
54
|
|
54
55
|
protected
|
55
56
|
|
57
|
+
def build_self(environment, options)
|
58
|
+
children = Array(@children[:default] || @children.values)
|
59
|
+
result(environment) { children.collect { |child| child.build(environment, options) } }
|
60
|
+
end
|
61
|
+
|
56
62
|
def update_context(options)
|
57
63
|
@children.each_value { |child| child.update_context(options) }
|
58
64
|
super
|
@@ -6,8 +6,6 @@ module Blueprints
|
|
6
6
|
class RootNamespace < Namespace
|
7
7
|
# Lists of executed blueprints (to prevent executing twice). Cleared before each test.
|
8
8
|
attr_reader :executed_blueprints
|
9
|
-
# Context that blueprints/namespaces are built against. Reset before each test.
|
10
|
-
attr_writer :eval_context
|
11
9
|
|
12
10
|
# Initialized new root context.
|
13
11
|
def initialize
|
@@ -17,53 +15,48 @@ module Blueprints
|
|
17
15
|
super '', Context.new
|
18
16
|
end
|
19
17
|
|
20
|
-
# Loads all instance variables from global context to current one.
|
21
|
-
def setup
|
22
|
-
@eval_context = EvalContext.new
|
18
|
+
# Loads all instance variables from global context to current one.
|
19
|
+
def setup(environment)
|
23
20
|
(@executed_blueprints - @global_executed_blueprints).each(&:undo!)
|
24
21
|
@executed_blueprints = @global_executed_blueprints.clone
|
25
22
|
|
26
23
|
if Blueprints.config.transactions
|
27
|
-
Marshal.load(@global_variables).each { |name, value|
|
24
|
+
Marshal.load(@global_variables).each { |name, value| environment.instance_variable_set(name, value) }
|
28
25
|
else
|
29
|
-
build(Blueprints.config.prebuild)
|
26
|
+
build(Blueprints.config.prebuild, environment)
|
30
27
|
end
|
31
28
|
end
|
32
29
|
|
33
|
-
# Sets up
|
30
|
+
# Sets up a context and executes prebuilt blueprints against it.
|
34
31
|
# @param [Array<Symbol, String>] blueprints Names of blueprints that are prebuilt.
|
35
32
|
def prebuild(blueprints)
|
36
|
-
|
33
|
+
environment = Object.new
|
34
|
+
environment.extend Blueprints::Helper
|
35
|
+
build(blueprints, environment) if blueprints
|
37
36
|
|
38
37
|
@global_executed_blueprints = @executed_blueprints
|
39
|
-
@global_variables = Marshal.dump(
|
38
|
+
@global_variables = Marshal.dump(environment.instance_variables.each_with_object({}) { |iv, hash| hash[iv] = environment.instance_variable_get(iv) })
|
40
39
|
end
|
41
40
|
|
42
|
-
# Builds blueprints that are passed against current context.
|
41
|
+
# Builds blueprints that are passed against current context.
|
43
42
|
# @param [Array<Symbol, String>] names List of blueprints/namespaces to build.
|
44
|
-
# @param
|
45
|
-
# @param
|
43
|
+
# @param environment Object to build blueprints against.
|
44
|
+
# @param options (see Buildable#build)
|
45
|
+
# @option options (see Buildable#build)
|
46
46
|
# @return Result of last blueprint/namespace.
|
47
|
-
def build(names,
|
47
|
+
def build(names, environment, options = {})
|
48
48
|
names = [names] unless names.is_a?(Array)
|
49
49
|
result = names.inject(nil) do |result, member|
|
50
50
|
if member.is_a?(Hash)
|
51
|
-
member.map { |name,
|
51
|
+
member.map { |name, opts| self[name].build(environment, options.merge(:options => opts)) }.last
|
52
52
|
else
|
53
|
-
self[member].build(
|
53
|
+
self[member].build(environment, options)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
eval_context.copy_instance_variables(current_context) if current_context
|
58
57
|
result
|
59
58
|
end
|
60
59
|
|
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
|
65
|
-
end
|
66
|
-
|
67
60
|
@@root = RootNamespace.new
|
68
61
|
end
|
69
62
|
end
|