gyro 0.4.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.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/README.md +840 -0
- data/bin/gyro +118 -0
- data/lib/gyro.rb +32 -0
- data/lib/gyro/realm/java/converter.rb +63 -0
- data/lib/gyro/realm/java/enum_generator.rb +128 -0
- data/lib/gyro/realm/java/generator.rb +183 -0
- data/lib/gyro/realm/java/templates.rb +67 -0
- data/lib/gyro/realm/objc/converter.rb +63 -0
- data/lib/gyro/realm/objc/enum_generator.rb +86 -0
- data/lib/gyro/realm/objc/generator.rb +373 -0
- data/lib/gyro/realm/objc/json_category_generator.rb +172 -0
- data/lib/gyro/realm/objc/protocol_generator.rb +59 -0
- data/lib/gyro/realm/objc/templates.rb +100 -0
- data/lib/gyro/realm/swift/converter.rb +74 -0
- data/lib/gyro/realm/swift/enum_generator.rb +73 -0
- data/lib/gyro/realm/swift/generator.rb +265 -0
- data/lib/gyro/realm/swift/object_mapper_generator.rb +124 -0
- data/lib/gyro/realm/swift/templates.rb +64 -0
- data/lib/gyro/utils/file_utils.rb +31 -0
- data/lib/gyro/utils/log.rb +68 -0
- data/lib/gyro/utils/raise.rb +23 -0
- data/lib/gyro/utils/string_xcdatamodel.rb +58 -0
- data/lib/gyro/xcdatamodel/parser/attribute.rb +98 -0
- data/lib/gyro/xcdatamodel/parser/entity.rb +234 -0
- data/lib/gyro/xcdatamodel/parser/relationship.rb +70 -0
- data/lib/gyro/xcdatamodel/parser/xcdatamodel.rb +59 -0
- metadata +77 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2016 - Niji
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
module Gyro
|
18
|
+
|
19
|
+
def self.find_xcdatamodel(dir)
|
20
|
+
Dir.chdir(dir) do
|
21
|
+
files = Dir.glob('*.xcdatamodel')
|
22
|
+
files.first.nil? ? nil : File.expand_path(files.first, dir)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.write_file_with_name(dir, name_file, content)
|
27
|
+
file_path = File.expand_path(name_file, dir)
|
28
|
+
File.write(file_path, content)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2016 - Niji
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
module Gyro
|
18
|
+
module Log
|
19
|
+
|
20
|
+
def self.title(str) # bg yellow
|
21
|
+
puts "\e[44;37m#{str}\e[0m"
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.error(str)
|
25
|
+
puts "\e[1;31m! #{str}\e[0m"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.info(str)
|
29
|
+
puts "\e[1;33m> #{str}\e[0m"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.success(str)
|
33
|
+
puts "\e[1;32m√ #{str}\e[0m"
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.prompt(str, url = nil)
|
37
|
+
prompt = "\e[1;36m ! #{str} [y/n]?\e[0m "
|
38
|
+
url_info = ' '*10 + "\e[0;37m (use '?' to show in browser)\e[0m"
|
39
|
+
print prompt
|
40
|
+
print "#{url_info}\r#{prompt}" if url
|
41
|
+
|
42
|
+
answer = get_char do |c|
|
43
|
+
`open '#{url}'` if url && (c == '?')
|
44
|
+
"yn\003".include?(c.downcase) # \003 = ctrl-C
|
45
|
+
end
|
46
|
+
puts answer + (url ? ' '*url_info.length : '')
|
47
|
+
answer.downcase == 'y'
|
48
|
+
end
|
49
|
+
|
50
|
+
private ######################################################################
|
51
|
+
|
52
|
+
def self.get_char
|
53
|
+
stop = false
|
54
|
+
typed_char = ''
|
55
|
+
begin
|
56
|
+
system('stty raw -echo')
|
57
|
+
until stop
|
58
|
+
typed_char = STDIN.getc.chr
|
59
|
+
stop = yield typed_char
|
60
|
+
end
|
61
|
+
ensure
|
62
|
+
system('stty -raw echo')
|
63
|
+
end
|
64
|
+
typed_char
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2016 - Niji
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
module Raise
|
18
|
+
|
19
|
+
def self.error(str)
|
20
|
+
raise "\e[1;31m! #{str}\e[0m"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2016 - Niji
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
class String
|
18
|
+
|
19
|
+
def delete_objc_prefix
|
20
|
+
i = 0
|
21
|
+
while i < self.length - 1 and /[[:upper:]]/.match(self[i+1])
|
22
|
+
i += 1
|
23
|
+
end
|
24
|
+
self[i..self.length]
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_inverse_suffix
|
28
|
+
self.gsub('_', '')
|
29
|
+
end
|
30
|
+
|
31
|
+
def capitalize_first_letter
|
32
|
+
self.slice(0, 1).capitalize + self.slice(1..-1)
|
33
|
+
end
|
34
|
+
|
35
|
+
def camel_case
|
36
|
+
words = self.scan(/[A-Z][a-z]+/)
|
37
|
+
words.map!(&:upcase)
|
38
|
+
words.join('_')
|
39
|
+
end
|
40
|
+
|
41
|
+
def underscore
|
42
|
+
self.gsub(/::/, '/').
|
43
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
44
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
45
|
+
tr('-', '_').
|
46
|
+
downcase
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_quotes
|
50
|
+
"\"" + self + "\""
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_parentheses
|
54
|
+
'(' + self + ')'
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2016 - Niji
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
module Gyro
|
18
|
+
module XCDataModel
|
19
|
+
module Parser
|
20
|
+
|
21
|
+
class Attribute
|
22
|
+
|
23
|
+
attr_accessor :entity_name, :name, :type, :optional, :indexed, :default
|
24
|
+
attr_accessor :realm_ignored, :realm_read_only, :enum_type, :enum_values
|
25
|
+
attr_accessor :json_key_path, :json_values, :transformer, :comment, :support_annotation
|
26
|
+
|
27
|
+
alias_method :optional?, :optional
|
28
|
+
alias_method :indexed?, :indexed
|
29
|
+
alias_method :realm_ignored?, :realm_ignored
|
30
|
+
|
31
|
+
def initialize (attribute_xml, entity_name)
|
32
|
+
@entity_name = entity_name
|
33
|
+
@name = attribute_xml.xpath('@name').to_s
|
34
|
+
@optional = attribute_xml.xpath('@optional').to_s == 'YES' ? true : false
|
35
|
+
@indexed = attribute_xml.xpath('@indexed').to_s == 'YES' ? true : false
|
36
|
+
@default = attribute_xml.xpath('@defaultValueString').to_s
|
37
|
+
@type = attribute_xml.xpath('@attributeType').to_s.downcase.gsub(' ', '_').to_sym
|
38
|
+
@realm_ignored = attribute_xml.xpath(USERINFO_VALUE%['realmIgnored']).to_s.empty? ? false : true
|
39
|
+
@realm_read_only = attribute_xml.xpath(USERINFO_VALUE%['realmReadOnly']).to_s
|
40
|
+
@enum_type = attribute_xml.xpath(USERINFO_VALUE%['enumType']).to_s
|
41
|
+
@enum_values = attribute_xml.xpath(USERINFO_VALUE%['enumValues']).to_s.split(',')
|
42
|
+
@json_key_path = attribute_xml.xpath(USERINFO_VALUE%['JSONKeyPath']).to_s
|
43
|
+
@json_values = attribute_xml.xpath(USERINFO_VALUE%['JSONValues']).to_s.split(',')
|
44
|
+
@transformer = attribute_xml.xpath(USERINFO_VALUE%['transformer']).to_s.strip
|
45
|
+
@comment = attribute_xml.xpath(USERINFO_VALUE%['comment']).to_s
|
46
|
+
@support_annotation = attribute_xml.xpath(USERINFO_VALUE%['supportAnnotation']).to_s
|
47
|
+
search_for_error
|
48
|
+
end
|
49
|
+
|
50
|
+
def enum?
|
51
|
+
!@enum_type.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
def read_only?
|
55
|
+
!@realm_read_only.empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
def has_default?
|
59
|
+
!@default.empty?
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
"\tAttribute => name=#{@name} | type=#{@type} | optional=#{@optional} | default=#{@default} | indexed=#{@indexed}\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
def is_decimal?
|
67
|
+
@type == :decimal or @type == :double or @type == :float
|
68
|
+
end
|
69
|
+
|
70
|
+
def is_integer?
|
71
|
+
@type == :integer_16 or @type == :integer_32 or @type == :integer_64
|
72
|
+
end
|
73
|
+
|
74
|
+
def is_number?
|
75
|
+
is_decimal? or is_integer?
|
76
|
+
end
|
77
|
+
|
78
|
+
def is_bool?
|
79
|
+
@type == :boolean
|
80
|
+
end
|
81
|
+
|
82
|
+
def need_transformer?
|
83
|
+
!@enum_type.empty? or @type == :boolean or @type == :date or !@transformer.empty?
|
84
|
+
end
|
85
|
+
|
86
|
+
private ################################################################
|
87
|
+
|
88
|
+
def search_for_error
|
89
|
+
Raise::error("The attribute \"%s\" from \"%s\" has no type - please fix it"%[@name, @entity_name]) if @type == :undefined || @type.empty?
|
90
|
+
Raise::error("The attribute \"%s\" from \"%s\" is enum with incorrect type (not Integer) - please fix it"%[@name, @entity_name]) if !@enum_type.empty? and !@enum_values.empty? and !is_integer?
|
91
|
+
Raise::error("The attribute \"%s\" from \"%s\" is wrongly annotated: when declaring an type with enum and JSONKeyPath, you must have the same number of items in the 'enumValues' and 'JSONValues' annotations - please fix it"%[@name, @entity_name]) if !@json_key_path.empty? and !@enum_values.empty? and @enum_values.size != @json_values.size
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2016 - Niji
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
=end
|
16
|
+
|
17
|
+
require 'nokogiri'
|
18
|
+
require 'set'
|
19
|
+
require File.expand_path('relationship', File.dirname(__FILE__))
|
20
|
+
require File.expand_path('attribute', File.dirname(__FILE__))
|
21
|
+
|
22
|
+
module Gyro
|
23
|
+
module XCDataModel
|
24
|
+
module Parser
|
25
|
+
class Entity
|
26
|
+
|
27
|
+
attr_accessor :name, :parent, :abstract, :attributes, :relationships, :identity_attribute, :comment
|
28
|
+
alias_method :abstract?, :abstract
|
29
|
+
|
30
|
+
def initialize(entity_xml)
|
31
|
+
@name = entity_xml.xpath('@name').to_s
|
32
|
+
@parent = entity_xml.xpath('@parentEntity').to_s
|
33
|
+
@abstract = entity_xml.xpath('@isAbstract').to_s == 'YES' ? true : false
|
34
|
+
@clean = false
|
35
|
+
@identity_attribute = entity_xml.xpath(USERINFO_VALUE%['identityAttribute']).to_s
|
36
|
+
@comment = entity_xml.xpath(USERINFO_VALUE%['comment']).to_s
|
37
|
+
@attributes = Hash.new
|
38
|
+
@relationships = Hash.new
|
39
|
+
load_entity(entity_xml)
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
str = "\nEntity => #{@name}\n"
|
44
|
+
@attributes.each do |_, attribute|
|
45
|
+
str += attribute.to_s
|
46
|
+
end
|
47
|
+
@relationships.each do |_, relationship|
|
48
|
+
str += relationship.to_s
|
49
|
+
end
|
50
|
+
str
|
51
|
+
end
|
52
|
+
|
53
|
+
def used_as_list_by_other?(entities)
|
54
|
+
entities.each do |_, entity|
|
55
|
+
entity.relationships.each do |_, relationship|
|
56
|
+
return true if relationship.inverse_type == @name and relationship.type == :to_many
|
57
|
+
end
|
58
|
+
end
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
def has_list_attributes?(inverse = false)
|
63
|
+
@relationships.each do |_, relationship|
|
64
|
+
return true if relationship.type == :to_many and (!inverse ? !relationship.inverse? : true)
|
65
|
+
end
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
def has_no_inverse_relationship?
|
70
|
+
@relationships.each do |_, relationship|
|
71
|
+
return true unless relationship.inverse?
|
72
|
+
end
|
73
|
+
false
|
74
|
+
end
|
75
|
+
|
76
|
+
def has_ignored?
|
77
|
+
@attributes.each do |_, attribute|
|
78
|
+
return true if attribute.realm_ignored?
|
79
|
+
end
|
80
|
+
@relationships.each do |_, relationship|
|
81
|
+
return true if relationship.realm_ignored?
|
82
|
+
end
|
83
|
+
false
|
84
|
+
end
|
85
|
+
|
86
|
+
def has_primary_key?
|
87
|
+
!@identity_attribute.empty?
|
88
|
+
end
|
89
|
+
|
90
|
+
def has_required?
|
91
|
+
@attributes.each do |_, attribute|
|
92
|
+
return true if is_required?(attribute)
|
93
|
+
end
|
94
|
+
false
|
95
|
+
end
|
96
|
+
|
97
|
+
def is_required?(attribute)
|
98
|
+
unless attribute.optional?
|
99
|
+
return true unless self.has_primary_key?
|
100
|
+
return true if self.has_primary_key? && !attribute.name.eql?(identity_attribute)
|
101
|
+
end
|
102
|
+
false
|
103
|
+
end
|
104
|
+
|
105
|
+
def has_default_value?(attribute = @identity_attribute)
|
106
|
+
attribute.name != @identity_attribute
|
107
|
+
end
|
108
|
+
|
109
|
+
def has_indexed_attributes?
|
110
|
+
@attributes.each do |_, attribute|
|
111
|
+
return true if attribute.indexed?
|
112
|
+
end
|
113
|
+
false
|
114
|
+
end
|
115
|
+
|
116
|
+
def has_json_key_path?
|
117
|
+
@attributes.each do |_, attribute|
|
118
|
+
return true unless attribute.json_key_path.empty?
|
119
|
+
end
|
120
|
+
@relationships.each do |_, relationship|
|
121
|
+
return true if !relationship.inverse? and !relationship.json_key_path.empty?
|
122
|
+
end
|
123
|
+
false
|
124
|
+
end
|
125
|
+
|
126
|
+
def has_enum_attributes?
|
127
|
+
@attributes.each do |_, attribute|
|
128
|
+
return true unless attribute.enum_type.empty?
|
129
|
+
end
|
130
|
+
false
|
131
|
+
end
|
132
|
+
|
133
|
+
def transformers
|
134
|
+
transformers = Set.new
|
135
|
+
@attributes.each do |_, attribute|
|
136
|
+
transformers.add attribute.transformer unless attribute.transformer.empty?
|
137
|
+
end
|
138
|
+
transformers
|
139
|
+
end
|
140
|
+
|
141
|
+
def has_custom_transformers?
|
142
|
+
@attributes.each do |_, attribute|
|
143
|
+
return true unless attribute.transformer.empty?
|
144
|
+
end
|
145
|
+
false
|
146
|
+
end
|
147
|
+
|
148
|
+
def need_transformer?
|
149
|
+
has_enum_attributes? || has_bool_attributes? || has_custom_transformers? || has_date_attribute?
|
150
|
+
end
|
151
|
+
|
152
|
+
def has_bool_attributes?
|
153
|
+
has_bool_attributes = false
|
154
|
+
@attributes.each do |_, attribute|
|
155
|
+
has_bool_attributes = true if attribute.type == :boolean
|
156
|
+
end
|
157
|
+
has_bool_attributes
|
158
|
+
end
|
159
|
+
|
160
|
+
def has_number_attributes?
|
161
|
+
has_number_attributes = false
|
162
|
+
@attributes.each do |_, attribute|
|
163
|
+
if attribute.enum_type.empty?
|
164
|
+
case attribute.type
|
165
|
+
when :integer_16 then
|
166
|
+
has_number_attributes = true
|
167
|
+
when :integer_32 then
|
168
|
+
has_number_attributes = true
|
169
|
+
when :integer_64 then
|
170
|
+
has_number_attributes = true
|
171
|
+
when :decimal then
|
172
|
+
has_number_attributes = true
|
173
|
+
when :double then
|
174
|
+
has_number_attributes = true
|
175
|
+
when :float then
|
176
|
+
has_number_attributes = true
|
177
|
+
else
|
178
|
+
has_number_attributes = false
|
179
|
+
end
|
180
|
+
break if has_number_attributes
|
181
|
+
end
|
182
|
+
end
|
183
|
+
has_number_attributes
|
184
|
+
end
|
185
|
+
|
186
|
+
def has_date_attribute?
|
187
|
+
@attributes.each do |_, attribute|
|
188
|
+
return true if attribute.type == :date
|
189
|
+
end
|
190
|
+
false
|
191
|
+
end
|
192
|
+
|
193
|
+
def has_list_relationship?
|
194
|
+
@relationships.each do |_, relationship|
|
195
|
+
return true unless relationship.destination.empty?
|
196
|
+
end
|
197
|
+
false
|
198
|
+
end
|
199
|
+
|
200
|
+
def has_only_inverse?
|
201
|
+
nb_inverses = 0
|
202
|
+
@relationships.each do |_, relationship|
|
203
|
+
nb_inverses+=1 if relationship.inverse?
|
204
|
+
end
|
205
|
+
nb_inverses==@relationships.size
|
206
|
+
end
|
207
|
+
|
208
|
+
private ################################################################
|
209
|
+
|
210
|
+
def load_entity(entity_xml)
|
211
|
+
load_attributes(entity_xml)
|
212
|
+
load_relationships(entity_xml)
|
213
|
+
end
|
214
|
+
|
215
|
+
def load_attributes(entity_xml)
|
216
|
+
entity_xml.xpath('attribute').each do |node|
|
217
|
+
attribute = Attribute.new(node, @name)
|
218
|
+
if attribute.type != 'Transformable'
|
219
|
+
@attributes[attribute.name] = attribute
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def load_relationships(entity_xml)
|
225
|
+
entity_xml.xpath('relationship').each do |node|
|
226
|
+
relationship = Relationship.new(node, @name)
|
227
|
+
@relationships[relationship.name] = relationship
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|