jcangas-datagateway 1.2.2 → 1.4.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.
- data/VERSION.yml +2 -2
- data/lib/datagateway/conduits/csv_conduit.rb +0 -0
- data/lib/datagateway/conduits/yaml_conduit.rb +0 -0
- data/lib/datagateway/data_gateway.rb +27 -514
- data/lib/datagateway/dbchange_point.rb +0 -0
- data/lib/datagateway/encoder.rb +27 -0
- data/lib/datagateway/folder_writer.rb +0 -0
- data/lib/datagateway/job.rb +223 -0
- data/lib/datagateway/jobs/nexus_export.rb +7 -6
- data/lib/datagateway/jobs/nexus_import.rb +1 -4
- data/lib/datagateway/jobs/shopin_export.rb +9 -6
- data/lib/datagateway/jobs/shopin_import.rb +9 -8
- data/lib/datagateway/mapper.rb +226 -0
- data/lib/datagateway/nexus/nax_ar.rb +0 -0
- data/lib/datagateway/nexus/nax_tlb.rb +0 -0
- data/lib/datagateway/nexus/nexus_ar.rb +0 -0
- data/lib/datagateway/ssh_transfer.rb +0 -0
- data/lib/datagateway.rb +111 -77
- data/lib/version.rb +0 -0
- data/template-prj/{README → nexus/README} +0 -0
- data/template-prj/{config → nexus/config}/README +0 -0
- data/template-prj/nexus/config/database.yml +17 -0
- data/template-prj/{config → nexus/config}/settings.yml +0 -2
- data/template-prj/{data → nexus/data}/donebox/README +0 -0
- data/template-prj/{data → nexus/data}/inbox/README +0 -0
- data/template-prj/{data → nexus/data}/outbox/README +0 -0
- data/template-prj/nexus/export-data.rb +9 -0
- data/template-prj/nexus/import-data.rb +14 -0
- data/template-prj/{log → nexus/log}/README +0 -0
- data/template-prj/{ruby.exe → nexus/ruby.exe} +0 -0
- data/template-prj/nexus/sistema.ini +4 -0
- data/template-prj/shopin/README +2 -0
- data/template-prj/shopin/config/README +4 -0
- data/template-prj/shopin/config/database.yml +8 -0
- data/template-prj/shopin/config/settings.yml +13 -0
- data/template-prj/shopin/data/donebox/README +1 -0
- data/template-prj/shopin/data/inbox/README +1 -0
- data/template-prj/shopin/data/outbox/README +1 -0
- data/template-prj/shopin/export-data.rb +6 -0
- data/template-prj/shopin/import-data.rb +6 -0
- data/template-prj/shopin/log/README +2 -0
- data/test/datagateway_test.rb +0 -0
- data/test/test_helper.rb +0 -0
- metadata +41 -20
- data/template-prj/config/database.yml +0 -32
- data/template-prj/dgw-job.rb +0 -25
- data/template-prj/run.bat +0 -1
- data/template-prj/sistema.ini +0 -3
data/VERSION.yml
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -1,33 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
3
|
require 'rubygems'
|
|
4
|
+
require 'jcode'
|
|
4
5
|
require 'benchmark'
|
|
5
6
|
require 'fileutils'
|
|
6
7
|
require 'zip/zip'
|
|
7
8
|
require 'folder_writer'
|
|
8
9
|
require 'iconv'
|
|
9
10
|
require 'ssh_transfer'
|
|
10
|
-
require '
|
|
11
|
+
require 'job'
|
|
12
|
+
require 'active_support'
|
|
13
|
+
|
|
11
14
|
|
|
12
15
|
module DataGateway
|
|
13
16
|
CONDUIT_DIR = File.join(File.dirname(__FILE__), 'conduits')
|
|
14
17
|
@@resource_path = ''
|
|
15
18
|
@@use_resources = false
|
|
16
19
|
class << self
|
|
17
|
-
attr_accessor :logger, :inbox, :outbox, :donebox
|
|
20
|
+
attr_accessor :last_time, :logger, :inbox, :outbox, :donebox
|
|
18
21
|
|
|
19
22
|
def use_resources
|
|
20
|
-
@@use_resources
|
|
21
|
-
end
|
|
23
|
+
@@use_resources
|
|
24
|
+
end
|
|
22
25
|
|
|
23
26
|
def use_resources=(value)
|
|
24
27
|
@@use_resources = value
|
|
25
|
-
end
|
|
28
|
+
end
|
|
26
29
|
|
|
27
30
|
def conduit_for(formatid)
|
|
28
31
|
conduitid = File.basename(formatid.to_s, '.zip').split('.').last
|
|
29
32
|
conduit_class = conduitid.upcase + 'Conduit'
|
|
30
|
-
unless Object.const_defined?(conduit_class)
|
|
33
|
+
unless Object.const_defined?(conduit_class)
|
|
31
34
|
conduit_file = conduitid.downcase + '_' + 'conduit.rb'
|
|
32
35
|
require File.join(CONDUIT_DIR, conduit_file)
|
|
33
36
|
end
|
|
@@ -46,498 +49,10 @@ module DataGateway
|
|
|
46
49
|
Object.const_get(class_name)
|
|
47
50
|
end
|
|
48
51
|
end
|
|
49
|
-
|
|
50
|
-
class NullEncoder
|
|
51
|
-
def pack(data)
|
|
52
|
-
data
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def unpack(data)
|
|
56
|
-
data
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
class Encoder
|
|
61
|
-
def initialize(options)
|
|
62
|
-
@pack = Iconv.new(options[:to], options[:from])
|
|
63
|
-
@unpack = Iconv.new(options[:from], options[:to])
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def pack(data)
|
|
67
|
-
@pack.iconv(data)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def unpack(data)
|
|
71
|
-
@unpack.iconv(data)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
class ColumnMapper
|
|
76
|
-
attr :options
|
|
77
|
-
def initialize(table_mapper, options = {})
|
|
78
|
-
@table_mapper = table_mapper
|
|
79
|
-
@options = options
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def apply_to(record, value)
|
|
83
|
-
DataGateway.logger.debug "apply_to(#{record.inspect}, #{value}) options #{@options.inspect}"
|
|
84
|
-
send(@options[:method], record, value)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# value mappers
|
|
88
|
-
def none(record, value)
|
|
89
|
-
# do nothing
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def write_to(record, value)
|
|
93
|
-
record[@options[:write_to]] = value
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def lookup(record, value)
|
|
97
|
-
|
|
98
|
-
result_status = {}
|
|
99
|
-
new_value = lookup_map(value, result_status)
|
|
100
|
-
if result_status[:found]
|
|
101
|
-
write_to(record, new_value)
|
|
102
|
-
else
|
|
103
|
-
@table_mapper.register_fixup(value, self)
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
private
|
|
108
|
-
|
|
109
|
-
def lookup_map(value, result_status)
|
|
110
|
-
DataGateway.logger.debug "lookup_map(#{value}, #{result_status}) options #{@options.inspect}"
|
|
111
|
-
lookup_model = DataGateway.model_for(@options[:table])
|
|
112
|
-
finder = "find_or_create_by_#{@options[:key]}"
|
|
113
|
-
lookup_rec = lookup_model.send(finder, value)
|
|
114
|
-
result_status[:found] = !(lookup_rec.nil?)
|
|
115
|
-
if result_status[:found]
|
|
116
|
-
lookup_rec.send(@options[:value]).to_s # valor mapeado
|
|
117
|
-
else
|
|
118
|
-
nil
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def solve_fixup(record, value)
|
|
123
|
-
DataGateway.logger.debug "mapper #{@map_method} opt. #{@options.inspect}"
|
|
124
|
-
result_status = {}
|
|
125
|
-
DataGateway.logger.debug "lookup #{record.inspect} -> <#{value}>"
|
|
126
|
-
value = lookup_map(value, result_status)
|
|
127
|
-
if result_status[:found]
|
|
128
|
-
DataGateway.logger.debug "FOUND: #{value}"
|
|
129
|
-
write_to(record, value)
|
|
130
|
-
else
|
|
131
|
-
DataGateway.logger.debug "NOT FOUND!"
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
class TableMapper
|
|
137
|
-
attr :source
|
|
138
|
-
attr :identity
|
|
139
|
-
|
|
140
|
-
def initialize(job, table)
|
|
141
|
-
@job = job
|
|
142
|
-
@source = table
|
|
143
|
-
@target = table
|
|
144
|
-
@column_map = {}
|
|
145
|
-
@identity = [:id]
|
|
146
|
-
@ar_fixups = []
|
|
147
|
-
@force_case = false
|
|
148
|
-
clear_fixups
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def ignore!
|
|
152
|
-
@target = nil
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def ignore?
|
|
156
|
-
@target == nil
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def target(table_name = nil)
|
|
160
|
-
@target = table_name if table_name
|
|
161
|
-
@target
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def force_downcase
|
|
165
|
-
@force_case = :downcase
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def force_upcase
|
|
169
|
-
@force_case = :upcase
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def target_model
|
|
173
|
-
DataGateway.model_for(@target)
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
# DSL syntax sugar for declare column mappers
|
|
177
|
-
def columns(column_map)
|
|
178
|
-
column_map.each_pair do |key, value|
|
|
179
|
-
case value
|
|
180
|
-
when Symbol, String: column_map[key] = write_to(value.to_sym)
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
@column_map.merge! column_map
|
|
184
|
-
|
|
185
|
-
@column_map.each_pair do |key, value|
|
|
186
|
-
defaults = column_mapper_defaults(key)
|
|
187
|
-
@column_map[key].options.replace(defaults.merge!(@column_map[key].options))
|
|
188
|
-
#puts "map for #{key} => #{@column_map[key].options.inspect}"
|
|
189
|
-
end
|
|
190
|
-
@column_map
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
def none
|
|
194
|
-
create_column_mapper({:method => :none})
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def write_to(column)
|
|
198
|
-
create_column_mapper({:method => :write_to, :write_to => column})
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
def lookup(options)
|
|
202
|
-
options[:method] = :lookup
|
|
203
|
-
create_column_mapper(options)
|
|
204
|
-
end
|
|
205
52
|
|
|
206
|
-
def identity_by(*cols)
|
|
207
|
-
@identity = cols
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# utilities
|
|
211
|
-
def column_mapper_for(column_name)
|
|
212
|
-
@column_map[column_name] ||= create_column_mapper(column_mapper_defaults(column_name))
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def column_mapper_defaults(column_name)
|
|
216
|
-
column_name = column_name.to_s.send(@force_case).to_sym if @force_case
|
|
217
|
-
case column_name.to_s
|
|
218
|
-
when /(.*)_id$/i: { :method => :lookup,
|
|
219
|
-
:write_to => column_name,
|
|
220
|
-
:table => $1.downcase.camelize.to_sym,
|
|
221
|
-
:key => @job.get_mapper($1.downcase.camelize.to_sym).identity,
|
|
222
|
-
:value => :id
|
|
223
|
-
}
|
|
224
|
-
else { :method => :write_to,
|
|
225
|
-
:write_to => column_name
|
|
226
|
-
}
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def update_all(records)
|
|
232
|
-
DataGateway.logger.debug "importing #{records.size} recods into table #{source}"
|
|
233
|
-
klass = target_model
|
|
234
|
-
DataGateway.logger.debug "target class #{klass} (PK: #{klass.primary_key})"
|
|
235
|
-
records.each { |rec|
|
|
236
|
-
rec = map(rec)
|
|
237
|
-
update_rec(rec) unless current_fixups(rec)
|
|
238
|
-
}
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
def clear_fixups
|
|
242
|
-
@fixups = {}
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def register_fixup(value, col_mapper)
|
|
246
|
-
@ar_fixups << [value, col_mapper]
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
def current_fixups(rec)
|
|
250
|
-
DataGateway.logger.debug "current fixups for: #{rec.inspect}"
|
|
251
|
-
DataGateway.logger.debug @ar_fixups.inspect
|
|
252
|
-
return false if @ar_fixups.empty?
|
|
253
|
-
@fixups[rec] ||= []
|
|
254
|
-
@fixups[rec].concat @ar_fixups
|
|
255
|
-
@ar_fixups = []
|
|
256
|
-
true
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def solve_fixups
|
|
260
|
-
DataGateway.logger.debug "start solve_fixups #{@fixups.size}"
|
|
261
|
-
@fixups.each_pair { |record, data|
|
|
262
|
-
data.each{|item|
|
|
263
|
-
value = item[0]
|
|
264
|
-
col_mapper = item[1]
|
|
265
|
-
col_mapper.solve_fixup(record, value)
|
|
266
|
-
}
|
|
267
|
-
update_rec(record)
|
|
268
|
-
}
|
|
269
|
-
DataGateway.logger.debug "end solve_fixups"
|
|
270
|
-
ensure
|
|
271
|
-
clear_fixups
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
def update_rec(rec)
|
|
275
|
-
DataGateway.logger.debug "update rec class #{target_model} '->' #{rec.inspect}"
|
|
276
|
-
conditions = identity.map{|key| key.to_s}
|
|
277
|
-
values = conditions.map{|key| rec.delete(key.to_sym)}
|
|
278
|
-
finder = 'find_or_create_by_' + conditions.join('_')
|
|
279
|
-
DataGateway.logger.debug "finder: #{finder}(#{values.join(',')})"
|
|
280
|
-
|
|
281
|
-
ar = target_model.send(finder, *values)
|
|
282
|
-
DataGateway.logger.debug "get: #{ar.inspect}"
|
|
283
|
-
DataGateway.logger.debug "upd atrt: #{rec.inspect}"
|
|
284
|
-
ar.update_attributes(rec)
|
|
285
|
-
return ar[:id]
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
def map(ar)
|
|
289
|
-
new_ar = {}
|
|
290
|
-
ar.each_pair do |key, value|
|
|
291
|
-
column_mapper_for(key).apply_to(new_ar, value)
|
|
292
|
-
end
|
|
293
|
-
new_ar
|
|
294
|
-
end
|
|
295
|
-
private
|
|
296
|
-
def create_column_mapper( options)
|
|
297
|
-
ColumnMapper.new(self, options)
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
class Job
|
|
302
|
-
attr_accessor :format_id
|
|
303
|
-
attr :transfer
|
|
304
|
-
attr :name
|
|
305
|
-
|
|
306
|
-
def initialize(name, &block)
|
|
307
|
-
@name = name
|
|
308
|
-
@use_resources = DataGateway.use_resources
|
|
309
|
-
@encoder = NullEncoder.new
|
|
310
|
-
@transfer = nil
|
|
311
|
-
instance_eval(&block) if block_given?
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
def transfer_for(options)
|
|
315
|
-
options.merge! :logger => DataGateway.logger
|
|
316
|
-
@transfer = SSHTransfer.new(options)
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def run
|
|
320
|
-
AppConfig.logger.info "running job #{name}"
|
|
321
|
-
do_run
|
|
322
|
-
AppConfig.logger.info "job #{name} finished"
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
private
|
|
326
|
-
# only for debug purpouse
|
|
327
|
-
def use_resources(bool)
|
|
328
|
-
@use_resources = bool
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
def encode(options)
|
|
332
|
-
@encoder = Encoder.new(options)
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
def pack(data)
|
|
336
|
-
DataGateway.conduit_for(self.format_id).pack(data)
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
def unpack(data)
|
|
340
|
-
DataGateway.conduit_for(format_id).unpack(data)
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
def dbchange_point
|
|
344
|
-
@dbchange_point ||= DBChangePoint.class_for(ActiveRecord::Base.connection).new
|
|
345
|
-
end
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
class Import < Job
|
|
349
|
-
def initialize(name, &block)
|
|
350
|
-
@mappers = {} #import mappers
|
|
351
|
-
super
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
def do_run
|
|
355
|
-
transfer.download if transfer and transfer.download_from
|
|
356
|
-
|
|
357
|
-
Dir.glob(File.join(DataGateway::inbox, '*.zip')).sort.each do |filename|
|
|
358
|
-
DataGateway.logger.info "Importing #{filename}"
|
|
359
|
-
import_file(filename)
|
|
360
|
-
FileUtils.mv(filename, DataGateway::donebox)
|
|
361
|
-
DataGateway.logger.info "Import done for #{filename}"
|
|
362
|
-
end
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
def get_mapper(table)
|
|
366
|
-
@mappers[table] ||= TableMapper.new(self, table)
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
public # DSL
|
|
370
|
-
|
|
371
|
-
def download_from(options)
|
|
372
|
-
options.merge! 'local_files' => DataGateway.inbox
|
|
373
|
-
transfer_for(options)
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
def importing(table, &block)
|
|
377
|
-
get_mapper(table).instance_eval(&block) if block_given?
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
private
|
|
381
|
-
|
|
382
|
-
def import_file(file_name)
|
|
383
|
-
self.format_id = file_name
|
|
384
|
-
clear_fixups
|
|
385
|
-
begin
|
|
386
|
-
Zip::ZipInputStream::open(file_name) { |io|
|
|
387
|
-
while (entry = io.get_next_entry)
|
|
388
|
-
content = io.read
|
|
389
|
-
fname = entry.name
|
|
390
|
-
if fname =~ /^attach\//
|
|
391
|
-
fname = fname.gsub(/^attach\//, '')
|
|
392
|
-
import_attach(fname, content)
|
|
393
|
-
else
|
|
394
|
-
class_name = File.basename(fname, '.*').downcase.camelize.to_sym
|
|
395
|
-
import_class(class_name, content)
|
|
396
|
-
end
|
|
397
|
-
end
|
|
398
|
-
}
|
|
399
|
-
ensure
|
|
400
|
-
solve_fixups
|
|
401
|
-
end
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
def clear_fixups
|
|
405
|
-
@mappers.each_value {|mapper|
|
|
406
|
-
mapper.clear_fixups
|
|
407
|
-
}
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
def solve_fixups
|
|
411
|
-
@mappers.each_value {|mapper|
|
|
412
|
-
mapper.solve_fixups
|
|
413
|
-
}
|
|
414
|
-
end
|
|
415
|
-
|
|
416
|
-
def import_class(class_name, data)
|
|
417
|
-
DataGateway.logger.info "Importing data for #{class_name}"
|
|
418
|
-
mapper = get_mapper(class_name)
|
|
419
|
-
if mapper.ignore?
|
|
420
|
-
DataGateway.logger.info "Ignored"
|
|
421
|
-
return
|
|
422
|
-
end
|
|
423
|
-
mapper.update_all unpack(data)
|
|
424
|
-
#p dbchange_point.capture_for(klass)
|
|
425
|
-
DataGateway.logger.info "done for #{class_name}"
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
def import_attach(fname, content)
|
|
429
|
-
return unless @use_resources
|
|
430
|
-
DataGateway.logger.info "importing attach #{fname}"
|
|
431
|
-
target_file = File.expand_path(fname, DataGateway.resource_path)
|
|
432
|
-
FileUtils.mkdir_p(File.dirname(target_file))
|
|
433
|
-
File.open(target_file, "wb") {|f| f.write content}
|
|
434
|
-
end
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
class Export < Job
|
|
438
|
-
def initialize(name, &block)
|
|
439
|
-
@exports = {}
|
|
440
|
-
@exports_order = []
|
|
441
|
-
export_to :csv #default format
|
|
442
|
-
super
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
def each
|
|
446
|
-
tables = @exports_order
|
|
447
|
-
tables.each { |cname|
|
|
448
|
-
yield cname, export_class(cname)
|
|
449
|
-
}
|
|
450
|
-
end
|
|
451
|
-
|
|
452
|
-
def export_folder
|
|
453
|
-
@export_folder ||= create_folder
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
def close_export_folder
|
|
457
|
-
@export_folder.close if @export_folder
|
|
458
|
-
end
|
|
459
|
-
|
|
460
|
-
def do_run
|
|
461
|
-
begin
|
|
462
|
-
self.each { |cname, records|
|
|
463
|
-
file_name = "#{cname}.#{self.format_id}"
|
|
464
|
-
DataGateway.logger.debug "Exporting archive #{file_name}"
|
|
465
|
-
#records.each { |rec|
|
|
466
|
-
# rec.each {|key, value|
|
|
467
|
-
# rec[key] = @encoder.pack(rec[key]) unless (key =~ /^img/i)
|
|
468
|
-
# }
|
|
469
|
-
#}
|
|
470
|
-
write_file(file_name, records)
|
|
471
|
-
}
|
|
472
|
-
ensure
|
|
473
|
-
close_export_folder
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
transfer.upload if transfer and transfer.upload_to
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
private # DSL
|
|
480
|
-
def upload_to(options)
|
|
481
|
-
options.merge! 'local_files' => File.join(DataGateway.outbox, "*.zip")
|
|
482
|
-
transfer_for(options)
|
|
483
|
-
end
|
|
484
|
-
|
|
485
|
-
def exporting(table_name, options = {})
|
|
486
|
-
@exports_order << table_name
|
|
487
|
-
@exports[table_name] = options
|
|
488
|
-
end
|
|
489
|
-
|
|
490
|
-
def export_to(format)
|
|
491
|
-
self.format_id = format
|
|
492
|
-
end
|
|
493
|
-
private
|
|
494
|
-
def create_folder(outbox = DataGateway::outbox)
|
|
495
|
-
FileUtils.mkpath(outbox)
|
|
496
|
-
stamp = Time.now.strftime("%Y%m%d%H%M%S")
|
|
497
|
-
folder_name = File.join(outbox, "#{stamp}.#{self.format_id}")
|
|
498
|
-
#(APP_ENV == 'development') ? FolderWriter.new(folder_name) :
|
|
499
|
-
ZipFolderWriter.new(folder_name)
|
|
500
|
-
end
|
|
501
|
-
|
|
502
|
-
def export_class(cname)
|
|
503
|
-
result = []
|
|
504
|
-
bm = Benchmark.measure {
|
|
505
|
-
klass = DataGateway.model_for(cname.to_s.downcase.camelize)
|
|
506
|
-
DataGateway.logger.info "Exporting #{klass} (#{self.format_id})"
|
|
507
|
-
records = klass.find(:all, @exports[cname])
|
|
508
|
-
records.each { |r| export_attachments(r) } if @use_resources
|
|
509
|
-
result = pack(records) unless records.empty?
|
|
510
|
-
}
|
|
511
|
-
DataGateway.logger.info "data exported in #{bm}"
|
|
512
|
-
result
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
def export_attachments(record)
|
|
516
|
-
record.attributes.keys.select { |key| key =~ /^img/i }.each { |key|
|
|
517
|
-
file = record.attributes[key]
|
|
518
|
-
#TODO Si el path del attach es absoluto, quiza debemos tener cuidado al descomprimir el zip
|
|
519
|
-
next if file.blank?
|
|
520
|
-
path = File.expand_path(file, DataGateway.resource_path)
|
|
521
|
-
DataGateway.logger.info "exporting attach #{path}"
|
|
522
|
-
#TODO Si el fichero ya se exporto solo en este vuelta, no repetir!
|
|
523
|
-
next unless File.exist?(path)
|
|
524
|
-
attach_data = File.open(path, 'rb') { |f| f.read }
|
|
525
|
-
write_file(File.join('attach', file), attach_data, 'b')
|
|
526
|
-
}
|
|
527
|
-
end
|
|
528
|
-
|
|
529
|
-
def write_file(file_name, data, options = '')
|
|
530
|
-
op = StringIO.new("", "w")
|
|
531
|
-
op.puts data
|
|
532
|
-
if (options == 'b')
|
|
533
|
-
export_folder.open(file_name, "w" + options){|f| f.puts op.string}
|
|
534
|
-
else
|
|
535
|
-
export_folder.open(file_name, "w" + options){|f| f.puts @encoder.pack(op.string)}
|
|
536
|
-
end
|
|
537
|
-
end
|
|
538
|
-
end
|
|
539
53
|
public
|
|
540
|
-
|
|
54
|
+
|
|
55
|
+
# DataGateway DSL
|
|
541
56
|
def resource_path(path= nil)
|
|
542
57
|
if path
|
|
543
58
|
@@resource_path = File.expand_path(path)
|
|
@@ -545,9 +60,13 @@ module DataGateway
|
|
|
545
60
|
@@resource_path || ''
|
|
546
61
|
end
|
|
547
62
|
end
|
|
548
|
-
|
|
63
|
+
|
|
549
64
|
module_function(:resource_path)
|
|
550
|
-
|
|
65
|
+
|
|
66
|
+
def last_time(key)
|
|
67
|
+
DataGateway.last_time[key.to_s].utc.to_s(:db)
|
|
68
|
+
end
|
|
69
|
+
|
|
551
70
|
def db_connection(conn)
|
|
552
71
|
::ActiveRecord::Base.establish_connection conn
|
|
553
72
|
if conn['nax_empresa']
|
|
@@ -557,13 +76,11 @@ module DataGateway
|
|
|
557
76
|
|
|
558
77
|
def nax_connection(connection)
|
|
559
78
|
NAX::ActiveRecord::Base.establish_connection connection
|
|
560
|
-
end
|
|
79
|
+
end
|
|
561
80
|
|
|
562
81
|
def import(name, &block)
|
|
563
82
|
name = name.to_sym
|
|
564
|
-
self.class.class_eval {
|
|
565
|
-
attr_reader name
|
|
566
|
-
}
|
|
83
|
+
self.class.class_eval {attr_reader name }
|
|
567
84
|
new_job = Import.new(name, &block)
|
|
568
85
|
instance_variable_set('@' + name.to_s, new_job)
|
|
569
86
|
return new_job
|
|
@@ -571,25 +88,21 @@ module DataGateway
|
|
|
571
88
|
|
|
572
89
|
def export(name, &block)
|
|
573
90
|
name = name.to_sym
|
|
574
|
-
self.class.class_eval {
|
|
575
|
-
attr_reader name
|
|
576
|
-
}
|
|
91
|
+
self.class.class_eval { attr_reader name }
|
|
577
92
|
new_job = Export.new(name, &block)
|
|
578
93
|
instance_variable_set('@' + name.to_s, new_job)
|
|
579
94
|
return new_job
|
|
580
95
|
end
|
|
581
|
-
|
|
582
|
-
def upload_to(options)
|
|
583
|
-
Export.new('upload') {
|
|
584
|
-
upload_to options
|
|
585
|
-
}.run
|
|
586
96
|
|
|
97
|
+
def upload_to(options)
|
|
98
|
+
options.merge! :logger => DataGateway.logger
|
|
99
|
+
options.merge! 'local_files' => File.join(DataGateway.outbox, "*.zip")
|
|
100
|
+
SSHTransfer.new(options).upload
|
|
587
101
|
end
|
|
588
102
|
|
|
589
103
|
def download_from(options)
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
104
|
+
options.merge! :logger => DataGateway.logger
|
|
105
|
+
options.merge! 'local_files' => DataGateway.inbox
|
|
106
|
+
SSHTransfer.new(options).download
|
|
594
107
|
end
|
|
595
108
|
end
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module DataGateway
|
|
2
|
+
|
|
3
|
+
class NullEncoder
|
|
4
|
+
def pack(data)
|
|
5
|
+
data
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def unpack(data)
|
|
9
|
+
data
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class Encoder
|
|
14
|
+
def initialize(options)
|
|
15
|
+
@pack = Iconv.new(options[:to], options[:from])
|
|
16
|
+
@unpack = Iconv.new(options[:from], options[:to])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def pack(data)
|
|
20
|
+
@pack.iconv(data)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def unpack(data)
|
|
24
|
+
@unpack.iconv(data)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
File without changes
|