xml_active 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/xml_active.rb +137 -133
  2. data/lib/xml_active/version.rb +1 -1
  3. metadata +3 -3
@@ -11,7 +11,7 @@ module XmlActive
11
11
  end while self.class.exists?(name => self[name])
12
12
  end
13
13
 
14
- VALID_FROM_XML_OPTIONS = [:sync, :create, :update, :destroy]
14
+ VALID_FROM_XML_OPTIONS = [:sync, :create, :update, :destroy, :fail_on_invalid]
15
15
 
16
16
  module ClassMethods
17
17
  def many_from_xml(source_xml, options = [])
@@ -19,84 +19,6 @@ module XmlActive
19
19
  many_from root_node_in source_xml
20
20
  end
21
21
 
22
- def many_from(current_node)
23
- case
24
- when self.name.pluralize.underscore.eql?(current_node.name.underscore)
25
- many_from_rails_xml current_node
26
-
27
- when (current_node.name.eql?('dataroot') \
28
- and current_node.namespace_definitions.map { |ns| ns.href }.include?('urn:schemas-microsoft-com:officedata'))
29
- # Identified as data generated from Microsoft Access
30
- many_from_ms_xml current_node
31
-
32
- when self.name.underscore.eql?(current_node.name.underscore)
33
- raise "The supplied XML (#{current_node.name}) is a single instance of '#{self.name}'. Please use one_from_xml"
34
-
35
- else
36
- raise "The supplied XML (#{current_node.name}) cannot be mapped to this class (#{self.name})"
37
-
38
- end
39
- end
40
-
41
- def many_from_ms_xml(current_node)
42
- records = []
43
- recorded_ids = []
44
-
45
- current_node.element_children.each do |node|
46
- if self.name.underscore.eql?(node.name.underscore)
47
- record = self.one_from_xml(node, @data_active_options)
48
- if record
49
- recorded_ids << record[primary_key.to_sym]
50
- records << record
51
- end
52
- end
53
- end
54
-
55
- remove_records_not_in recorded_ids
56
-
57
- records
58
- end
59
-
60
- def many_from_rails_xml(current_node)
61
- records = []
62
- recorded_ids = []
63
-
64
- current_node.element_children.each do |node|
65
- record = self.one_from_xml(node, @data_active_options)
66
- if record
67
- recorded_ids << record[primary_key.to_sym]
68
- records << record
69
- end
70
- end
71
-
72
- remove_records_not_in recorded_ids
73
-
74
- records
75
- end
76
-
77
- def remove_records_not_in(recorded_ids)
78
- if @data_active_options.include?(:sync)
79
- if recorded_ids.length > 0
80
- self.destroy_all [self.primary_key.to_s + " not in (?)", recorded_ids.collect]
81
- end
82
- elsif @data_active_options.include?(:destroy)
83
- if recorded_ids.length > 0
84
- self.destroy_all [self.primary_key.to_s + " not in (?)", recorded_ids.collect]
85
- else
86
- self.destroy_all
87
- end
88
- end
89
- end
90
-
91
- def root_node_in(source_xml)
92
- if source_xml.is_a?(String)
93
- doc = Nokogiri::XML(source_xml)
94
- doc.children.first
95
- else
96
- source_xml
97
- end
98
- end
99
-
100
22
  def one_from_xml(source_xml, options = [])
101
23
  @data_active_options = options
102
24
 
@@ -108,21 +30,14 @@ module XmlActive
108
30
 
109
31
  active_record = find_record_based_on(pk_node)
110
32
 
111
-
112
33
  unless active_record.nil?
113
34
  # Process the attributes
114
35
  if options.include? :update or options.include? :sync or options.include? :create
115
36
  assign_attributes_from current_node, :to => active_record
116
- end
117
-
118
- # Save the record
119
- if options.include? :sync
120
- # Doing complete synchronisation with XML
121
- active_record.save
122
- elsif options.include?(:create) and active_record.new_record?
123
- active_record.save
124
- elsif options.include?(:update) and not active_record.new_record?
125
- active_record.save
37
+ if options.include? :fail_on_invalid and !active_record.valid?
38
+ messages = active_record.errors.messages.map {|attribute, messages| "#{attribute} #{messages.map{|message| message }.join(', ')}"}.join(', ')
39
+ raise "Found an invalid #{active_record.class.name} with the following errors: #{messages}. Source: #{current_node.to_s}"
40
+ end
126
41
  end
127
42
 
128
43
  # Check through associations and apply sync appropriately
