agreement-design-prototype 0.0.3 → 0.0.4
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/README.md +15 -0
- data/agreement-design.gemspec +2 -1
- data/build/build_models.rb +24 -9
- data/gen/data/data.json +1 -0
- data/gen/data/data.yaml +46 -0
- data/gen/data/fm_agreements.jsonlines +2 -0
- data/gen/data/fm_catalogue.jsonlines +1 -0
- data/gen/diagrams/metamodel.dot +45 -0
- data/gen/doc/data.md +44 -0
- data/gen/doc/metamodel.md +99 -57
- data/gen/images/metamodel.jpg +0 -0
- data/model/agreement.rb +95 -43
- data/model/fm.rb +56 -24
- data/model/geographic.rb +30 -0
- data/model/party.rb +14 -12
- data/out/test/data/datatest.json +1 -0
- data/out/test/diagrams/d.dot +16 -30
- data/out/test/doc/doctest.md +17 -19
- data/out/test/doc/modeldoctest.md +62 -0
- data/out/test/images/d.jpg +0 -0
- data/src/api.rb +33 -0
- data/src/data.rb +89 -0
- data/src/data_model.rb +102 -38
- data/src/diagram.rb +61 -95
- data/src/doc.rb +55 -151
- data/src/transform.rb +144 -0
- data/test/data_model_test.rb +43 -65
- data/test/data_test.rb +26 -0
- data/test/diagram_test.rb +2 -5
- data/test/doc_test.rb +15 -9
- data/test/test_model.rb +88 -0
- data/test/transform_test.rb +83 -0
- metadata +21 -5
- data/gen/diagrams/data_model.dot +0 -34
- data/gen/doc/frameworks.md +0 -19
- data/gen/images/data_model.jpg +0 -0
data/src/diagram.rb
CHANGED
@@ -1,67 +1,13 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'transform'
|
3
|
+
include Transform
|
3
4
|
|
5
|
+
class Diagram < Output
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
super(file)
|
8
|
-
@node = node
|
9
|
-
pput %Q("#{@node}" [label=<<table BORDER="1" CELLBORDER="0" CELLSPACING="0"><TH><TD>#{@node}</TD></TH>)
|
10
|
-
@items = []
|
7
|
+
def initialize dir, name
|
8
|
+
super dir, name, ".dot"
|
11
9
|
end
|
12
10
|
|
13
|
-
def item i
|
14
|
-
@items << i
|
15
|
-
self.pput %Q(<TR><TD ALIGN="LEFT">-#{i}</TD></TR>)
|
16
|
-
end
|
17
|
-
|
18
|
-
def finish
|
19
|
-
# self.pput " " << @items.join( ",")
|
20
|
-
self.pput "</table>"
|
21
|
-
self.pput ">];\n"
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
class Graph < Element
|
28
|
-
def initialize file
|
29
|
-
super(file)
|
30
|
-
self.pput "strict digraph {\n"
|
31
|
-
end
|
32
|
-
|
33
|
-
def finish
|
34
|
-
self.pput "}\n"
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
class SubGraph < Element
|
40
|
-
def initialize file, model
|
41
|
-
super(file)
|
42
|
-
self.pput "subgraph cluster_#{model} {\n"
|
43
|
-
self.pput "node [shape=plaintext margin=0];\n"
|
44
|
-
self.pput "label=#{model};\n"
|
45
|
-
end
|
46
|
-
|
47
|
-
def finish
|
48
|
-
self.pput "}\n"
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
class Links < Element
|
54
|
-
|
55
|
-
def link el1, el2, label: el, arrowhead: nil, arrowtail: nil
|
56
|
-
ah = arrowhead ? %Q!arrowhead = "#{arrowhead}"! : ""
|
57
|
-
at = arrowtail ? %Q!arrowtail = "#{arrowtail}"! : ""
|
58
|
-
pput %Q!"#{el1}" -> "#{el2}" [label="#{label}" #{ah} #{at} ];\n!
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
class Diagram < Doc
|
64
|
-
|
65
11
|
def dotfile
|
66
12
|
File.join(diagram_path, "#{self.name}.dot")
|
67
13
|
end
|
@@ -75,42 +21,56 @@ class Diagram < Doc
|
|
75
21
|
FileUtils.mkpath diagram_path
|
76
22
|
FileUtils.mkpath image_path
|
77
23
|
File.open(self.dotfile, "w") do |file|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
24
|
+
# nodes
|
25
|
+
file.print "strict digraph {\n"
|
26
|
+
|
27
|
+
transform_metamodel(
|
28
|
+
{
|
29
|
+
before_model: lambda do |model:|
|
30
|
+
file.print "subgraph cluster_#{model} {\n"
|
31
|
+
file.print "node [shape=plaintext margin=0];\n"
|
32
|
+
file.print "label=#{model};\n"
|
33
|
+
end,
|
34
|
+
after_model: lambda do |model:, before:|
|
35
|
+
file.print "}\n"
|
36
|
+
end,
|
37
|
+
before_type: lambda do |type:, depth:, index:, total:|
|
38
|
+
file.print %Q("#{type.typename}" [label=<<table BORDER="1" CELLBORDER="0" CELLSPACING="0"><TH><TD>#{type.typename}</TD></TH>)
|
39
|
+
end,
|
40
|
+
after_type: lambda do |type:, depth:, before:|
|
41
|
+
file.print "</table>"
|
42
|
+
file.print ">];\n"
|
43
|
+
end,
|
44
|
+
attribute: lambda do |id:, val:, depth:, type:, index:, total:|
|
45
|
+
file.print %Q(<TR><TD ALIGN="LEFT">-#{id}</TD></TR>)
|
46
|
+
end,
|
47
|
+
},
|
48
|
+
*models
|
49
|
+
)
|
50
|
+
# links
|
51
|
+
transform_metamodel(
|
52
|
+
{
|
53
|
+
before_type: lambda do |type:, depth:, index:, total:|
|
54
|
+
if type.superclass < DataType
|
55
|
+
link(file, type.typename, type.superclass.typename,
|
106
56
|
label: "extends",
|
107
57
|
arrowhead: "none",
|
108
|
-
arrowtail:
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
58
|
+
arrowtail: "normal")
|
59
|
+
end
|
60
|
+
end,
|
61
|
+
:attribute => lambda do |id:, val:, depth: 0, type:, index:, total:|
|
62
|
+
if val[:links] || val[:type] < DataType
|
63
|
+
contains = (val[:type] < DataType)
|
64
|
+
link(file, type.typename, val[:links] ? val[:links].typename : val[:type].typename,
|
65
|
+
label: %Q!#{contains ? "{contains} " : ""}#{val[:name]}!,
|
66
|
+
arrowhead: contains ? "none" : "open",
|
67
|
+
arrowtail: contains ? "diamond" : "none")
|
68
|
+
end
|
69
|
+
end,
|
70
|
+
},
|
71
|
+
*models
|
72
|
+
)
|
73
|
+
file.print "}\n"
|
114
74
|
end
|
115
75
|
|
116
76
|
unless system("dot -Tjpg #{self.dotfile} > #{self.jpgfile}")
|
@@ -136,11 +96,17 @@ class Diagram < Doc
|
|
136
96
|
private
|
137
97
|
|
138
98
|
def image_path
|
139
|
-
File.join(self.
|
99
|
+
File.join(self.dir, "images")
|
140
100
|
end
|
141
101
|
|
142
102
|
def diagram_path
|
143
|
-
File.join(self.
|
103
|
+
File.join(self.dir, "diagrams")
|
104
|
+
end
|
105
|
+
|
106
|
+
def link file, el1, el2, label: el2, arrowhead: nil, arrowtail: nil
|
107
|
+
ah = arrowhead ? %Q!arrowhead = "#{arrowhead}"! : ""
|
108
|
+
at = arrowtail ? %Q!arrowtail = "#{arrowtail}"! : ""
|
109
|
+
file.print %Q!"#{el1}" -> "#{el2}" [label="#{label}" #{ah} #{at} ];\n!
|
144
110
|
end
|
145
111
|
|
146
112
|
end
|
data/src/doc.rb
CHANGED
@@ -1,114 +1,61 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
@file = file
|
4
|
-
end
|
5
|
-
|
6
|
-
def finish
|
7
|
-
self
|
8
|
-
end
|
9
|
-
|
10
|
-
protected
|
11
|
-
|
12
|
-
def pput(string)
|
13
|
-
@file.print string
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def cond_call(depth, id, value, lam, lambdas)
|
20
|
-
if lambdas[lam]
|
21
|
-
return lambdas[lam].(depth, id, value)
|
22
|
-
end
|
23
|
-
return 0
|
24
|
-
end
|
25
|
-
|
26
|
-
# each lambda takes the depth, id, value
|
27
|
-
# Lambdas are:
|
28
|
-
# :before_type_lambda,
|
29
|
-
# :after_type_lambda,
|
30
|
-
# :before_array_lambda,
|
31
|
-
# :after_array_lambda,
|
32
|
-
# :attribute_lambda
|
33
|
-
# which takes a type and returns an object (the id)
|
34
|
-
# depth is the number counting from zero, incremented with array elements and nested types.
|
35
|
-
# ID is a nested int of the type a for types and a.b for array types,
|
36
|
-
# and is the name of the attribute for attributes
|
37
|
-
# decl is the type or attribute or array
|
1
|
+
require_relative 'transform'
|
2
|
+
include Transform
|
38
3
|
|
39
|
-
|
4
|
+
class Document < Output
|
40
5
|
|
41
|
-
|
42
|
-
|
43
|
-
j = 1
|
44
|
-
for aa in decl
|
45
|
-
transform_type(depth , "#{id}.#{j}", aa, lambdas)
|
46
|
-
j = j + 1
|
47
|
-
end
|
48
|
-
cond_call(depth, id, decl, :after_array_lambda, lambdas)
|
49
|
-
elsif decl.class <= DataType
|
50
|
-
cond_call(depth, id, decl, :before_type_lambda, lambdas)
|
51
|
-
for ak in decl.attributes.keys
|
52
|
-
av = decl.attributes[ak]
|
53
|
-
transform_type(depth + 1, ak, av, lambdas)
|
54
|
-
end
|
55
|
-
cond_call(depth, id, decl, :after_type_lambda, lambdas)
|
56
|
-
else
|
57
|
-
cond_call(depth, id, decl, :attribute_lambda, lambdas)
|
6
|
+
def initialize dir, name
|
7
|
+
super File.join( dir, "doc"), name, "md"
|
58
8
|
end
|
59
|
-
self
|
60
|
-
end
|
61
|
-
|
62
|
-
class ClassNameElement < Element
|
63
9
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
10
|
+
def document *models
|
11
|
+
file do |file|
|
12
|
+
transform_datamodel(
|
13
|
+
{
|
14
|
+
:before_type => lambda do |type:, depth: 0, index:,total:|
|
15
|
+
file.print %Q!####{'#' * depth} #{type.name} #{type.attributes[:id] || ""} \n!
|
16
|
+
end,
|
17
|
+
:attribute => lambda do |id:, val:, depth: 0, type: nil, index:, total:|
|
18
|
+
file.print %Q!#{" " * depth} - #{id} #{val}\n!
|
19
|
+
end
|
20
|
+
}, *models)
|
68
21
|
end
|
69
22
|
end
|
70
23
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
pput "\n #{type.description}\n\n"
|
106
|
-
pput "|attribute|type|multiplicity|description|\n"
|
107
|
-
pput "|---------|----|------------|-----------|\n"
|
108
|
-
for a in type.attributes.values
|
109
|
-
pput "|#{a[:name]}|#{a[:type]}|#{self.multiplicity(a)}|#{a[:description]}|\n"
|
24
|
+
def document_metamodel *models
|
25
|
+
file do |file|
|
26
|
+
transform_metamodel(
|
27
|
+
{
|
28
|
+
before_model: lambda do |model:|
|
29
|
+
file.print %Q!\# Data model: #{model}\n!
|
30
|
+
end,
|
31
|
+
before_group: lambda do |group|
|
32
|
+
file.print %Q!\# #{cat.class}: #{cat.name}\n!
|
33
|
+
if (cat.respond_to?(:description))
|
34
|
+
file.print %Q! #{cat.description}\n!
|
35
|
+
end
|
36
|
+
end,
|
37
|
+
before_type: lambda do |type:, depth:, index:, total:|
|
38
|
+
file.print "## #{type.typename}"
|
39
|
+
if type.extends
|
40
|
+
file.print " extends #{type.extends}"
|
41
|
+
end
|
42
|
+
file.print "\n #{type.description}\n\n"
|
43
|
+
file.print "|attribute|type|multiplicity|description|\n"
|
44
|
+
file.print "|---------|----|------------|-----------|\n"
|
45
|
+
end,
|
46
|
+
attribute: lambda do |id:, val:, type:, depth:, index:, total:|
|
47
|
+
file.print "|#{val[:name]}|#{type_and_link(val)}|#{multiplicity(val)}|#{val[:description]}|\n"
|
48
|
+
end,
|
49
|
+
before_codes: lambda do |model:|
|
50
|
+
file.print "# Codes\n"
|
51
|
+
end,
|
52
|
+
code: lambda do |model:, code:|
|
53
|
+
file.print "## #{code[:id]} #{code[:title]}\n"
|
54
|
+
file.print "#{code[:description]}\n"
|
55
|
+
file.print "#{code[:uri]}\n"
|
56
|
+
end
|
57
|
+
}, *models)
|
110
58
|
end
|
111
|
-
self
|
112
59
|
end
|
113
60
|
|
114
61
|
def multiplicity m
|
@@ -125,57 +72,14 @@ class MetaTypeElement < Element
|
|
125
72
|
end
|
126
73
|
return m.to_s
|
127
74
|
end
|
128
|
-
end
|
129
|
-
|
130
|
-
class Doc
|
131
|
-
attr_accessor :path, :name
|
132
75
|
|
133
|
-
|
134
|
-
self.path = path
|
135
|
-
self.name = name
|
136
|
-
end
|
76
|
+
private
|
137
77
|
|
138
|
-
def
|
139
|
-
|
140
|
-
|
141
|
-
for model in models
|
142
|
-
dom = ClassNameElement.new(file)
|
143
|
-
dom.write model
|
144
|
-
for typename in model.contents.keys
|
145
|
-
grp = GroupElement.new(file)
|
146
|
-
grp.write typename
|
147
|
-
i = 1
|
148
|
-
for decl in model.contents[typename]
|
149
|
-
TypeDeclElement.new(file).write(0, i, decl).finish
|
150
|
-
i = i + 1
|
151
|
-
end
|
152
|
-
grp.finish
|
153
|
-
end
|
154
|
-
dom.finish
|
155
|
-
end
|
78
|
+
def type_and_link(val)
|
79
|
+
if val[:links]
|
80
|
+
return "#{val[:type]} -> #{val[:links]}"
|
156
81
|
end
|
157
|
-
|
158
|
-
|
159
|
-
def document_metamodel *models
|
160
|
-
FileUtils.mkpath doc_path
|
161
|
-
File.open(self.docfile, "w") do |file|
|
162
|
-
for model in models
|
163
|
-
dom = GroupElement.new(file)
|
164
|
-
dom.write model.name, level: 1
|
165
|
-
for type in model.types.values
|
166
|
-
MetaTypeElement.new(file).write(type).finish
|
167
|
-
end
|
168
|
-
dom.finish
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def docfile
|
174
|
-
File.join(doc_path, "#{self.name}.md")
|
175
|
-
end
|
176
|
-
|
177
|
-
def doc_path
|
178
|
-
File.join(self.path, "doc")
|
82
|
+
val[:type]
|
179
83
|
end
|
180
84
|
|
181
85
|
end
|
data/src/transform.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
module Transform
|
2
|
+
|
3
|
+
class Output
|
4
|
+
public
|
5
|
+
|
6
|
+
attr_accessor :dir, :name, :ext
|
7
|
+
|
8
|
+
def initialize dir, name, ext
|
9
|
+
self.dir = dir
|
10
|
+
self.name = name
|
11
|
+
self.ext = ext
|
12
|
+
end
|
13
|
+
|
14
|
+
def filepath
|
15
|
+
File.join(self.dir, "#{name}.#{ext}")
|
16
|
+
end
|
17
|
+
|
18
|
+
def file(&block)
|
19
|
+
FileUtils.mkpath dir
|
20
|
+
File.open(filepath, "w", &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def before_model_lambda model: nil
|
26
|
+
return [model: model]
|
27
|
+
end
|
28
|
+
|
29
|
+
def after_model_lambda model: nil, before: nil
|
30
|
+
return [model: model, before: before]
|
31
|
+
end
|
32
|
+
|
33
|
+
def before_codes_lambda model: nil
|
34
|
+
return [model: model]
|
35
|
+
end
|
36
|
+
|
37
|
+
def code_lambda model: nil, code: nil
|
38
|
+
return [model: model, code: code]
|
39
|
+
end
|
40
|
+
|
41
|
+
def before_group_lambda name: nil, depth: 0
|
42
|
+
return [name: name, depth: depth]
|
43
|
+
end
|
44
|
+
|
45
|
+
def after_group_lambda name: nil, before: nil, depth: 0
|
46
|
+
return [name: name, before: before, depth: depth]
|
47
|
+
end
|
48
|
+
|
49
|
+
def before_type_lambda type: nil, depth: 0, index: 0, total: 1
|
50
|
+
return [type: type, depth: depth, index: index, total: total]
|
51
|
+
end
|
52
|
+
|
53
|
+
def after_type_lambda type: nil, before: nil, depth: 0
|
54
|
+
return [type: type, before: before, depth: depth]
|
55
|
+
end
|
56
|
+
|
57
|
+
def before_array_lambda name: nil, decl: nil, depth: 0, total: 1
|
58
|
+
return [name: name, decl: decl, depth: depth, total: total]
|
59
|
+
end
|
60
|
+
|
61
|
+
def after_array_lambda index: 0, decl: nil, depth: 0, before: nil
|
62
|
+
return [index: index, decl: decl, depth: depth, before: before]
|
63
|
+
end
|
64
|
+
|
65
|
+
def attribute_lambda id:, val:, depth: 0, type: nil, index:, total:
|
66
|
+
return [id: id, val: val, depth: depth, type: type, index: index, total: total]
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param models - the models to transform
|
70
|
+
# @lambdas - set of function callbacks to transform
|
71
|
+
|
72
|
+
def transform_datamodel lambdas, *models
|
73
|
+
for model in models
|
74
|
+
dom = cond_call(lambdas, :before_model, *before_model_lambda(model: model))
|
75
|
+
for typename in model.contents.keys
|
76
|
+
grp = cond_call(lambdas, :before_group, *before_group_lambda(name: typename))
|
77
|
+
t = 0
|
78
|
+
# there will be more than one of each type
|
79
|
+
for type in model.contents[typename]
|
80
|
+
transform_type(lambdas, decl: type, name: typename, depth: 0, index: 0, total: 1)
|
81
|
+
t = t + 1
|
82
|
+
end
|
83
|
+
grp = cond_call(lambdas, :after_group, *after_group_lambda(name: typename, before: grp))
|
84
|
+
end
|
85
|
+
cond_call(lambdas, :after_model, *after_model_lambda(model: model, before: dom))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def transform_metamodel lambdas, *models
|
90
|
+
for model in models
|
91
|
+
dom = cond_call(lambdas, :before_model, *before_model_lambda(model: model))
|
92
|
+
for type in model.types.values
|
93
|
+
before = cond_call(lambdas, :before_type, *before_type_lambda(type: type, index:0, total:1))
|
94
|
+
i = 0
|
95
|
+
for ak in type.attributes.keys
|
96
|
+
av = type.attributes[ak]
|
97
|
+
cond_call(lambdas, :attribute, *attribute_lambda(id: ak, val: av, type: type, index: i, total: type.attributes.keys.length))
|
98
|
+
i = i + 1
|
99
|
+
end
|
100
|
+
cond_call(lambdas, :after_type, *after_type_lambda(type: type, before: before))
|
101
|
+
end
|
102
|
+
cond_call(lambdas, :after_model, *after_model_lambda(model: model, before: dom))
|
103
|
+
if model.respond_to? :codes
|
104
|
+
cond_call(lambdas, :before_codes, *before_codes_lambda(model: model))
|
105
|
+
for code in model.codes.values
|
106
|
+
cond_call(lambdas, :code, *code_lambda(model: model, code: code))
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def cond_call(lambdas, lam, *args)
|
113
|
+
if lambdas[lam]
|
114
|
+
return lambdas[lam].(*args)
|
115
|
+
end
|
116
|
+
return 0
|
117
|
+
end
|
118
|
+
|
119
|
+
def transform_type(lambdas, index:, name:, decl:, depth:, total:)
|
120
|
+
|
121
|
+
if decl.class <= Array
|
122
|
+
arrctx = cond_call(lambdas, :before_array, *before_array_lambda(name: name, decl: decl, depth: depth, total: decl.length))
|
123
|
+
j = 0
|
124
|
+
for aa in decl
|
125
|
+
transform_type(lambdas, index: j, decl: aa, name: name, depth: depth, total: decl.length)
|
126
|
+
j = j + 1
|
127
|
+
end
|
128
|
+
cond_call(lambdas, :after_array, *after_array_lambda(index: index, decl: decl, depth: depth, before: arrctx))
|
129
|
+
elsif decl.class <= DataType
|
130
|
+
before = cond_call(lambdas, :before_type, *before_type_lambda(type: decl, depth: depth, index: index, total: total))
|
131
|
+
i = 0
|
132
|
+
for ak in decl.attributes.keys
|
133
|
+
av = decl.attributes[ak]
|
134
|
+
transform_type(lambdas, name: ak, decl: av, depth: depth + 1, index: i, total: decl.attributes.keys.length)
|
135
|
+
i = i + 1
|
136
|
+
end
|
137
|
+
cond_call(lambdas, :after_type, *after_type_lambda(type: decl, depth: depth, before: before))
|
138
|
+
else
|
139
|
+
cond_call(lambdas, :attribute, *attribute_lambda(id: name, val: decl, index: index, depth: depth, total: total))
|
140
|
+
end
|
141
|
+
self
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|