blueprints 0.8.2 → 0.9.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 +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
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
@orm, @version = (ENV['ORM'] || 'active_record').split('.', 2)
|
2
|
+
gem_mappings = {'active_record' => 'activerecord'}
|
3
|
+
gem gem_mappings[@orm], "~> #{@version}" if @version
|
4
|
+
require @orm unless @orm == 'none'
|
5
|
+
|
6
|
+
Root = Pathname.new(__FILE__).dirname.join('..')
|
7
|
+
$: << Root.to_s
|
8
|
+
|
9
|
+
require 'logger'
|
10
|
+
@logger_file = Root.join('debug.log')
|
11
|
+
@logger = Logger.new(@logger_file)
|
12
|
+
|
13
|
+
require 'lib/blueprints'
|
14
|
+
require "spec/support/#{@orm}/initializer"
|
15
|
+
|
16
|
+
config_class = if @rspec1
|
17
|
+
gem 'rspec', '~> 1.0'
|
18
|
+
require 'spec'
|
19
|
+
Spec::Runner
|
20
|
+
else
|
21
|
+
gem 'rspec', '>= 2.0.0.beta'
|
22
|
+
require 'rspec'
|
23
|
+
RSpec
|
24
|
+
end
|
25
|
+
|
26
|
+
config_class.configure do |config|
|
27
|
+
config.mock_with :mocha
|
28
|
+
end
|
29
|
+
|
30
|
+
Blueprints.enable do |config|
|
31
|
+
config.root = Root.join('spec')
|
32
|
+
config.prebuild = :big_cherry
|
33
|
+
config.transactions = @transactions
|
34
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Fruit < ActiveRecord::Base
|
2
|
+
belongs_to :tree
|
3
|
+
end
|
4
|
+
|
5
|
+
class Tree < ActiveRecord::Base
|
6
|
+
attr_protected :size
|
7
|
+
has_many :fruits
|
8
|
+
end
|
9
|
+
|
10
|
+
db_config = YAML::load(Root.join("spec/support/active_record/database.yml").read)
|
11
|
+
ActiveRecord::Base.establish_connection(db_config)
|
12
|
+
ActiveRecord::Base.logger = @logger
|
13
|
+
|
14
|
+
@rspec1 = @version.to_s[0, 1] == '2'
|
15
|
+
@transactions = true
|
File without changes
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Fruit
|
2
|
+
include DataMapper::Resource
|
3
|
+
|
4
|
+
property :id, Serial
|
5
|
+
property :species, String
|
6
|
+
property :average_diameter, Integer
|
7
|
+
|
8
|
+
belongs_to :tree, :required => false, :default => nil
|
9
|
+
end
|
10
|
+
|
11
|
+
class Tree
|
12
|
+
include DataMapper::Resource
|
13
|
+
|
14
|
+
property :id, Serial
|
15
|
+
property :name, String
|
16
|
+
property :size, String, :writer => :private
|
17
|
+
|
18
|
+
has n, :fruits
|
19
|
+
end
|
20
|
+
|
21
|
+
DataMapper::Model.raise_on_save_failure = true
|
22
|
+
|
23
|
+
require 'dm-transactions'
|
24
|
+
require 'dm-migrations'
|
25
|
+
|
26
|
+
DataMapper::Logger.new(@logger_file, :debug)
|
27
|
+
DataMapper.setup(:default, 'mysql://localhost/blueprints_test')
|
28
|
+
DataMapper.finalize
|
29
|
+
DataMapper.auto_migrate!
|
30
|
+
|
31
|
+
@transactions = true
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Fruit
|
2
|
+
include MongoMapper::Document
|
3
|
+
|
4
|
+
key :species, String
|
5
|
+
key :average_diameter, Integer
|
6
|
+
|
7
|
+
belongs_to :tree
|
8
|
+
end
|
9
|
+
|
10
|
+
class Tree
|
11
|
+
include MongoMapper::Document
|
12
|
+
|
13
|
+
key :size
|
14
|
+
|
15
|
+
attr_protected :size
|
16
|
+
many :fruits
|
17
|
+
end
|
18
|
+
|
19
|
+
MongoMapper.connection = Mongo::Connection.new('localhost')
|
20
|
+
MongoMapper.database = 'blueprints_test'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Fruit
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :species
|
5
|
+
field :average_diameter, :type => Integer
|
6
|
+
|
7
|
+
referenced_in :tree, :inverse_of => :fruits
|
8
|
+
end
|
9
|
+
|
10
|
+
class Tree
|
11
|
+
include Mongoid::Document
|
12
|
+
|
13
|
+
field :size
|
14
|
+
|
15
|
+
attr_protected :size
|
16
|
+
references_many :fruits
|
17
|
+
end
|
18
|
+
|
19
|
+
Mongoid.configure do |config|
|
20
|
+
config.logger = @logger
|
21
|
+
config.from_hash YAML.load_file(Root.join('spec/support/mongoid/database.yml'))
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class NoneOrm
|
2
|
+
include Blueprints::Extensions::Blueprintable
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def add (record)
|
6
|
+
@all ||= []
|
7
|
+
@all << record
|
8
|
+
end
|
9
|
+
|
10
|
+
def destroy(record)
|
11
|
+
@all.delete record
|
12
|
+
end
|
13
|
+
|
14
|
+
def count
|
15
|
+
all.size
|
16
|
+
end
|
17
|
+
|
18
|
+
def all(options = {})
|
19
|
+
Array(@all).clone.tap do |result|
|
20
|
+
result.reject! do |record|
|
21
|
+
options[:conditions].any? { |key, value| record.send(key) != value }
|
22
|
+
end if options[:conditions]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def first(options = {})
|
27
|
+
all(options).first
|
28
|
+
end
|
29
|
+
|
30
|
+
def last(options = {})
|
31
|
+
all(options).last
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize #(params)
|
36
|
+
# params.each { |param, value| instance_variable_set("@#{param}", value) }
|
37
|
+
self.class.add(self)
|
38
|
+
end
|
39
|
+
|
40
|
+
def reload
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def destroy
|
45
|
+
self.class.destroy(self)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Fruit < NoneOrm
|
50
|
+
attr_accessor :species, :average_diameter, :tree
|
51
|
+
end
|
52
|
+
|
53
|
+
class Tree < NoneOrm
|
54
|
+
attr_accessor :name, :size, :fruits
|
55
|
+
end
|
56
|
+
|
57
|
+
RSpec.configure do |config|
|
58
|
+
config.before do
|
59
|
+
[Fruit, Tree].each do |klass|
|
60
|
+
klass.instance_variables.each { |iv| klass.send(:remove_instance_variable, iv) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,11 +1,6 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
-
require '
|
4
|
-
require 'spec/active_record/fixtures/tree'
|
5
|
-
|
6
|
-
databases = YAML::load(IO.read("spec/active_record/fixtures/database.yml"))
|
7
|
-
db_info = databases[ENV["DB"] || "test"]
|
8
|
-
ActiveRecord::Base.establish_connection(db_info)
|
3
|
+
require File.dirname(__FILE__) + '/../support/active_record/initializer'
|
9
4
|
|
10
5
|
describe ActiveRecord::Base do
|
11
6
|
it "should allow calling blueprint on associations" do
|
data/spec/unit/blueprint_spec.rb
CHANGED
@@ -1,53 +1,124 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe Blueprints::Blueprint do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
it "should rewrite trace" do
|
5
|
+
context = Blueprints::Context.new(:file => __FILE__)
|
6
|
+
error_blueprint = Blueprints::Blueprint.new(:error, context) { raise 'error' }
|
7
|
+
begin
|
8
|
+
error_blueprint.build(stage)
|
9
|
+
rescue RuntimeError => e
|
10
|
+
e.backtrace[0].should =~ %r{spec/unit/blueprint_spec.rb:#{__LINE__ - 4}:in blueprint 'error'}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "building" do
|
15
|
+
describe "build count" do
|
16
|
+
it "should increase build count" do
|
17
|
+
lambda {
|
18
|
+
blueprint.build(stage)
|
19
|
+
}.should change(blueprint, :uses).by(1)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not increase build count if blueprint was already built" do
|
23
|
+
blueprint.build(stage)
|
24
|
+
lambda {
|
25
|
+
blueprint.build(stage, false)
|
26
|
+
}.should_not change(blueprint, :uses)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should copy instance variables to container" do
|
31
|
+
result = mock
|
32
|
+
blueprint { @bl = result }.build(stage)
|
33
|
+
stage.instance_variable_get(:@bl).should == result
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "auto set variable" do
|
37
|
+
it "should be set" do
|
38
|
+
blueprint.build(stage)
|
39
|
+
stage.instance_variable_get(:@blueprint).should == mock1
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should not be set if blueprint defines same variable" do
|
43
|
+
result = mock
|
44
|
+
blueprint do
|
45
|
+
@blueprint = result
|
46
|
+
:false_result
|
47
|
+
end.build(stage)
|
48
|
+
stage.instance_variable_get(:@blueprint).should == result
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should reset auto variable" do
|
52
|
+
blueprint.build(stage)
|
53
|
+
stage.instance_variable_set(:@blueprint, :false_result)
|
54
|
+
blueprint.build(stage, false)
|
55
|
+
stage.instance_variable_get(:@blueprint).should == mock1
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should allow passing options" do
|
60
|
+
(result = mock).expects(:options=).with(:option => 'value')
|
61
|
+
blueprint2 { result.options = options }.build(stage, true, :option => 'value')
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should include attributes for blueprint" do
|
65
|
+
(result = mock).expects(:attributes=).with(:option => 'value')
|
66
|
+
blueprint2 { result.attributes = attributes }.attributes(:option => 'value').build(stage)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should automatically build dependencies" do
|
70
|
+
blueprint
|
71
|
+
blueprint2.depends_on(:blueprint).build(stage)
|
72
|
+
blueprint.should be_built
|
73
|
+
end
|
8
74
|
end
|
9
75
|
|
10
76
|
describe "demolish" do
|
11
77
|
before do
|
12
|
-
@
|
78
|
+
@result = blueprint.build(stage)
|
79
|
+
@result.stubs(:destroy)
|
13
80
|
end
|
14
81
|
|
15
82
|
it "should allow to demolish blueprint" do
|
16
|
-
@
|
17
|
-
|
83
|
+
@result.expects(:destroy)
|
84
|
+
blueprint.demolish(stage)
|
18
85
|
end
|
19
86
|
|
20
87
|
it "should raise error if blueprint is not built" do
|
21
|
-
|
22
|
-
lambda {
|
88
|
+
blueprint.demolish(stage)
|
89
|
+
lambda { blueprint.demolish(stage) }.should raise_error(Blueprints::DemolishError)
|
23
90
|
end
|
24
91
|
|
25
92
|
it "should set blueprint as not built" do
|
26
|
-
|
27
|
-
Blueprints::Namespace.root.executed_blueprints.should_not include(
|
93
|
+
blueprint.demolish(stage)
|
94
|
+
Blueprints::Namespace.root.executed_blueprints.should_not include(blueprint)
|
28
95
|
end
|
29
96
|
|
30
97
|
it "should allow to customize demolishing" do
|
31
|
-
@
|
32
|
-
|
33
|
-
|
98
|
+
@result.expects(:demolish)
|
99
|
+
blueprint.demolish { @blueprint.demolish }
|
100
|
+
blueprint.demolish(stage)
|
34
101
|
end
|
35
102
|
end
|
36
103
|
|
37
104
|
describe "updating" do
|
105
|
+
before do
|
106
|
+
@result = blueprint.build(stage)
|
107
|
+
end
|
108
|
+
|
38
109
|
it "should allow building blueprint with different parameters" do
|
39
|
-
@
|
40
|
-
|
110
|
+
@result.expects(:blueprint).with(:option => 'value')
|
111
|
+
blueprint.build stage, true, :option => 'value'
|
41
112
|
end
|
42
113
|
|
43
114
|
it "should allow customizing update block" do
|
44
|
-
|
45
|
-
@
|
46
|
-
|
115
|
+
blueprint.update { @blueprint.update_attributes(options) }
|
116
|
+
@result.expects(:update_attributes).with(:option => 'value')
|
117
|
+
blueprint.build stage, true, :option => 'value'
|
47
118
|
end
|
48
119
|
|
49
120
|
it "should not update if build_once is false" do
|
50
|
-
|
121
|
+
blueprint.build stage, false, :option => 'value'
|
51
122
|
end
|
52
123
|
end
|
53
124
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Blueprints do
|
4
|
+
describe "usage" do
|
5
|
+
before do
|
6
|
+
blueprint
|
7
|
+
blueprint2
|
8
|
+
namespace_blueprint
|
9
|
+
namespace_blueprint2
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should allow getting unused blueprints" do
|
13
|
+
Blueprints::Namespace.root.build [:blueprint, :"namespace.blueprint2"]
|
14
|
+
Blueprints.unused.should =~ ['blueprint2', 'namespace.blueprint']
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "most used" do
|
18
|
+
before do
|
19
|
+
Blueprints::Namespace.root.build [:blueprint, :blueprint2, :"namespace.blueprint"]
|
20
|
+
Blueprints::Namespace.root.executed_blueprints.clear
|
21
|
+
Blueprints::Namespace.root.build [:blueprint2, :"namespace.blueprint"]
|
22
|
+
Blueprints::Namespace.root.executed_blueprints.clear
|
23
|
+
Blueprints::Namespace.root.build [:"namespace.blueprint"]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return all blueprints with their usages" do
|
27
|
+
Blueprints.most_used.should == [["namespace.blueprint", 3], ["blueprint2", 2], ["blueprint", 1], ["namespace.blueprint2", 0]]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should allow getting most used blueprints" do
|
31
|
+
Blueprints.most_used(:count => 2).should == [['namespace.blueprint', 3], ['blueprint2', 2]]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should allow getting list of blueprints used at least n times" do
|
35
|
+
Blueprints.most_used(:at_least => 1).should == [['namespace.blueprint', 3], ['blueprint2', 2], ["blueprint", 1]]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should allow mixing at least with count" do
|
39
|
+
Blueprints.most_used(:at_least => 2, :count => 3).should == [['namespace.blueprint', 3], ['blueprint2', 2]]
|
40
|
+
Blueprints.most_used(:at_least => 2, :count => 1).should == [['namespace.blueprint', 3]]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/unit/buildable_spec.rb
CHANGED
@@ -1,14 +1,45 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe Blueprints::Buildable do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
it "should inspect buildable nicely" do
|
5
|
+
namespace_blueprint.attributes(:attr => 'value').depends_on(:dependency)
|
6
|
+
namespace_blueprint.inspect.should == %q(<#Blueprints::Blueprint name: "namespace.blueprint", attributes: {:attr=>"value"}, dependencies: [:dependency]>)
|
7
7
|
end
|
8
8
|
|
9
|
-
describe "
|
10
|
-
|
11
|
-
Blueprints
|
9
|
+
describe "name" do
|
10
|
+
after do
|
11
|
+
Blueprints.config.default_attributes = :name
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should raise TypeError when scenario name is not symbol or string' do
|
15
|
+
lambda {
|
16
|
+
Blueprints::Blueprint.new([], context)
|
17
|
+
}.should raise_error(TypeError, "Pass blueprint names as strings or symbols only, cannot define blueprint []")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return full name" do
|
21
|
+
namespace_blueprint.full_name.should == 'namespace.blueprint'
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "inferring" do
|
25
|
+
it "should infer name using default attributes" do
|
26
|
+
Blueprints::Buildable.new(nil, context.attributes(:name => 'inferred_name')).name.should == :inferred_name
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should infer name from third default attribute" do
|
30
|
+
Blueprints.config.default_attributes = :name, :to_s, :id
|
31
|
+
Blueprints::Buildable.new(nil, context.attributes(:id => 'third')).name.should == :third
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should parameterize infered name" do
|
35
|
+
Blueprints::Buildable.new(nil, context.attributes(:name => 'my blueprint')).name.should == :my_blueprint
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should raise error if name can't be inferred" do
|
39
|
+
lambda {
|
40
|
+
Blueprints::Buildable.new(nil, context.attributes(:id => 'third')).name.should == :third
|
41
|
+
}.should raise_error(TypeError, "Pass blueprint names as strings or symbols only, cannot define blueprint nil")
|
42
|
+
end
|
12
43
|
end
|
13
44
|
end
|
14
45
|
end
|