xml_active 0.0.5 → 0.0.6

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.
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: []