@@ -199,6 +114,16 @@ module XmlActive
199
114
  raise "unsupported association #{association.macro} for #{association.name } on #{self.name}"
200
115
  end
201
116
  end
117
+
118
+ # Save the record
119
+ if options.include? :sync
120
+ # Doing complete synchronisation with XML
121
+ active_record.save
122
+ elsif options.include?(:create) and active_record.new_record?
123
+ active_record.save
124
+ elsif options.include?(:update) and not active_record.new_record?
125
+ active_record.save
126
+ end
202
127
  end
203
128
 
204
129
  active_record
@@ -207,17 +132,50 @@ module XmlActive
207
132
  end
208
133
  end
209
134
 
210
- def foreign_key_from(association)
211
- if ActiveRecord::Reflection::AssociationReflection.method_defined? :foreign_key
212
- # Support for Rails 3.1 and later
213
- foreign_key = association.foreign_key
214
- elsif ActiveRecord::Reflection::AssociationReflection.method_defined? :primary_key_name
215
- # Support for Rails earlier than 3.1
216
- foreign_key = association.primary_key_name
135
+ private
136
+ def xml_node_matches_class(xml_node)
137
+ if xml_node.attributes['type'].blank?
138
+ xml_node.name.underscore == self.name.underscore
217
139
  else
218
- raise "Unsupported version of ActiveRecord. Unable to identify the foreign key."
140
+ xml_node.attributes['type'].value.underscore == self.name.underscore
141
+ end
142
+ end
143
+
144
+ def find_record_based_on(pk_node)
145
+ ar = nil
146
+ if pk_node
147
+ begin
148
+ ar = find pk_node.text
149
+ rescue
150
+ # No record exists, create a new one
151
+ if @data_active_options.include?(:sync) or @data_active_options.include?(:create)
152
+ ar = self.new
153
+ end
154
+ end
155
+ else
156
+ # No primary key value, must be a new record
157
+ if @data_active_options.include?(:sync) or @data_active_options.include?(:create)
158
+ ar = self.new
159
+ end
160
+ end
161
+ ar
162
+ end
163
+
164
+ def assign_attributes_from(current_node, options)
165
+ record = options[:to]
166
+
167
+ record.attributes.each do |name, value|
168
+ attribute_nodes = current_node.xpath name.to_s
169
+ if attribute_nodes.count == 1
170
+ if attribute_nodes[0].attributes['nil'].try(:value)
171
+ record[name] = nil
172
+ else
173
+ record[name] = attribute_nodes[0].text
174
+ end
175
+ elsif attribute_nodes.count > 1
176
+ raise "Found duplicate elements in xml for active record attribute '#{name}'"
177
+ end
219
178
  end
220
- foreign_key
221
179
  end
222
180
 
223
181
  def instances_for(association, options)
@@ -234,7 +192,7 @@ module XmlActive
234
192
  # </book>
235
193
  # </books>
236
194
  if active_record.new_record?
237
- results = current_node.xpath("//#{self.name.underscore}[#{self.primary_key}=#{current_node.xpath(self.primary_key.to_s).text}]/#{association.name}")
195
+ results = current_node.xpath("#{association.name}")
238
196
  else
239
197
  results = current_node.xpath("//#{self.name.underscore}[#{self.primary_key}=#{active_record.attributes[self.primary_key.to_s]}]/#{association.name}")
240
198
  end
@@ -246,7 +204,7 @@ module XmlActive
246
204
  # ...
247
205
  # </book>
248
206
  if active_record.new_record?
249
- results = current_node.xpath("//#{self.name.underscore}[#{self.primary_key}=#{current_node.xpath(self.primary_key.to_s).text}]/#{association.name.to_s.singularize}")
207
+ results = current_node.xpath("#{association.name.to_s.singularize}")
250
208
  else
251
209
  results = current_node.xpath("//#{self.name.underscore}[#{self.primary_key}=#{active_record.attributes[self.primary_key.to_s]}]/#{association.name.to_s.singularize}")
252
210
  end
@@ -257,48 +215,94 @@ module XmlActive
257
215
  results
258
216
  end
259
217
 
260
- def assign_attributes_from(current_node, options)
261
- record = options[:to]
218
+ def foreign_key_from(association)
219
+ if ActiveRecord::Reflection::AssociationReflection.method_defined? :foreign_key
220
+ # Support for Rails 3.1 and later
221
+ foreign_key = association.foreign_key
222
+ elsif ActiveRecord::Reflection::AssociationReflection.method_defined? :primary_key_name
223
+ # Support for Rails earlier than 3.1
224
+ foreign_key = association.primary_key_name
225
+ else
226
+ raise "Unsupported version of ActiveRecord. Unable to identify the foreign key."
227
+ end
228
+ foreign_key
229
+ end
262
230
 
