engineering 0.2 → 0.3
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.
- 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
|