blueprints 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +14 -1
  3. data/README.rdoc +3 -173
  4. data/Rakefile +32 -15
  5. data/blueprints.gemspec +2 -16
  6. data/lib/blueprints.rb +17 -10
  7. data/lib/blueprints/blueprint.rb +85 -41
  8. data/lib/blueprints/blueprint_name_proxy.rb +34 -0
  9. data/lib/blueprints/buildable.rb +53 -26
  10. data/lib/blueprints/context.rb +8 -0
  11. data/lib/blueprints/extensions.rb +22 -4
  12. data/lib/blueprints/extensions/rspec.rb +28 -14
  13. data/lib/blueprints/helper.rb +17 -9
  14. data/lib/blueprints/namespace.rb +20 -14
  15. data/lib/blueprints/railtie.rb +3 -0
  16. data/lib/blueprints/root_namespace.rb +16 -23
  17. data/lib/blueprints/version.rb +1 -1
  18. data/lib/generators/blueprints/model/model_generator.rb +29 -0
  19. data/spec/blueprints_spec.rb +18 -1
  20. data/spec/support/active_record/initializer.rb +9 -5
  21. data/spec/support/none/initializer.rb +4 -0
  22. data/spec/unit/active_record_spec.rb +58 -4
  23. data/spec/unit/blueprint_name_proxy_spec.rb +31 -0
  24. data/spec/unit/blueprint_spec.rb +160 -22
  25. data/spec/unit/blueprints_spec.rb +4 -4
  26. data/spec/unit/context_spec.rb +8 -1
  27. data/spec/unit/dependency_spec.rb +1 -5
  28. data/spec/unit/fixtures.rb +69 -47
  29. data/spec/unit/namespace_spec.rb +23 -5
  30. data/spec/unit/root_namespace_spec.rb +9 -0
  31. data/spec/unit/spec_helper.rb +3 -4
  32. data/test/blueprints_test.rb +18 -1
  33. data/test/test_helper.rb +1 -0
  34. data/test_all.sh +6 -33
  35. metadata +43 -276
  36. data/Gemfile.lock +0 -108
  37. data/lib/blueprints/database_cleaner_fix.rb +0 -9
  38. data/lib/blueprints/eval_context.rb +0 -51
  39. 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
@@ -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 blueprint and then blueprint itself.
51
- # @param [Blueprints::EvalContext] eval_context Context to build buildable object in.
52
- # @param [true, false] build_once Used if buildable is already built. If true then old one is updated else buildable is built again.
53
- # @param [Hash] options List of options to be accessible in the body of a blueprint.
54
- def build(eval_context, build_once = true, options = {})
55
- return result(eval_context) if @building or (built? and build_once and options.blank?)
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
- each_namespace { |namespace| namespace.build_parents(eval_context) }
59
- build_parents(eval_context)
60
-
61
- result = build_self(eval_context, build_once, options)
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
- (namespace.path(join_with) + join_with unless namespace.nil? or namespace.path.empty?).to_s + @name.to_s
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 [Blueprints::EvalContext] eval_context Context to build parents against.
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(eval_context)
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(eval_context)
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(eval_context)
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 eval_context.instance_variable_defined?(variable_name)
140
- eval_context.instance_variable_set(variable_name, result)
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
- eval_context.instance_variable_get(variable_name)
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
@@ -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) { klass.blueprint attributes }
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
- ActiveRecord::Base.send(:include, Blueprints::Extensions::Saveable) if defined?(ActiveRecord)
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(:append_inclusions, Blueprints::Extensions::DynamicSaveable) if defined?(MongoMapper)
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 DescribeHelper
2
- # Creates new before filter that builds blueprints before each spec.
3
- # @param names (see Helper#build)
4
- def build_blueprint(*names)
5
- before { build_blueprint *names }
6
- end
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
- # Same as DescribeHelper#build_blueprint except that you can use it to build same blueprint several times.
9
- # @param names (see Helper#build)
10
- def build_blueprint!(*names)
11
- before { build_blueprint! *names }
12
- end
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
- alias :build :build_blueprint
15
- alias :build! :build_blueprint!
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
@@ -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, true)
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 [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
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 [Array<Symbol, String, Hash>] names Names of blueprints/namespaces to build. Pass Hash if you want to pass additional options.
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, false)
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(Namespace.root.eval_context)
48
- Namespace.root.eval_context.normalize_hash(blueprint.attributes).tap { Namespace.root.eval_context.copy_instance_variables(self) }
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(Namespace.root.eval_context) }
75
+ names.each { |name| Namespace.root[name].demolish(self) }
68
76
  end
69
77
 
70
78
  alias :build_blueprint :build
@@ -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 [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) }
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
@@ -0,0 +1,3 @@
1
+ class Blueprints::Railtie < Rails::Railtie
2
+ config.app_generators.fixture_replacement :blueprints
3
+ end
@@ -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. Creates new eval context.
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| eval_context.instance_variable_set(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 global context and executes prebuilt blueprints against it.
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
- build(blueprints) if blueprints
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(eval_context.instance_variables.each_with_object({}) { |iv, hash| hash[iv] = eval_context.instance_variable_get(iv) })
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. Copies instance variables to context given if one is given.
41
+ # Builds blueprints that are passed against current context.
43
42
  # @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)
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, current_context = nil, build_once = true)
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, options| self[name].build(eval_context, build_once, options) }.last
51
+ member.map { |name, opts| self[name].build(environment, options.merge(:options => opts)) }.last
52
52
  else
53
- self[member].build(eval_context, build_once)
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