263
- record.attributes.each do |name, value|
264
- attribute_nodes = current_node.xpath name.to_s
265
- if attribute_nodes.count == 1
266
- if attribute_nodes[0].attributes['nil'].try(:value)
267
- record[name] = nil
268
- else
269
- record[name] = attribute_nodes[0].text
270
- end
271
- elsif attribute_nodes.count > 1
272
- raise "Found duplicate elements in xml for active record attribute '#{name}'"
231
+ def root_node_in(source_xml)
232
+ if source_xml.is_a?(String)
233
+ doc = Nokogiri::XML(source_xml)
234
+ doc.children.first
235
+ else
236
+ source_xml
237
+ end
238
+ end
239
+
240
+ def remove_records_not_in(recorded_ids)
241
+ if @data_active_options.include?(:sync)
242
+ if recorded_ids.length > 0
243
+ self.destroy_all [self.primary_key.to_s + " not in (?)", recorded_ids.collect]
244
+ end
245
+ elsif @data_active_options.include?(:destroy)
246
+ if recorded_ids.length > 0
247
+ self.destroy_all [self.primary_key.to_s + " not in (?)", recorded_ids.collect]
248
+ else
249
+ self.destroy_all
273
250
  end
274
251
  end
275
252
  end
276
253
 
277
- def find_record_based_on(pk_node)
278
- ar = nil
279
- if pk_node
280
- begin
281
- ar = find pk_node.text
282
- rescue
283
- # No record exists, create a new one
284
- if @data_active_options.include?(:sync) or @data_active_options.include?(:create)
285
- ar = self.new
286
- end
254
+ def many_from_rails_xml(current_node)
255
+ records = []
256
+ recorded_ids = []
257
+
258
+ current_node.element_children.each do |node|
259
+ record = self.one_from_xml(node, @data_active_options)
260
+ if record
261
+ recorded_ids << record[primary_key.to_sym]
262
+ records << record
287
263
  end
288
- else
289
- # No primary key value, must be a new record
290
- if @data_active_options.include?(:sync) or @data_active_options.include?(:create)
291
- ar = self.new
264
+ end
265
+
266
+ remove_records_not_in recorded_ids
267
+
268
+ records
269
+ end
270
+
271
+ def many_from_ms_xml(current_node)
272
+ records = []
273
+ recorded_ids = []
274
+
275
+ current_node.element_children.each do |node|
276
+ if self.name.underscore.eql?(node.name.underscore)
277
+ record = self.one_from_xml(node, @data_active_options)
278
+ if record
279
+ recorded_ids << record[primary_key.to_sym]
280
+ records << record
281
+ end
292
282
  end
293
283
  end
294
- ar
284
+
285
+ remove_records_not_in recorded_ids
286
+
287
+ records
295
288
  end
296
289
 
297
- def xml_node_matches_class(xml_node)
298
- if xml_node.attributes['type'].blank?
299
- xml_node.name.underscore == self.name.underscore
300
- else
301
- xml_node.attributes['type'].value.underscore == self.name.underscore
290
+ def many_from(current_node)
291
+ case
292
+ when self.name.pluralize.underscore.eql?(current_node.name.underscore)
293
+ many_from_rails_xml current_node
294
+
295
+ when (current_node.name.eql?('dataroot') \
296
+ and current_node.namespace_definitions.map { |ns| ns.href }.include?('urn:schemas-microsoft-com:officedata'))
297
+ # Identified as data generated from Microsoft Access
298
+ many_from_ms_xml current_node
299
+
300
+ when self.name.underscore.eql?(current_node.name.underscore)
301
+ raise "The supplied XML (#{current_node.name}) is a single instance of '#{self.name}'. Please use one_from_xml"
302
+
303
+ else
304
+ raise "The supplied XML (#{current_node.name}) cannot be mapped to this class (#{self.name})"
305
+
302
306
  end
303
307
  end
304
308
  end
@@ -1,3 +1,3 @@
1
1
  module XmlActive
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xml_active
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-15 00:00:00.000000000 Z
12
+ date: 2012-07-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -97,5 +97,5 @@ rubyforge_project: xml_active
97
97
  rubygems_version: 1.8.22
98
98
  signing_key:
99
99
  specification_version: 3
100
- summary: xml_active 0.0.5
100
+ summary: xml_active 0.0.6
101
101
  test_files: []