blueprints 0.7.3 → 0.8.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/README.rdoc +6 -11
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/blueprints.gemspec +14 -4
- data/lib/blueprints/blueprint.rb +31 -2
- data/lib/blueprints/buildable.rb +18 -20
- data/lib/blueprints/configuration.rb +0 -11
- data/lib/blueprints/core_ext.rb +69 -0
- data/lib/blueprints/dependency.rb +35 -0
- data/lib/blueprints/errors.rb +17 -5
- data/lib/blueprints/extensions/rspec.rb +16 -0
- data/lib/blueprints/file_context.rb +3 -4
- data/lib/blueprints/helper.rb +4 -18
- data/lib/blueprints/namespace.rb +5 -0
- data/lib/blueprints/root_namespace.rb +9 -9
- data/lib/blueprints.rb +22 -14
- data/spec/active_record/blueprint.rb +2 -1
- data/spec/active_record/blueprints_spec.rb +15 -48
- data/spec/active_record/spec_helper.rb +0 -1
- data/spec/no_db/blueprint.rb +3 -1
- data/spec/no_db/blueprints_spec.rb +20 -1
- data/spec/no_db/fixtures/fruit.rb +7 -0
- data/spec/no_db/spec_helper.rb +0 -1
- data/spec/test_all.sh +6 -3
- data/spec/unit/active_record_spec.rb +17 -0
- data/spec/unit/blueprint_spec.rb +58 -0
- data/spec/unit/buildable_spec.rb +14 -0
- data/spec/unit/configuration_spec.rb +1 -12
- data/spec/unit/dependency_spec.rb +39 -0
- data/spec/unit/namespace_spec.rb +23 -0
- data/spec/unit/spec_helper.rb +9 -0
- data/test/blueprints_test.rb +46 -49
- metadata +17 -7
- data/lib/blueprints/database_backends/active_record.rb +0 -48
- data/lib/blueprints/extensions/deprecated.rb +0 -22
data/README.rdoc
CHANGED
@@ -113,19 +113,15 @@ You can just type:
|
|
113
113
|
|
114
114
|
If you need to make associations then:
|
115
115
|
|
116
|
-
SomeModel.blueprint
|
116
|
+
SomeModel.blueprint(:something, :associated_column => d(:some_blueprint))
|
117
117
|
|
118
|
-
|
118
|
+
...or if the name of blueprint and the name of instance variable are not the same:
|
119
119
|
|
120
|
-
|
120
|
+
SomeModel.blueprint(:something, :associated_column => d(:some_blueprint, :some_instance_variable))
|
121
121
|
|
122
|
-
...
|
122
|
+
...and when you need to pass options to associated blueprint:
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
...or if name of blueprint that this one depends on and instance variable association uses are the same...
|
127
|
-
|
128
|
-
SomeModel.blueprint(:something, :associated_column => d(:some_blueprint)) # I prefer this one
|
124
|
+
SomeModel.blueprint(:something, :associated_column => d(:some_blueprint, :option => 'value'))
|
129
125
|
|
130
126
|
You can learn more about blueprint method in http://wiki.github.com/sinsiliux/blueprints/method-blueprint
|
131
127
|
|
@@ -148,11 +144,10 @@ which resets database to the state before the test. This state is empty database
|
|
148
144
|
|
149
145
|
== TODO
|
150
146
|
|
151
|
-
* Add ability to revert one blueprint.
|
152
147
|
* Add preloading blueprints for whole block of tests.
|
153
148
|
* Fix rake tasks
|
154
149
|
* Add merb support
|
155
|
-
* Add support for other test frameworks
|
150
|
+
* Add support for other test frameworks
|
156
151
|
|
157
152
|
== Credits
|
158
153
|
|
data/Rakefile
CHANGED
@@ -56,6 +56,8 @@ task :rspec_to_test do
|
|
56
56
|
data.gsub!(/(\s+)lambda \{\n(.*)\n(\s+)\}.should raise_error\((.*)\)/, "\\1assert_raise(\\4) do\n\\2\n\\3end")
|
57
57
|
# should =~ => assert_similar
|
58
58
|
data.gsub!(/^(\s+)(.*)\.should\s*=~\s*(.*)/, '\1assert_similar(\2, \3)')
|
59
|
+
# A.should_not include(B) => assert_false(A.include?(B))
|
60
|
+
data.gsub!(/^(\s+)(.*)\.should_not\s*include\((.*)\)/, '\1assert(!\2.include?(\3))')
|
59
61
|
|
60
62
|
# .should_not => assert(!())
|
61
63
|
data.gsub!(/^(\s+)(.*)\.should_not(.*)/, '\1assert(!(\2\3))')
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.8.0
|
data/blueprints.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{blueprints}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.8.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Andrius Chamentauskas"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-08-13}
|
13
13
|
s.default_executable = %q{blueprintify}
|
14
14
|
s.description = %q{Another replacement for factories and fixtures. The library that lazy typists will love}
|
15
15
|
s.email = %q{sinsiliux@gmail.com}
|
@@ -38,10 +38,10 @@ Gem::Specification.new do |s|
|
|
38
38
|
"lib/blueprints/context.rb",
|
39
39
|
"lib/blueprints/convertable.rb",
|
40
40
|
"lib/blueprints/convertable/fixtures.rb",
|
41
|
-
"lib/blueprints/
|
41
|
+
"lib/blueprints/core_ext.rb",
|
42
|
+
"lib/blueprints/dependency.rb",
|
42
43
|
"lib/blueprints/errors.rb",
|
43
44
|
"lib/blueprints/extensions/cucumber.rb",
|
44
|
-
"lib/blueprints/extensions/deprecated.rb",
|
45
45
|
"lib/blueprints/extensions/rspec.rb",
|
46
46
|
"lib/blueprints/extensions/test_unit.rb",
|
47
47
|
"lib/blueprints/file_context.rb",
|
@@ -60,7 +60,12 @@ Gem::Specification.new do |s|
|
|
60
60
|
"spec/no_db/fixtures/fruit.rb",
|
61
61
|
"spec/no_db/spec_helper.rb",
|
62
62
|
"spec/test_all.sh",
|
63
|
+
"spec/unit/active_record_spec.rb",
|
64
|
+
"spec/unit/blueprint_spec.rb",
|
65
|
+
"spec/unit/buildable_spec.rb",
|
63
66
|
"spec/unit/configuration_spec.rb",
|
67
|
+
"spec/unit/dependency_spec.rb",
|
68
|
+
"spec/unit/namespace_spec.rb",
|
64
69
|
"spec/unit/spec_helper.rb",
|
65
70
|
"test/blueprints_test.rb",
|
66
71
|
"test/test_helper.rb",
|
@@ -76,8 +81,13 @@ Gem::Specification.new do |s|
|
|
76
81
|
"spec/no_db/spec_helper.rb",
|
77
82
|
"spec/no_db/blueprints_spec.rb",
|
78
83
|
"spec/no_db/blueprint.rb",
|
84
|
+
"spec/unit/active_record_spec.rb",
|
85
|
+
"spec/unit/blueprint_spec.rb",
|
79
86
|
"spec/unit/spec_helper.rb",
|
80
87
|
"spec/unit/configuration_spec.rb",
|
88
|
+
"spec/unit/namespace_spec.rb",
|
89
|
+
"spec/unit/buildable_spec.rb",
|
90
|
+
"spec/unit/dependency_spec.rb",
|
81
91
|
"spec/active_record/fixtures/fruit.rb",
|
82
92
|
"spec/active_record/fixtures/tree.rb",
|
83
93
|
"spec/active_record/fixtures/schema.rb",
|
data/lib/blueprints/blueprint.rb
CHANGED
@@ -6,12 +6,22 @@ module Blueprints
|
|
6
6
|
def initialize(name, file, &block)
|
7
7
|
@file = file
|
8
8
|
super(name)
|
9
|
+
|
10
|
+
ivname = :"@#{path}"
|
9
11
|
@block = block
|
12
|
+
@demolish_block = lambda { instance_variable_get(ivname).destroy }
|
13
|
+
@update_block = lambda { instance_variable_get(ivname).blueprint(options) }
|
10
14
|
end
|
11
15
|
|
12
16
|
# Builds blueprint and adds it to executed blueprint hash. Setups instance variable with same name as blueprint if it is not defined yet.
|
13
17
|
def build_self(build_once = true)
|
14
|
-
surface_errors
|
18
|
+
surface_errors do
|
19
|
+
if built? and build_once
|
20
|
+
Namespace.root.context.instance_eval(&@update_block) if RootNamespace.root.context.options.present?
|
21
|
+
elsif @block
|
22
|
+
@result = Namespace.root.context.instance_eval(&@block)
|
23
|
+
end
|
24
|
+
end
|
15
25
|
end
|
16
26
|
|
17
27
|
# Changes blueprint block to build another blueprint by passing additional options to it. Usually used to dry up
|
@@ -22,7 +32,26 @@ module Blueprints
|
|
22
32
|
end
|
23
33
|
|
24
34
|
def backtrace(trace)
|
25
|
-
trace.collect {|line| line.sub(/^\(eval\):(\d+).*/, "#{@file}:\\1:in blueprint '#{@name}'") }
|
35
|
+
trace.collect { |line| line.sub(/^\(eval\):(\d+).*/, "#{@file}:\\1:in blueprint '#{@name}'") }
|
36
|
+
end
|
37
|
+
|
38
|
+
# If block is passed then sets custom demolish block for this blueprint.
|
39
|
+
# If no block is passed then calls demolish block and marks blueprint as not built.
|
40
|
+
# Raises DemolishError if blueprints has not been built.
|
41
|
+
def demolish(&block)
|
42
|
+
if block
|
43
|
+
@demolish_block = block
|
44
|
+
elsif built?
|
45
|
+
Namespace.root.context.instance_eval(&@demolish_block)
|
46
|
+
undo!
|
47
|
+
else
|
48
|
+
raise DemolishError, @name
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Allows customizing what happens when blueprint is already built and it's being built again.
|
53
|
+
def update(&block)
|
54
|
+
@update_block = block
|
26
55
|
end
|
27
56
|
|
28
57
|
private
|
data/lib/blueprints/buildable.rb
CHANGED
@@ -1,13 +1,5 @@
|
|
1
1
|
module Blueprints
|
2
2
|
class Buildable
|
3
|
-
class Dependency < Struct.new(:name) # :nodoc:
|
4
|
-
alias :to_sym :name
|
5
|
-
|
6
|
-
def iv_name
|
7
|
-
:"@#{name}"
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
3
|
attr_reader :name
|
12
4
|
attr_accessor :namespace
|
13
5
|
|
@@ -31,15 +23,12 @@ module Blueprints
|
|
31
23
|
|
32
24
|
# Builds dependencies of blueprint and then blueprint itself.
|
33
25
|
#
|
34
|
-
# +build_once+ - pass false if you want to build
|
26
|
+
# +build_once+ - pass false if you want to build blueprint again instead of updating old one.
|
35
27
|
#
|
36
28
|
# +options+ - list of options to be accessible in the body of a blueprint. Defaults to empty Hash.
|
37
29
|
def build(build_once = true, options = {})
|
38
|
-
if
|
39
|
-
|
40
|
-
return @result
|
41
|
-
end
|
42
|
-
Namespace.root.executed_blueprints << path
|
30
|
+
return @result if (built? or Namespace.root.executed_blueprints.include? self) and build_once and options.blank?
|
31
|
+
Namespace.root.executed_blueprints << self
|
43
32
|
|
44
33
|
each_namespace {|namespace| namespace.build_parents }
|
45
34
|
build_parents
|
@@ -53,6 +42,17 @@ module Blueprints
|
|
53
42
|
Namespace.root.add_variable(path, @result)
|
54
43
|
end
|
55
44
|
|
45
|
+
# Returns if blueprint has been built
|
46
|
+
def built?
|
47
|
+
instance_variable_defined?(:@result)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Marks blueprint as not built
|
51
|
+
def undo!
|
52
|
+
remove_instance_variable(:@result) if built?
|
53
|
+
Namespace.root.executed_blueprints.delete self
|
54
|
+
end
|
55
|
+
|
56
56
|
# If value is passed then it sets attributes for this buildable object.
|
57
57
|
# Otherwise returns attributes (defaulting to empty Hash)
|
58
58
|
def attributes(value)
|
@@ -69,13 +69,11 @@ module Blueprints
|
|
69
69
|
def self.normalize_attributes(attributes)
|
70
70
|
attributes = attributes.dup
|
71
71
|
attributes.each do |attr, value|
|
72
|
-
if value.is_a?(Blueprints::
|
73
|
-
|
74
|
-
|
72
|
+
attributes[attr] = value.value if value.is_a?(Blueprints::Dependency)
|
73
|
+
if value.is_a? Symbol and value.to_s =~ /^@.+$/
|
74
|
+
STDERR.puts "DEPRECATION WARNING: :@variables are deprecated in favor of `d` method"
|
75
|
+
attributes[attr] = Blueprints::Namespace.root.context.instance_variable_get(value)
|
75
76
|
end
|
76
|
-
iv_name = value if value.is_a? Symbol and value.to_s =~ /^@.+$/
|
77
|
-
|
78
|
-
attributes[attr] = Blueprints::Namespace.root.context.instance_variable_get(iv_name) if iv_name
|
79
77
|
end
|
80
78
|
end
|
81
79
|
|
@@ -9,8 +9,6 @@ module Blueprints
|
|
9
9
|
attr_reader :root
|
10
10
|
# By default blueprints runs each test in it's own transaction. This may sometimes be not desirable so this options allows to turn this off.
|
11
11
|
attr_accessor :transactions
|
12
|
-
# Returns ORM that is used, default is :active_record
|
13
|
-
attr_reader :orm
|
14
12
|
|
15
13
|
# Sets default attributes for all attributes
|
16
14
|
def initialize
|
@@ -26,15 +24,6 @@ module Blueprints
|
|
26
24
|
@root = defined?(Rails) ? Rails.root : Pathname.pwd
|
27
25
|
end
|
28
26
|
|
29
|
-
# Allows specifying what ORM should be used. See SUPPORTED_ORMS to check what values it can contain.
|
30
|
-
def orm=(value)
|
31
|
-
if SUPPORTED_ORMS.include?(value)
|
32
|
-
@orm = value
|
33
|
-
else
|
34
|
-
raise ArgumentError, "Unsupported ORM #{value.inspect}. Blueprints supports only #{SUPPORTED_ORMS.collect(&:inspect).join(', ')}"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
27
|
def filename=(value)
|
39
28
|
@filename = Array(value).flatten.collect {|path| Pathname.new(path) }
|
40
29
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Include this module into your class if you need klass.blueprint and object.blueprint methods.
|
2
|
+
module Blueprints::Blueprintable
|
3
|
+
module ClassMethods
|
4
|
+
# Two forms of this method can be used. First one is typically used inside blueprint block. Essentially it does
|
5
|
+
# same as <tt>create!</tt>, except it does bypass attr_protected and attr_accessible. It accepts only a hash or attributes,
|
6
|
+
# same as <tt>create!</tt> does.
|
7
|
+
# blueprint :post => [:user, :board] do
|
8
|
+
# @user.posts.blueprint(:title => 'first post', :text => 'My first post')
|
9
|
+
# end
|
10
|
+
# The second form is used when you want to define new blueprint. It takes first argument as name of blueprint
|
11
|
+
# and second one as hash of attributes. As you cannot use instance variables outside of blueprint block, you need
|
12
|
+
# to prefix them with colon. So the example above could be rewritten like this:
|
13
|
+
# Post.blueprint(:post, :title => 'first post', :text => 'My first post', :user => d(:user)).depends_on(:board)
|
14
|
+
def blueprint(name_or_attrs, attrs = {})
|
15
|
+
if Blueprints::FileContext.current
|
16
|
+
define_blueprint(name_or_attrs, attrs)
|
17
|
+
else
|
18
|
+
if name_or_attrs.is_a?(Array)
|
19
|
+
name_or_attrs.collect { |attrs| blueprint(attrs) }
|
20
|
+
else
|
21
|
+
blueprint_object(name_or_attrs)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def define_blueprint(name, attrs)
|
29
|
+
klass = self
|
30
|
+
blueprint = Blueprints::Blueprint.new(name, Blueprints::FileContext.current.file) { klass.blueprint attributes }
|
31
|
+
blueprint.attributes(attrs)
|
32
|
+
blueprint
|
33
|
+
end
|
34
|
+
|
35
|
+
def blueprint_object(attrs)
|
36
|
+
object = new
|
37
|
+
object.blueprint(attrs)
|
38
|
+
object
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.included(mod)
|
43
|
+
mod.extend Blueprints::Blueprintable::ClassMethods
|
44
|
+
end
|
45
|
+
|
46
|
+
# Updates attributes of object by calling setter methods.
|
47
|
+
def blueprint(attributes)
|
48
|
+
Blueprints::Blueprint.normalize_attributes(attributes).each do |attr, val|
|
49
|
+
send(:"#{attr}=", val)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Include this instead of Blueprints::Blueprintable if record needs to persist, includes Blueprints::Blueprintable
|
55
|
+
module Blueprints::Saveable
|
56
|
+
include Blueprints::Blueprintable
|
57
|
+
|
58
|
+
def self.included(mod)
|
59
|
+
mod.extend Blueprints::Blueprintable::ClassMethods
|
60
|
+
end
|
61
|
+
|
62
|
+
# Overrides object.blueprint to also call save!
|
63
|
+
def blueprint(attributes)
|
64
|
+
super(attributes)
|
65
|
+
save!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
::ActiveRecord::Base.send(:include, Blueprints::Saveable) if defined?(ActiveRecord)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Class for defining blueprint dependencies. Accepts up to 3 params:
|
2
|
+
# * name - pass the name of blueprint to build when trying to access value of this dependency.
|
3
|
+
# * iv_name (optional) - pass the name of instance variable to use for value. Defaults to same name as blueprint name.
|
4
|
+
# * options (optional) - pass options that are then passed to blueprint when building.
|
5
|
+
# Examples:
|
6
|
+
# Blueprints::Dependency.new(:blueprint).value # Builds blueprint 'blueprint' and returns value of @blueprint instance variable
|
7
|
+
# Blueprints::Dependency.new(:blueprint, value).value # Builds blueprint 'blueprint' and returns value of @value instance variable
|
8
|
+
# Blueprints::Dependency.new(:blueprint, :option => true).value # Builds blueprint 'blueprint' with options and returns value of @value instance variable
|
9
|
+
#
|
10
|
+
# Blueprints::Dependency objects also catch all missing methods. They are later replayed on instance variable when getting value. Example:
|
11
|
+
# d = Blueprints::Dependency.new(:blueprint).name.size
|
12
|
+
# d.value # => 4 when @blueprint.name == 'John'
|
13
|
+
class Blueprints::Dependency
|
14
|
+
# Initializes new copy of Blueprints::Dependency with name, iv_name and options.
|
15
|
+
def initialize(name, *args)
|
16
|
+
@name = name
|
17
|
+
@options = args.extract_options!
|
18
|
+
@iv_name = args.first || @name
|
19
|
+
@registry = []
|
20
|
+
end
|
21
|
+
|
22
|
+
# Builds blueprint (if necessary) and returns the value of instance variable.
|
23
|
+
def value
|
24
|
+
Blueprints::RootNamespace.root.build @name => @options
|
25
|
+
@registry.inject(Blueprints::RootNamespace.root.context.instance_variable_get(:"@#{@iv_name}")) do |value, (method, args, block)|
|
26
|
+
value.send(method, *args, &block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Catches all missing methods to later replay when asking for value.
|
31
|
+
def method_missing(method, *args, &block)
|
32
|
+
@registry << [method, args, block]
|
33
|
+
self
|
34
|
+
end
|
35
|
+
end
|
data/lib/blueprints/errors.rb
CHANGED
@@ -1,12 +1,24 @@
|
|
1
1
|
module Blueprints
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
@blueprints = args
|
2
|
+
class Error < StandardError
|
3
|
+
def initialize(blueprint)
|
4
|
+
@name = blueprint
|
6
5
|
end
|
7
6
|
|
8
7
|
def to_s
|
9
|
-
"Blueprint
|
8
|
+
"Blueprint '#{@name}' #{message_append}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class DemolishError < Error
|
13
|
+
def message_append
|
14
|
+
'must be built before demolishing'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Is raised when blueprint or namespace is not found.
|
19
|
+
class BlueprintNotFoundError < Error
|
20
|
+
def message_append
|
21
|
+
'not found'
|
10
22
|
end
|
11
23
|
end
|
12
24
|
end
|
@@ -1,6 +1,22 @@
|
|
1
|
+
module DescribeHelper
|
2
|
+
# Creates new before filter that builds blueprints before each spec.
|
3
|
+
def build_blueprint(*names)
|
4
|
+
before { build_blueprint *names }
|
5
|
+
end
|
6
|
+
|
7
|
+
# Same as #build_blueprint except that you can use it to build same blueprint several times.
|
8
|
+
def build_blueprint!(*names)
|
9
|
+
before { build_blueprint! *names }
|
10
|
+
end
|
11
|
+
|
12
|
+
alias :build :build_blueprint
|
13
|
+
alias :build! :build_blueprint!
|
14
|
+
end
|
15
|
+
|
1
16
|
config_class = defined?(RSpec) ? RSpec : Spec::Runner
|
2
17
|
config_class.configure do |config|
|
3
18
|
config.include(Blueprints::Helper)
|
19
|
+
config.extend(DescribeHelper)
|
4
20
|
config.before do
|
5
21
|
Blueprints.setup(self)
|
6
22
|
end
|
@@ -29,10 +29,9 @@ module Blueprints
|
|
29
29
|
namespace
|
30
30
|
end
|
31
31
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
Buildable::Dependency.new(name)
|
32
|
+
# Wrapper around Blueprints::Dependency.new. See Blueprints::Dependency for more information.
|
33
|
+
def d(*args)
|
34
|
+
Dependency.new(*args)
|
36
35
|
end
|
37
36
|
end
|
38
37
|
end
|
data/lib/blueprints/helper.rb
CHANGED
@@ -33,25 +33,11 @@ module Blueprints
|
|
33
33
|
alias :build :build_blueprint
|
34
34
|
alias :build! :build_blueprint!
|
35
35
|
|
36
|
-
#
|
37
|
-
# to remove scenarios from built scenarios cache.
|
36
|
+
# Demolishes built blueprints (by default simply calls destroy method on result of blueprint, but can be customized).
|
38
37
|
#
|
39
|
-
#
|
40
|
-
def demolish(*
|
41
|
-
|
42
|
-
options = args.extract_options!
|
43
|
-
args = (ActiveRecord::Base.connection.tables - ['schema_migrations']) if args.blank?
|
44
|
-
args.each {|table| ActiveRecord::Base.connection.execute("DELETE FROM #{table}") }
|
45
|
-
|
46
|
-
if options[:undo] == :all
|
47
|
-
Namespace.root.executed_blueprints.clear
|
48
|
-
else
|
49
|
-
undo = [options[:undo]].flatten.compact.collect(&:to_s)
|
50
|
-
unless (not_found = undo - Namespace.root.executed_blueprints.to_a).blank?
|
51
|
-
raise(BlueprintNotFoundError, not_found)
|
52
|
-
end
|
53
|
-
Namespace.root.executed_blueprints -= undo
|
54
|
-
end
|
38
|
+
# demolish :apple, :pear
|
39
|
+
def demolish(*names)
|
40
|
+
names.each { |name| Namespace.root[name].demolish }
|
55
41
|
end
|
56
42
|
end
|
57
43
|
end
|
data/lib/blueprints/namespace.rb
CHANGED
@@ -3,12 +3,10 @@ module Blueprints
|
|
3
3
|
# building blueprints/namespaces by name. Is also used for copying instance variables between blueprints/contexts/global
|
4
4
|
# context.
|
5
5
|
class RootNamespace < Namespace
|
6
|
-
attr_reader :context, :
|
7
|
-
attr_accessor :executed_blueprints
|
6
|
+
attr_reader :context, :executed_blueprints
|
8
7
|
|
9
8
|
def initialize
|
10
|
-
@executed_blueprints =
|
11
|
-
@global_executed_blueprints = Set.new
|
9
|
+
@executed_blueprints = @global_executed_blueprints = []
|
12
10
|
@auto_iv_list = Set.new
|
13
11
|
|
14
12
|
super ''
|
@@ -16,8 +14,10 @@ module Blueprints
|
|
16
14
|
|
17
15
|
# Loads all instance variables from global context to current one.
|
18
16
|
def setup
|
19
|
-
@
|
17
|
+
(@executed_blueprints - @global_executed_blueprints).each(&:undo!)
|
20
18
|
@executed_blueprints = @global_executed_blueprints.clone
|
19
|
+
@context = Blueprints::Context.new
|
20
|
+
|
21
21
|
if Blueprints.config.transactions
|
22
22
|
Marshal.load(@global_variables).each { |name, value| @context.instance_variable_set(name, value) }
|
23
23
|
else
|
@@ -35,10 +35,10 @@ module Blueprints
|
|
35
35
|
# Sets up global context and executes prebuilt blueprints against it.
|
36
36
|
def prebuild(blueprints)
|
37
37
|
@context = Blueprints::Context.new
|
38
|
-
|
39
|
-
@global_executed_blueprints = @executed_blueprints
|
38
|
+
build(blueprints) if blueprints
|
40
39
|
|
41
|
-
@
|
40
|
+
@global_executed_blueprints = @executed_blueprints
|
41
|
+
@global_variables = Marshal.dump(@context.instance_variables.each_with_object({}) { |iv, hash| hash[iv] = @context.instance_variable_get(iv) })
|
42
42
|
end
|
43
43
|
|
44
44
|
# Builds blueprints that are passed against current context. Copies instance variables to context given if one is given.
|
@@ -46,7 +46,7 @@ module Blueprints
|
|
46
46
|
names = [names] unless names.is_a?(Array)
|
47
47
|
result = names.inject(nil) do |result, member|
|
48
48
|
if member.is_a?(Hash)
|
49
|
-
member.map {|name, options| self[name].build(build_once, options) }.last
|
49
|
+
member.map { |name, options| self[name].build(build_once, options) }.last
|
50
50
|
else
|
51
51
|
self[member].build(build_once)
|
52
52
|
end
|
data/lib/blueprints.rb
CHANGED
@@ -4,9 +4,9 @@ require 'database_cleaner'
|
|
4
4
|
require 'set'
|
5
5
|
|
6
6
|
files = %w{
|
7
|
-
configuration context buildable namespace root_namespace blueprint file_context helper errors
|
7
|
+
configuration context buildable namespace root_namespace blueprint file_context helper errors dependency core_ext
|
8
8
|
}
|
9
|
-
files.each {|f| require File.join(File.dirname(__FILE__), 'blueprints', f) }
|
9
|
+
files.each { |f| require File.join(File.dirname(__FILE__), 'blueprints', f) }
|
10
10
|
|
11
11
|
module Blueprints
|
12
12
|
# Contains current configuration of blueprints
|
@@ -18,12 +18,12 @@ module Blueprints
|
|
18
18
|
def self.setup(current_context)
|
19
19
|
Namespace.root.setup
|
20
20
|
Namespace.root.copy_ivars(current_context)
|
21
|
-
DatabaseCleaner.start
|
21
|
+
if_orm { DatabaseCleaner.start }
|
22
22
|
end
|
23
23
|
|
24
24
|
# Rollbacks transaction returning everything to state before test. Should be called after every test case.
|
25
25
|
def self.teardown
|
26
|
-
DatabaseCleaner.clean
|
26
|
+
if_orm { DatabaseCleaner.clean }
|
27
27
|
end
|
28
28
|
|
29
29
|
# Enables blueprints support for RSpec or Test::Unit depending on whether (R)Spec is defined or not. Yields
|
@@ -36,7 +36,7 @@ module Blueprints
|
|
36
36
|
elsif defined? Spec or defined? RSpec
|
37
37
|
'rspec'
|
38
38
|
else
|
39
|
-
|
39
|
+
'test_unit'
|
40
40
|
end
|
41
41
|
require File.join(File.dirname(__FILE__), 'blueprints', 'extensions', extension)
|
42
42
|
end
|
@@ -45,12 +45,12 @@ module Blueprints
|
|
45
45
|
def self.load
|
46
46
|
return unless Namespace.root.empty?
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
if_orm do
|
49
|
+
DatabaseCleaner.clean_with :truncation
|
50
|
+
DatabaseCleaner.strategy = (config.transactions ? :transaction : :truncation)
|
51
|
+
end
|
51
52
|
load_scenarios_files(config.filename)
|
52
53
|
|
53
|
-
DatabaseCleaner.strategy = (config.transactions ? :transaction : :truncation) if config.orm
|
54
54
|
Namespace.root.prebuild(config.prebuild) if config.transactions
|
55
55
|
end
|
56
56
|
|
@@ -59,10 +59,10 @@ module Blueprints
|
|
59
59
|
root_sub = /^#{config.root}[\\\/]/
|
60
60
|
blueprints_path = File.dirname(__FILE__).sub(root_sub, '')
|
61
61
|
|
62
|
-
bc.add_filter {|line| line.sub(root_sub, '') }
|
62
|
+
bc.add_filter { |line| line.sub(root_sub, '') }
|
63
63
|
|
64
|
-
bc.add_silencer {|line| File.dirname(line).starts_with?(blueprints_path) }
|
65
|
-
bc.add_silencer {|line| Gem.path.any? {|path| File.dirname(line).starts_with?(path) } }
|
64
|
+
bc.add_silencer { |line| File.dirname(line).starts_with?(blueprints_path) }
|
65
|
+
bc.add_silencer { |line| Gem.path.any? { |path| File.dirname(line).starts_with?(path) } }
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -77,10 +77,18 @@ module Blueprints
|
|
77
77
|
def self.load_scenarios_files(patterns)
|
78
78
|
patterns.each do |pattern|
|
79
79
|
pattern = config.root.join(pattern)
|
80
|
-
Dir[pattern]
|
81
|
-
|
80
|
+
files = Dir[pattern.to_s]
|
81
|
+
files.each { |f| FileContext.new f }
|
82
|
+
return if files.size > 0
|
82
83
|
end
|
83
84
|
|
84
85
|
raise "Blueprints file not found! Put blueprints in #{patterns.join(' or ')} or pass custom filename pattern with :filename option"
|
85
86
|
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def self.if_orm
|
91
|
+
yield
|
92
|
+
rescue DatabaseCleaner::NoORMDetected, DatabaseCleaner::NoStrategySetError
|
93
|
+
end
|
86
94
|
end
|
@@ -44,6 +44,7 @@ Tree.blueprint(:oak_without_attributes)
|
|
44
44
|
|
45
45
|
blueprint :pine do
|
46
46
|
@the_pine = Tree.blueprint :name => 'Pine', :size => 'medium'
|
47
|
+
@pine = Tree.blueprint :name => 'Pine', :size => 'small'
|
47
48
|
end
|
48
49
|
|
49
50
|
Fruit.blueprint(:acorn, :species => 'Acorn', :tree => d(:oak))
|
@@ -74,7 +75,7 @@ namespace :attributes do
|
|
74
75
|
|
75
76
|
Fruit.blueprint :shortened_cherry, :species => 'cherry'
|
76
77
|
|
77
|
-
Fruit.blueprint :dependent_cherry1, :tree => d(:pine)
|
78
|
+
Fruit.blueprint :dependent_cherry1, :tree => d(:pine, :the_pine)
|
78
79
|
Fruit.blueprint(:dependent_cherry2, :tree => :@the_pine).depends_on(:pine)
|
79
80
|
end.attributes(:average_diameter => 10, :species => 'fruit with attributes')
|
80
81
|
|