data_active 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/features/step_definitions/sync_books_with_xml.rb +48 -3
- data/features/support/fixtures/xml/books_fresh_without_ids.xml +5 -0
- data/features/support/fixtures/xml/ms_access/books_fresh_without_ids.xml +5 -0
- data/features/sync_one_to_many.feature +1 -0
- data/lib/data_active.rb +46 -60
- data/lib/data_active/version.rb +1 -1
- metadata +3 -3
@@ -110,6 +110,12 @@ When /^the book price will be identical to those in "([^"]*)"$/ do |xml_document
|
|
110
110
|
if book_price.nil?
|
111
111
|
fail "BookPrice with id #{book_price_id} is missing"
|
112
112
|
else
|
113
|
+
if book_price.book_id.nil?
|
114
|
+
fail "BookPrice.book_id in database isn't being set (expecting book_id = #{book_id})"
|
115
|
+
elsif book_price.book_id != book_id.to_i
|
116
|
+
fail "BookPrice.book_id in database is set incorrectly (expecting book_id = #{book_id} and got #{book_price.book_id})"
|
117
|
+
end
|
118
|
+
|
113
119
|
book_price_sell = book_price_element.xpath("sell").text
|
114
120
|
book_price_educational = book_price_element.xpath("educational").text
|
115
121
|
book_price_cost = book_price_element.xpath("cost").text
|
@@ -141,6 +147,40 @@ When /^the book price will be identical to those in "([^"]*)"$/ do |xml_document
|
|
141
147
|
end
|
142
148
|
end
|
143
149
|
|
150
|
+
When /^the book price will be identical to those in "([^"]*)" with new ids$/ do |xml_document_file|
|
151
|
+
xml_document = Nokogiri::XML(File.open(Rails.root.join(xml_document_file)).read)
|
152
|
+
|
153
|
+
# Ensure that all chapters in the xml document have been recorded
|
154
|
+
xml_document.xpath('//book').each do |book_element|
|
155
|
+
book = Book.find_by_name book_element.xpath('name')[0].text
|
156
|
+
book_id = book.id
|
157
|
+
book_price_element = book_element.xpath('book_price')
|
158
|
+
book_price = BookPrice.find_by_book_id book_id
|
159
|
+
|
160
|
+
fail 'Too many book prices' if book_price_element.count > 1
|
161
|
+
|
162
|
+
if book_price.nil?
|
163
|
+
fail "BookPrice for book '#{book.name}' is missing"
|
164
|
+
else
|
165
|
+
book_price_sell = book_price_element.xpath('sell').text
|
166
|
+
book_price_educational = book_price_element.xpath('educational').text
|
167
|
+
book_price_cost = book_price_element.xpath('cost').text
|
168
|
+
|
169
|
+
if Float(book_price_sell) != book_price.sell
|
170
|
+
fail "BookPrice 'sell' in database doesn't match book price sell in xml for book '#{book.name}', XML: #{book_price_sell}, Database: #{book_price.sell}"
|
171
|
+
end
|
172
|
+
|
173
|
+
if Float(book_price_cost) != book_price.cost
|
174
|
+
fail "BookPrice 'cost' in database doesn't match book price cost in xml for book '#{book.name}', XML: #{book_price_cost}, Database: #{book_price.cost}"
|
175
|
+
end
|
176
|
+
|
177
|
+
if Float(book_price_educational) != book_price.educational
|
178
|
+
fail "BookPrice 'educational' in database doesn't match book price educational in xml for book '#{book.name}', XML: #{book_price_educational}, Database: #{book_price.educational}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
144
184
|
When /^the chapters will be identical to those in "([^"]*)"$/ do |xml_document_file|
|
145
185
|
chapters_in_database = Chapter.all
|
146
186
|
if chapters_in_database.count > 0
|
@@ -190,18 +230,23 @@ When /^the chapters will be identical to those in "([^"]*)" with new ids$/ do |x
|
|
190
230
|
xml_document.xpath("//book").each do |book_element|
|
191
231
|
book = Book.where(:name => book_element.xpath("name")[0].text).first
|
192
232
|
book_id = book.id
|
193
|
-
xml_document.xpath("//book[name[text()='#{
|
233
|
+
xml_document.xpath("//book[name[text()='#{book.name}']]/chapters/chapter").each do |chapter_element|
|
194
234
|
chapter_title = chapter_element.xpath("title")[0].text
|
195
235
|
chapter_introduction = chapter_element.xpath("introduction")[0].text
|
196
|
-
chapter = book.chapters.where(:title => chapter_title)
|
236
|
+
chapter = book.chapters.where(:title => chapter_title).first
|
197
237
|
|
198
238
|
if chapter == nil
|
199
239
|
fail "Chapters #{chapter_title} is missing"
|
200
240
|
else
|
241
|
+
if chapter.book_id.nil?
|
242
|
+
fail "Chapter.book_id in database isn't being set (expecting book_id = #{book_id}"
|
243
|
+
elsif chapter.book_id != book_id
|
244
|
+
fail "Chapter.book_id in database is set incorrectly (expecting book_id = #{book_id} and got #{chapter.book_id})"
|
245
|
+
end
|
201
246
|
if chapter_introduction != chapter.introduction
|
202
247
|
fail "Chapter introduction in database doesn't match chapter introduction in xml for chapter #{chapter_title}, XML: #{chapter_introduction}, Database: #{chapter.introduction}"
|
203
248
|
end
|
204
|
-
if book_id != chapter.book_id
|
249
|
+
if book_id != chapter.book_id
|
205
250
|
fail "Chapter book_id in database doesn't match chapter book_id in xml for chapter #{chapter_title}, XML: #{book_id}, Database: #{chapter.book_id}"
|
206
251
|
end
|
207
252
|
end
|
@@ -110,6 +110,11 @@
|
|
110
110
|
</book>
|
111
111
|
<book>
|
112
112
|
<name>Book 2</name>
|
113
|
+
<book_price>
|
114
|
+
<sell>50.00</sell>
|
115
|
+
<educational>35.00</educational>
|
116
|
+
<cost>20.00</cost>
|
117
|
+
</book_price>
|
113
118
|
<chapter>
|
114
119
|
<title>B2 Chapter 1</title>
|
115
120
|
<introduction>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus purus nulla, condimentum vitae
|
@@ -45,6 +45,7 @@ Feature: Synchronise one to many relationships
|
|
45
45
|
When I synchronise with "<xml_file>"
|
46
46
|
Then the books in the database will be identical to those in "<xml_file>" with new ids
|
47
47
|
And the chapters will be identical to those in "<xml_file>" with new ids
|
48
|
+
And the book price will be identical to those in "<xml_file>" with new ids
|
48
49
|
|
49
50
|
Examples:
|
50
51
|
| xml_file |
|
data/lib/data_active.rb
CHANGED
@@ -28,7 +28,7 @@ module DataActive
|
|
28
28
|
# Load or create a new record
|
29
29
|
pk_node = current_node.xpath self.primary_key.to_s
|
30
30
|
|
31
|
-
active_record =
|
31
|
+
active_record = find_or_create_based_on(pk_node)
|
32
32
|
|
33
33
|
unless active_record.nil?
|
34
34
|
# Process the attributes
|
@@ -41,7 +41,6 @@ module DataActive
|
|
41
41
|
end
|
42
42
|
|
43
43
|
# Check through associations and apply sync appropriately
|
44
|
-
associations = self.reflect_on_all_associations
|
45
44
|
self.reflect_on_all_associations.each do |association|
|
46
45
|
foreign_key = foreign_key_from(association)
|
47
46
|
klass = association.klass
|
@@ -101,7 +100,11 @@ module DataActive
|
|
101
100
|
new_record = klass.one_from_xml(single_objects[0], options)
|
102
101
|
if new_record != nil
|
103
102
|
new_record[foreign_key.to_sym] = active_record[self.primary_key.to_s]
|
104
|
-
new_record
|
103
|
+
if active_record.new_record?
|
104
|
+
active_record.send("#{klass.name.underscore.to_sym}=", new_record)
|
105
|
+
else
|
106
|
+
new_record.save!
|
107
|
+
end
|
105
108
|
end
|
106
109
|
end
|
107
110
|
elsif single_objects.count > 1
|
@@ -142,6 +145,44 @@ module DataActive
|
|
142
145
|
end
|
143
146
|
|
144
147
|
private
|
148
|
+
def many_from(current_node)
|
149
|
+
case
|
150
|
+
when (is_ms_access_xml?(current_node) or is_rails_like_xml?(current_node))
|
151
|
+
process_children_for current_node
|
152
|
+
|
153
|
+
when self.name.underscore.eql?(current_node.name.underscore)
|
154
|
+
raise "The supplied XML (#{current_node.name}) is a single instance of '#{self.name}'. Please use one_from_xml"
|
155
|
+
|
156
|
+
else
|
157
|
+
raise "The supplied XML (#{current_node.name}) cannot be mapped to this class (#{self.name})"
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def process_children_for(current_node)
|
163
|
+
records = []
|
164
|
+
recorded_ids = []
|
165
|
+
|
166
|
+
current_node.xpath(".//#{self.name.underscore}").each do |node|
|
167
|
+
record = self.one_from_xml(node, @data_active_options)
|
168
|
+
if record
|
169
|
+
recorded_ids << record[primary_key.to_sym]
|
170
|
+
records << record
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
remove_records_not_in recorded_ids
|
175
|
+
records
|
176
|
+
end
|
177
|
+
|
178
|
+
def is_ms_access_xml?(node)
|
179
|
+
node.name.eql?('dataroot') and node.namespace_definitions.map { |ns| ns.href }.include?('urn:schemas-microsoft-com:officedata')
|
180
|
+
end
|
181
|
+
|
182
|
+
def is_rails_like_xml?(current_node)
|
183
|
+
self.name.pluralize.underscore.eql?(current_node.name.underscore)
|
184
|
+
end
|
185
|
+
|
145
186
|
def xml_node_matches_class(xml_node)
|
146
187
|
if xml_node.attributes['type'].blank?
|
147
188
|
xml_node.name.underscore == self.name.underscore
|
@@ -150,7 +191,7 @@ module DataActive
|
|
150
191
|
end
|
151
192
|
end
|
152
193
|
|
153
|
-
def
|
194
|
+
def find_or_create_based_on(pk_node)
|
154
195
|
ar = nil
|
155
196
|
if pk_node
|
156
197
|
begin
|
@@ -232,7 +273,7 @@ module DataActive
|
|
232
273
|
# Support for Rails earlier than 3.1
|
233
274
|
foreign_key = association.primary_key_name
|
234
275
|
else
|
235
|
-
raise
|
276
|
+
raise 'Unsupported version of ActiveRecord. Unable to identify the foreign key.'
|
236
277
|
end
|
237
278
|
foreign_key
|
238
279
|
end
|
@@ -259,61 +300,6 @@ module DataActive
|
|
259
300
|
end
|
260
301
|
end
|
261
302
|
end
|
262
|
-
|
263
|
-
def many_from_rails_xml(current_node)
|
264
|
-
records = []
|
265
|
-
recorded_ids = []
|
266
|
-
|
267
|
-
current_node.element_children.each do |node|
|
268
|
-
record = self.one_from_xml(node, @data_active_options)
|
269
|
-
if record
|
270
|
-
recorded_ids << record[primary_key.to_sym]
|
271
|
-
records << record
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
remove_records_not_in recorded_ids
|
276
|
-
|
277
|
-
records
|
278
|
-
end
|
279
|
-
|
280
|
-
def many_from_ms_xml(current_node)
|
281
|
-
records = []
|
282
|
-
recorded_ids = []
|
283
|
-
|
284
|
-
current_node.element_children.each do |node|
|
285
|
-
if self.name.underscore.eql?(node.name.underscore)
|
286
|
-
record = self.one_from_xml(node, @data_active_options)
|
287
|
-
if record
|
288
|
-
recorded_ids << record[primary_key.to_sym]
|
289
|
-
records << record
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
remove_records_not_in recorded_ids
|
295
|
-
|
296
|
-
records
|
297
|
-
end
|
298
|
-
|
299
|
-
def many_from(current_node)
|
300
|
-
case
|
301
|
-
when self.name.pluralize.underscore.eql?(current_node.name.underscore)
|
302
|
-
many_from_rails_xml current_node
|
303
|
-
|
304
|
-
when (current_node.name.eql?('dataroot') \
|
305
|
-
and current_node.namespace_definitions.map { |ns| ns.href }.include?('urn:schemas-microsoft-com:officedata'))
|
306
|
-
# Identified as data generated from Microsoft Access
|
307
|
-
many_from_ms_xml current_node
|
308
|
-
|
309
|
-
when self.name.underscore.eql?(current_node.name.underscore)
|
310
|
-
raise "The supplied XML (#{current_node.name}) is a single instance of '#{self.name}'. Please use one_from_xml"
|
311
|
-
|
312
|
-
else
|
313
|
-
raise "The supplied XML (#{current_node.name}) cannot be mapped to this class (#{self.name})"
|
314
|
-
|
315
|
-
end
|
316
|
-
end
|
317
303
|
end
|
318
304
|
end
|
319
305
|
|
data/lib/data_active/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: data_active
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
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: 2013-04-
|
12
|
+
date: 2013-04-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -280,7 +280,7 @@ rubyforge_project: data_active
|
|
280
280
|
rubygems_version: 1.8.22
|
281
281
|
signing_key:
|
282
282
|
specification_version: 3
|
283
|
-
summary: data_active 0.0.
|
283
|
+
summary: data_active 0.0.6
|
284
284
|
test_files:
|
285
285
|
- features/remove_records_missing_in_xml.feature
|
286
286
|
- features/step_definitions/remove_records_missing_in_xml.rb
|