engineering 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +11 -0
- data/Gemfile +6 -2
- data/Rakefile +2 -0
- data/engineering.gemspec +8 -6
- data/lib/builder/extrusion.rb +189 -0
- data/lib/builder/model.rb +120 -0
- data/lib/builder/sketch.rb +119 -0
- data/lib/engineering.rb +28 -54
- data/lib/model/dsl.rb +26 -0
- data/lib/sketchup.rb +25 -5
- data/test/builder/extrusion.rb +143 -0
- data/test/builder/model.rb +191 -0
- data/test/builder/sketch.rb +161 -0
- data/test/engineering.rb +95 -30
- data/test/fixtures/sketchup/sketch_group_group.su +4 -0
- data/test/fixtures/sketchup/sketch_group_group_group.su +4 -0
- data/test/sketchup/builder.rb +43 -9
- metadata +42 -27
data/lib/engineering.rb
CHANGED
@@ -5,6 +5,9 @@ require 'model'
|
|
5
5
|
require 'sketch'
|
6
6
|
require 'units'
|
7
7
|
|
8
|
+
require_relative 'builder/extrusion'
|
9
|
+
require_relative 'builder/model'
|
10
|
+
require_relative 'builder/sketch'
|
8
11
|
require_relative 'sketchup'
|
9
12
|
|
10
13
|
=begin
|
@@ -18,76 +21,42 @@ module Engineering
|
|
18
21
|
|
19
22
|
# Create a new {Extrusion} subclass and initialize it with the given block
|
20
23
|
# @param name [Symbol] The name of the resulting subclass
|
21
|
-
def extrusion(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
klass = Class.new(Model::Extrusion)
|
27
|
-
|
28
|
-
if initial_arguments.has_key?(:length)
|
29
|
-
klass.instance_variable_set :@length, initial_arguments[:length]
|
30
|
-
klass.class.send(:define_method, :length) { @length }
|
31
|
-
end
|
32
|
-
|
33
|
-
klass.instance_variable_set :@sketch, initial_arguments[:sketch]
|
34
|
-
klass.class.send(:define_method, :sketch) { @sketch }
|
35
|
-
|
36
|
-
klass.send :define_method, :initialize do |options={}, &block|
|
37
|
-
raise ArgumentError, "Can't initialize with a length when #{self} already has a length attribute" if initial_arguments.has_key?(:length) and options.has_key?(:length)
|
38
|
-
super initial_arguments.merge(options), &block
|
24
|
+
def extrusion(name=nil, &block)
|
25
|
+
klass = Engineering::Builder::Extrusion.build(&block)
|
26
|
+
if name
|
27
|
+
parent = (Module == self.class) ? self : Object
|
28
|
+
parent.const_set(name, klass)
|
39
29
|
end
|
40
|
-
|
41
|
-
Object.const_set(symbol, klass)
|
30
|
+
klass
|
42
31
|
end
|
43
32
|
|
44
33
|
# Create a new {Model} subclass and initialize it with the given block
|
45
34
|
# @param name [Symbol] The name of the new {Model} subclass
|
46
|
-
def model(name, &block)
|
47
|
-
klass =
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# The defaults are hidden in an instance variable so that the passed block can't accidentally corrupt them
|
53
|
-
attribute_defaults = builder.instance_variable_get(:@attribute_defaults) || {}
|
54
|
-
|
55
|
-
# Bind any attribute getters and setters to the new subclass
|
56
|
-
attribute_getters = builder.instance_variable_get(:@attribute_getters) || {}
|
57
|
-
attribute_getters.each {|k, m| klass.send :define_method, k, m }
|
58
|
-
|
59
|
-
attribute_setters = builder.instance_variable_get(:@attribute_setters) || {}
|
60
|
-
attribute_setters.each {|k, m| klass.send :define_method, k, m }
|
61
|
-
|
62
|
-
klass.send :define_method, :initialize do |*args, &block|
|
63
|
-
super *(attribute_defaults.map {|k,v| { k => (v.respond_to?(:call) ? v.call : v) } }), *args, &block
|
64
|
-
initial_elements.each {|a| push a }
|
35
|
+
def model(name=nil, &block)
|
36
|
+
klass = Builder::Model.build(&block)
|
37
|
+
if name
|
38
|
+
parent = (Module == self.class) ? self : Object
|
39
|
+
parent.const_set(name, klass)
|
65
40
|
end
|
66
|
-
|
67
|
-
Object.const_set(name, klass)
|
41
|
+
klass
|
68
42
|
end
|
69
43
|
|
70
44
|
# Create a new {Sketch} subclass and initialize it with the given block
|
71
45
|
# @param name [Symbol] The name of the {Sketch} subclass
|
72
|
-
def sketch(
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
klass = Class.new(Sketch)
|
78
|
-
klass.send :define_method, :initialize do |*args, &block|
|
79
|
-
super *args, &block
|
80
|
-
initial_elements.each {|a| push a }
|
46
|
+
def sketch(name=nil, &block)
|
47
|
+
klass = Builder::Sketch.build(&block)
|
48
|
+
if name
|
49
|
+
parent = (Module == self.class) ? self : Object
|
50
|
+
parent.const_set(name, klass)
|
81
51
|
end
|
82
|
-
|
83
|
-
Object.const_set(symbol, klass)
|
52
|
+
klass
|
84
53
|
end
|
85
54
|
|
86
55
|
class Geometry::Polygon
|
87
56
|
# Build a {Polygon} instance using the {Sketch} DSL
|
88
57
|
# @return [Polygon]
|
89
58
|
def self.build(&block)
|
90
|
-
Sketch::
|
59
|
+
Sketch::Builder::Polygon.new.evaluate(&block)
|
91
60
|
end
|
92
61
|
end
|
93
62
|
|
@@ -95,7 +64,7 @@ module Engineering
|
|
95
64
|
# Build a {Polyline} instance using the {Sketch} DSL
|
96
65
|
# @return [Polyline]
|
97
66
|
def self.build(&block)
|
98
|
-
Sketch::
|
67
|
+
Sketch::Builder::Polyline.new.evaluate(&block)
|
99
68
|
end
|
100
69
|
end
|
101
70
|
end
|
@@ -103,3 +72,8 @@ end
|
|
103
72
|
|
104
73
|
self.extend Engineering::DSL
|
105
74
|
include Geometry # Make Geometry types more readily available
|
75
|
+
|
76
|
+
# Allow the DSL to be called from within Module definitions
|
77
|
+
class Module
|
78
|
+
include Engineering::DSL
|
79
|
+
end
|
data/lib/model/dsl.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
class Model
|
2
|
+
# Extensions to Model::DSL
|
3
|
+
module DSL
|
4
|
+
# Define a new read-write {Model} attribute. An optional default value can be supplied as either an argument, or as a block. The block will be evaluated the first time the attribute is accessed.
|
5
|
+
# @param name [String,Symbol] The new attribute's name
|
6
|
+
# @param value A default value for the new attribute
|
7
|
+
def attr_accessor(name, value=nil, &block)
|
8
|
+
define_attribute_reader name, value, &block
|
9
|
+
define_attribute_writer name
|
10
|
+
end
|
11
|
+
alias :attribute :attr_accessor
|
12
|
+
|
13
|
+
# Define a new read-only {Model} attribute. An optional default value can be supplied as either an argument, or as a block. The block will be evaluated the first time the attribute is accessed.
|
14
|
+
# @param name [String,Symbol] The new attribute's name
|
15
|
+
# @param value A default value for the new attribute
|
16
|
+
def attr_reader(name, value=nil, &block)
|
17
|
+
define_attribute_reader(name, value, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Define a new write-only {Model} attribute
|
21
|
+
# @param name [String,Symbol] The new attribute's name
|
22
|
+
def attr_writer(name)
|
23
|
+
define_attribute_writer(name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/sketchup.rb
CHANGED
@@ -81,6 +81,7 @@ module SketchUp
|
|
81
81
|
end
|
82
82
|
|
83
83
|
# Convert the given container to an array of strings that SketchUp can read
|
84
|
+
# @return [Array]
|
84
85
|
def to_array(container, parent='model.entities', transformation=nil)
|
85
86
|
case container
|
86
87
|
when Model::Extrusion
|
@@ -90,11 +91,11 @@ module SketchUp
|
|
90
91
|
to_array(container.sketch, parent, container.transformation).map {|l| "#{l}.pushpull(#{to_sketchup(-container.length)})"}
|
91
92
|
end
|
92
93
|
when Model::Group
|
94
|
+
elements = container.elements.map {|element| to_array(element, 'group.entities') }
|
93
95
|
if container.transformation and not container.transformation.identity?
|
94
|
-
|
95
|
-
else
|
96
|
-
container.elements.map {|element| to_array(element, parent) }.flatten
|
96
|
+
elements << "group.transformation = #{to_sketchup(container.transformation)}"
|
97
97
|
end
|
98
|
+
["#{parent}.add_group.tap {|group|", elements.flatten.map {|line| line.prepend("\t") }, '}']
|
98
99
|
when Model # !!! Must be after all subclasses of Model
|
99
100
|
if container.transformation and not container.transformation.identity?
|
100
101
|
add_instance(parent, container)
|
@@ -102,7 +103,14 @@ module SketchUp
|
|
102
103
|
container.elements.map {|element| to_array(element, parent) }.flatten
|
103
104
|
end
|
104
105
|
when Sketch::Group
|
105
|
-
container.geometry.map
|
106
|
+
container.geometry.map do |element|
|
107
|
+
combined_transformation = transformation ? (transformation + container.transformation) : container.transformation
|
108
|
+
case element
|
109
|
+
when Sketch::Group then to_array(element, parent, combined_transformation)
|
110
|
+
else
|
111
|
+
to_sketchup(element, parent, combined_transformation)
|
112
|
+
end
|
113
|
+
end.flatten
|
106
114
|
when Sketch # !!! Must be after all subclasses of Sketch
|
107
115
|
container.geometry.map do |element|
|
108
116
|
case element
|
@@ -120,6 +128,11 @@ module SketchUp
|
|
120
128
|
case entity
|
121
129
|
when Array
|
122
130
|
entity.map {|v| to_sketchup(v, parent, transformation) }.join(', ')
|
131
|
+
when Geometry::Annulus
|
132
|
+
"->{ inner_face = #{parent}.add_circle(#{to_sketchup(entity.center, parent, transformation)}, [0,0,1], #{to_sketchup(entity.inner_radius)}).tap {|points| points[0].find_faces}.first.faces[0]\n \
|
133
|
+
outer_face = #{parent}.add_circle(#{to_sketchup(entity.center, parent, transformation)}, [0,0,1], #{to_sketchup(entity.outer_radius)}).tap {|points| points[0].find_faces}.first.faces[0]\n \
|
134
|
+
#{parent}.erase_entities(inner_face)\n \
|
135
|
+
outer_face }.call"
|
123
136
|
when Geometry::Arc
|
124
137
|
"#{parent}.add_arc(#{to_sketchup(entity.center)}, [1,0,0], [0,0,1], #{to_sketchup(entity.radius)}, #{to_sketchup(entity.start_angle)}, #{to_sketchup(entity.end_angle)})"
|
125
138
|
when Geometry::Circle
|
@@ -145,7 +158,7 @@ module SketchUp
|
|
145
158
|
end
|
146
159
|
when Geometry::Polygon
|
147
160
|
"#{parent}.add_face(#{to_sketchup(entity.points, parent, transformation)})"
|
148
|
-
when Geometry::Rectangle
|
161
|
+
when Geometry::Rectangle, Geometry::Square
|
149
162
|
"#{parent}.add_face(#{to_sketchup(entity.points, parent, transformation)})"
|
150
163
|
when Geometry::Transformation
|
151
164
|
pt = '[' + (entity.translation ? to_sketchup(entity.translation.to_a) : '0,0,0') + ']'
|
@@ -161,6 +174,13 @@ module SketchUp
|
|
161
174
|
when Units
|
162
175
|
s = entity.to_s
|
163
176
|
SKETCHUP_UNITS[s] or raise "SketchUp won't recognize '#{s}'"
|
177
|
+
when Units::Operator
|
178
|
+
operator = case entity
|
179
|
+
when Units::Addition then ' + '
|
180
|
+
when Units::Division then ' / '
|
181
|
+
when Units::Subtraction then ' - '
|
182
|
+
end
|
183
|
+
'(' + entity.operands.map {|a| to_sketchup(a)}.join(operator) + ')'
|
164
184
|
when Units::Numeric
|
165
185
|
[entity.value, entity.units].compact.map {|a| to_sketchup(a)}.join '.'
|
166
186
|
else
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'builder/extrusion'
|
3
|
+
|
4
|
+
describe Engineering::Builder::Extrusion do
|
5
|
+
subject { Engineering::Builder::Extrusion }
|
6
|
+
|
7
|
+
it 'must build a subclass' do
|
8
|
+
subject.build.ancestors.must_include(Model::Extrusion)
|
9
|
+
Class.wont_be :respond_to?, :elements
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'must build a subclass with an empty block' do
|
13
|
+
klass = subject.build {}
|
14
|
+
klass.ancestors.must_include(Model::Extrusion)
|
15
|
+
klass.sketch.ancestors.must_include(Sketch)
|
16
|
+
klass.sketch.elements.must_be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'must build a subclass with a length property' do
|
20
|
+
subject.build.must_be :respond_to?, :length
|
21
|
+
Class.wont_be :respond_to?, :length
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'must build a subclass with a sketch property' do
|
25
|
+
subject.build.must_be :respond_to?, :sketch
|
26
|
+
Class.wont_be :respond_to?, :sketch
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'must have a length property that is availabe to the DSL' do
|
30
|
+
subject.build() { length 5; length.must_equal 5 }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'when creating a subclass with attributes' do
|
34
|
+
let :klass do
|
35
|
+
subject.build do
|
36
|
+
attribute :attribute0
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'must define the attributes' do
|
41
|
+
klass.new.must_be :respond_to?, :attribute0
|
42
|
+
klass.new.must_be :respond_to?, :attribute0=
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'must define the attribute on the Sketch instance' do
|
46
|
+
klass.new.sketch.must_be :respond_to?, :attribute0
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'must have working accessors' do
|
50
|
+
test_model = klass.new
|
51
|
+
test_model.attribute0 = 42
|
52
|
+
test_model.attribute0.must_equal 42
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'must be able to initialize the attribute during construction' do
|
56
|
+
klass.new(attribute0: 37).attribute0.must_equal 37
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'when creating a subclass with attributes that have default values' do
|
61
|
+
let :klass do
|
62
|
+
subject.build do
|
63
|
+
attribute :attribute0, 42
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'must define the attribute on the Sketch subclass' do
|
68
|
+
klass.sketch.must_be :respond_to?, :attribute0
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'must have the default value' do
|
72
|
+
klass.new.attribute0.must_equal 42
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'must allow the default value to be overriden' do
|
76
|
+
klass.new(attribute0: 24).attribute0.must_equal 24
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'must not pollute Class' do
|
80
|
+
Class.wont_be :respond_to?, :attribute0
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'must have class attributes' do
|
84
|
+
klass.attribute0.must_equal 42
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'must not have a class setter' do
|
88
|
+
-> { klass.attribute0 = 5 }.must_raise NoMethodError
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'when creating a subclass with read-only attributes that have default values' do
|
93
|
+
let :klass do
|
94
|
+
subject.build do
|
95
|
+
attr_reader :attributeO, 42
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'must have the default value' do
|
100
|
+
klass.new.attributeO.must_equal 42
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'must not allow the default value to be overriden' do
|
104
|
+
-> { klass.new(attributeO: 24) }.must_raise NoMethodError
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'must not pollute Class' do
|
108
|
+
Class.wont_be :respond_to?, :attribute0
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'must have class attributes' do
|
112
|
+
klass.attributeO.must_equal 42
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'must not have a class setter' do
|
116
|
+
-> { klass.attributeO = 5 }.must_raise NoMethodError
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'must not have an instance setter' do
|
120
|
+
-> { klass.new.attributeO = 6 }.must_raise NoMethodError
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'when creating a subclass with a group' do
|
125
|
+
let :klass do
|
126
|
+
subject.build do
|
127
|
+
group origin:[1,2] do
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'must create a Group subclass' do
|
133
|
+
klass.sketch.elements.count.must_equal 1
|
134
|
+
klass.sketch.elements.first.first.ancestors.must_include Sketch::Group
|
135
|
+
klass.sketch.elements.first.last.must_equal [origin:[1,2]]
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'must pass the initializer arguments when instantiating the subclass' do
|
139
|
+
klass.new.sketch.first.must_be_kind_of Sketch::Group
|
140
|
+
klass.new.sketch.first.transformation.translation.must_equal Geometry::Point[1,2]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'builder/model'
|
3
|
+
|
4
|
+
describe Engineering::Builder::Model do
|
5
|
+
subject { Engineering::Builder::Model }
|
6
|
+
|
7
|
+
it 'must build a Model subclass' do
|
8
|
+
subject.build.ancestors.must_include(Model)
|
9
|
+
Class.wont_be :respond_to?, :elements
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'must build a Model subclass with an empty block' do
|
13
|
+
klass = subject.build {}
|
14
|
+
klass.ancestors.must_include(Model)
|
15
|
+
klass.elements.must_be_empty
|
16
|
+
Class.wont_be :respond_to?, :elements
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'when creating a Model subclass with attributes' do
|
20
|
+
let :klass do
|
21
|
+
subject.build do
|
22
|
+
attribute :attribute0
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'must define the attributes for instances' do
|
27
|
+
klass.new.must_be :respond_to?, :attribute0
|
28
|
+
klass.new.must_be :respond_to?, :attribute0=
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'must have working instance accessors' do
|
32
|
+
test_model = klass.new
|
33
|
+
test_model.attribute0 = 42
|
34
|
+
test_model.attribute0.must_equal 42
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'must be able to initialize the attribute during construction' do
|
38
|
+
klass.new(attribute0: 37).attribute0.must_equal 37
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'when creating a Model subclass with attributes that have default values' do
|
43
|
+
let :klass do
|
44
|
+
subject.build do
|
45
|
+
attribute :attribute0, 42
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'must have the default value' do
|
50
|
+
klass.new.attribute0.must_equal 42
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'must allow the default value to be overriden' do
|
54
|
+
klass.new(attribute0: 24).attribute0.must_equal 24
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'must have class attributes' do
|
58
|
+
klass.attribute0.must_equal 42
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'must not pollute Class' do
|
62
|
+
Class.wont_be :respond_to?, :attribute0
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'must not have a class setter' do
|
66
|
+
-> { klass.attribute0 = 5 }.must_raise NoMethodError
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'when creating a Model subclass with read-only attributes that have default values' do
|
71
|
+
let :klass do
|
72
|
+
subject.build do
|
73
|
+
attr_reader :attributeO, 42
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'must have the default value' do
|
78
|
+
klass.new.attributeO.must_equal 42
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'must not allow the default value to be overriden' do
|
82
|
+
-> { klass.new(attributeO: 24) }.must_raise NoMethodError
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'must not pollute Class' do
|
86
|
+
Class.wont_be :respond_to?, :attribute0
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'must have class attributes' do
|
90
|
+
klass.attributeO.must_equal 42
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'must not have a class setter' do
|
94
|
+
-> { klass.attributeO = 5 }.must_raise NoMethodError
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'must not have an instance setter' do
|
98
|
+
-> { klass.new.attributeO = 6 }.must_raise NoMethodError
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'when pushing subclasses with initializer arguments' do
|
103
|
+
let :klass do
|
104
|
+
subject.build do
|
105
|
+
push Model, origin:[1,2,3]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'must store the subclass in initializer arguments' do
|
110
|
+
klass.elements.first.must_be_kind_of Array
|
111
|
+
klass.elements.first.must_equal [Model, [origin:[1,2,3]]]
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'must pass the initializer arguments when instantiating the subclass' do
|
115
|
+
klass.new.elements.first.must_be_kind_of Model
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'when creating a subclass with an extrusion' do
|
120
|
+
let :klass do
|
121
|
+
subject.build do
|
122
|
+
extrude length:10, origin:[1,2,3] do
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'must create an Extrusion subclass' do
|
128
|
+
klass.elements.count.must_equal 1
|
129
|
+
klass.elements.first.first.ancestors.must_include Model::Extrusion
|
130
|
+
klass.elements.first.last.must_equal [length:10, origin:[1,2,3]]
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'must pass the initializer arguments when instantiating the subclass' do
|
134
|
+
klass.new.first.must_be_kind_of Model::Extrusion
|
135
|
+
klass.new.first.transformation.translation.must_equal Geometry::Point[1,2,3]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'when creating a subclass with a group' do
|
140
|
+
let :klass do
|
141
|
+
subject.build do
|
142
|
+
group origin:[1,2,3] do
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'must create a Group subclass' do
|
148
|
+
klass.elements.count.must_equal 1
|
149
|
+
klass.elements.first.first.ancestors.must_include Model::Group
|
150
|
+
klass.elements.first.last.must_equal [origin:[1,2,3]]
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'must pass the initializer arguments when instantiating the subclass' do
|
154
|
+
klass.new.first.must_be_kind_of Model::Group
|
155
|
+
klass.new.first.transformation.translation.must_equal Geometry::Point[1,2,3]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe 'when creating a subclass that contains another Model subclass' do
|
160
|
+
let :klass do
|
161
|
+
subject.build do
|
162
|
+
push Model
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'must add the subclass' do
|
167
|
+
klass.elements.length.must_equal 1
|
168
|
+
klass.elements.first.first.ancestors.must_include Model
|
169
|
+
klass.elements.first.last.must_equal []
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe 'when creating a subclass that contains another Model subclass that has argument' do
|
174
|
+
let :klass do
|
175
|
+
subject.build do
|
176
|
+
push Model, origin:[1,2,3]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'must add the subclass' do
|
181
|
+
klass.elements.length.must_equal 1
|
182
|
+
klass.elements.first.first.ancestors.must_include Model
|
183
|
+
klass.elements.first.last.must_equal [origin:[1,2,3]]
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'must pass the initializer arguments when instantiating the subclass' do
|
187
|
+
klass.new.first.must_be_kind_of Model
|
188
|
+
klass.new.first.transformation.translation.must_equal Geometry::Point[1,2,3]
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|