sp2db 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +180 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +180 -0
- data/Rakefile +10 -0
- data/lib/generators/sp2db/config_generator.rb +13 -0
- data/lib/generators/sp2db/templates/sp2db.rb +27 -0
- data/lib/sp2db/base_table.rb +238 -0
- data/lib/sp2db/client.rb +56 -0
- data/lib/sp2db/config.rb +82 -0
- data/lib/sp2db/exception_handler.rb +26 -0
- data/lib/sp2db/import_concern.rb +84 -0
- data/lib/sp2db/import_strategy.rb +157 -0
- data/lib/sp2db/logging.rb +29 -0
- data/lib/sp2db/model_table.rb +171 -0
- data/lib/sp2db/non_model_table.rb +17 -0
- data/lib/sp2db/spreadsheet.rb +19 -0
- data/lib/sp2db/version.rb +3 -0
- data/lib/sp2db.rb +55 -0
- data/lib/tasks/sp2db.rake +12 -0
- data/sp2db.gemspec +32 -0
- metadata +153 -0
@@ -0,0 +1,238 @@
|
|
1
|
+
module Sp2db
|
2
|
+
class BaseTable
|
3
|
+
|
4
|
+
attr_accessor :name,
|
5
|
+
:sheet_name,
|
6
|
+
:worksheet,
|
7
|
+
:find_columns,
|
8
|
+
:spreadsheet_id,
|
9
|
+
:client
|
10
|
+
|
11
|
+
def initialize opts={}
|
12
|
+
|
13
|
+
if opts[:name].blank? && opts[:sheet_name].blank?
|
14
|
+
raise "Must specify at least one of name or sheet name"
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.each do |k, v|
|
18
|
+
self.send "#{k}=", v
|
19
|
+
end
|
20
|
+
|
21
|
+
self.sheet_name ||= opts[:sheet_name] = config[:sheet_name] || worksheet.try(:title)
|
22
|
+
end
|
23
|
+
|
24
|
+
def active_record?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
# Table name
|
29
|
+
def name
|
30
|
+
@name ||= sheet_name.try(:to_sym) || raise("Name cannot be nil")
|
31
|
+
end
|
32
|
+
|
33
|
+
def spreadsheet_id
|
34
|
+
@spreadsheet_id ||= config[:spreadsheet_id] || Sp2db.config.spreadsheet_id
|
35
|
+
end
|
36
|
+
|
37
|
+
def name=n
|
38
|
+
@name = n&.to_sym
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_columns
|
42
|
+
@find_columns ||= config[:find_columns] || Sp2db.config.default_find_columns
|
43
|
+
end
|
44
|
+
|
45
|
+
def required_columns
|
46
|
+
@required_columns ||= config[:required_columns] || []
|
47
|
+
end
|
48
|
+
|
49
|
+
def client
|
50
|
+
@client = Sp2db.client
|
51
|
+
end
|
52
|
+
|
53
|
+
def spreadsheet
|
54
|
+
client.spreadsheet spreadsheet_id
|
55
|
+
end
|
56
|
+
|
57
|
+
def sheet_name
|
58
|
+
@sheet_name ||= (config[:sheet_name] || name)&.to_sym
|
59
|
+
end
|
60
|
+
|
61
|
+
def worksheet
|
62
|
+
@worksheet = spreadsheet.worksheet_by_name(self.sheet_name.to_s)
|
63
|
+
end
|
64
|
+
|
65
|
+
def sp_data
|
66
|
+
retries = 2
|
67
|
+
raw_data = CSV.parse worksheet.export_as_string
|
68
|
+
data = process_data raw_data, source: :sp
|
69
|
+
data
|
70
|
+
end
|
71
|
+
|
72
|
+
def csv_data
|
73
|
+
raw_data = CSV.parse File.open(csv_file)
|
74
|
+
data = process_data raw_data, source: :csv
|
75
|
+
data
|
76
|
+
end
|
77
|
+
|
78
|
+
def header_row
|
79
|
+
# @header_row ||= config[:header_row] || 0
|
80
|
+
0
|
81
|
+
end
|
82
|
+
|
83
|
+
def csv_folder
|
84
|
+
folder = "#{Sp2db.config.export_location}/csv"
|
85
|
+
FileUtils.mkdir_p folder
|
86
|
+
folder
|
87
|
+
end
|
88
|
+
|
89
|
+
def csv_file
|
90
|
+
"#{csv_folder}/#{name}.csv"
|
91
|
+
end
|
92
|
+
|
93
|
+
def sp_to_csv opts={}
|
94
|
+
write_csv to_csv(sp_data)
|
95
|
+
end
|
96
|
+
|
97
|
+
def write_csv data
|
98
|
+
File.open csv_file, "wb" do |f|
|
99
|
+
f.write data
|
100
|
+
end
|
101
|
+
csv_file
|
102
|
+
end
|
103
|
+
|
104
|
+
# Array of hash data to csv format
|
105
|
+
def to_csv data
|
106
|
+
attributes = data.first&.keys || []
|
107
|
+
|
108
|
+
CSV.generate(headers: true) do |csv|
|
109
|
+
csv << attributes
|
110
|
+
|
111
|
+
data.each do |row|
|
112
|
+
csv << attributes.map do |att|
|
113
|
+
row[att]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Global config
|
120
|
+
def config
|
121
|
+
{}.with_indifferent_access
|
122
|
+
end
|
123
|
+
|
124
|
+
def process_data raw_data, opts={}
|
125
|
+
raw_data = data_transform raw_data, opts unless opts[:skip_data_transform]
|
126
|
+
raw_data = raw_filter raw_data, opts unless opts[:skip_data_filter]
|
127
|
+
data = call_process_data raw_data, opts
|
128
|
+
data
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
# Tranform data to standard csv format
|
133
|
+
def data_transform raw_data, opts={}
|
134
|
+
if config[:data_transform].present?
|
135
|
+
config[:data_transform].call *args, &block
|
136
|
+
else
|
137
|
+
raw_data
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
protected
|
142
|
+
# Remove header which starts with "#"
|
143
|
+
def valid_header? h
|
144
|
+
h.present? && !h.match("^#.*")
|
145
|
+
end
|
146
|
+
|
147
|
+
# Header with "!" at the beginning or ending is required
|
148
|
+
def require_header? h
|
149
|
+
h.present? && (h.match("^!.*") || h.match(".*?!$"))
|
150
|
+
end
|
151
|
+
|
152
|
+
# Convert number string to number
|
153
|
+
def standardize_cell_val v
|
154
|
+
v = ((float = Float(v)) && (float % 1.0 == 0) ? float.to_i : float) rescue v
|
155
|
+
v = v.force_encoding("UTF-8") if v.is_a?(String)
|
156
|
+
v
|
157
|
+
end
|
158
|
+
|
159
|
+
def call_process_data raw_data, opts={}
|
160
|
+
data = raw_data
|
161
|
+
if (data_proc = config[:process_data]).present?
|
162
|
+
data = data_proc.call raw_data
|
163
|
+
end
|
164
|
+
data
|
165
|
+
end
|
166
|
+
|
167
|
+
# Remove uncessary columns and invalid rows from csv format data
|
168
|
+
def raw_filter raw_data, opts={}
|
169
|
+
raw_header = raw_data[header_row].map.with_index do |h, idx|
|
170
|
+
is_valid = valid_header?(h)
|
171
|
+
{
|
172
|
+
idx: idx,
|
173
|
+
is_remove: !is_valid,
|
174
|
+
is_required: require_header?(h),
|
175
|
+
name: is_valid && h.gsub(/\s*/, '').gsub(/!/, '').downcase
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
rows = raw_data[(header_row + 1)..-1].map.with_index do |raw, rdx|
|
180
|
+
row = {}.with_indifferent_access
|
181
|
+
raw_header.each do |h|
|
182
|
+
val = raw[h[:idx]]
|
183
|
+
next if h[:is_remove]
|
184
|
+
if h[:is_required] && val.blank?
|
185
|
+
row = {}
|
186
|
+
break
|
187
|
+
end
|
188
|
+
|
189
|
+
row[h[:name]] = standardize_cell_val val
|
190
|
+
end
|
191
|
+
|
192
|
+
next if row.values.all?(&:blank?)
|
193
|
+
|
194
|
+
row[:id] = rdx + 1 if find_columns.include?(:id) && row[:id].blank?
|
195
|
+
row
|
196
|
+
end.compact
|
197
|
+
.reject(&:blank?)
|
198
|
+
rows = rows.select do |row|
|
199
|
+
if required_columns.present?
|
200
|
+
required_columns.all? {|col| row[col].present? }
|
201
|
+
else
|
202
|
+
true
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
rows
|
207
|
+
end
|
208
|
+
|
209
|
+
class << self
|
210
|
+
|
211
|
+
def all_tables
|
212
|
+
ModelTable.all_tables + NonModelTable.all_tables
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
def table_by_names *names
|
217
|
+
all_tables = self.all_tables
|
218
|
+
if names.blank?
|
219
|
+
all_tables
|
220
|
+
else
|
221
|
+
names.map do |n|
|
222
|
+
all_tables.find {|tb| tb.name == n.to_sym} || raise("Not found: #{n}")
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def sp_to_csv *table_names
|
228
|
+
table_by_names(*table_names).map(&__method__)
|
229
|
+
end
|
230
|
+
|
231
|
+
def model_table_class
|
232
|
+
ModelTable
|
233
|
+
end
|
234
|
+
|
235
|
+
delegate :sp_to_db, :csv_to_db, to: :model_table_class
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
data/lib/sp2db/client.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Sp2db
|
2
|
+
class Client
|
3
|
+
|
4
|
+
include Logging
|
5
|
+
|
6
|
+
attr_accessor :credential, :session
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def config
|
13
|
+
Sp2db.config
|
14
|
+
end
|
15
|
+
|
16
|
+
def credential
|
17
|
+
@credential ||= config.credential
|
18
|
+
end
|
19
|
+
|
20
|
+
def session
|
21
|
+
logger.debug "Init session"
|
22
|
+
unless credential = self.credential
|
23
|
+
return @session = saved_session
|
24
|
+
end
|
25
|
+
|
26
|
+
key = OpenSSL::PKey::RSA.new(credential['private_key'])
|
27
|
+
auth = Signet::OAuth2::Client.new(
|
28
|
+
token_credential_uri: credential['token_uri'],
|
29
|
+
audience: credential['token_uri'],
|
30
|
+
scope: %w(
|
31
|
+
https://www.googleapis.com/auth/drive
|
32
|
+
https://spreadsheets.google.com/feeds/
|
33
|
+
),
|
34
|
+
issuer: credential['client_email'],
|
35
|
+
signing_key: key
|
36
|
+
)
|
37
|
+
|
38
|
+
auth.fetch_access_token!
|
39
|
+
@session = GoogleDrive.login_with_oauth(auth.access_token)
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def saved_session
|
44
|
+
logger.debug "Use saved session"
|
45
|
+
GoogleDrive.saved_session Sp2db.config.personal_credential,
|
46
|
+
nil,
|
47
|
+
client_id: config.client_id,
|
48
|
+
client_secret: config.client_secret
|
49
|
+
end
|
50
|
+
|
51
|
+
def spreadsheet sid
|
52
|
+
Spreadsheet.new session.spreadsheet_by_key(sid)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/lib/sp2db/config.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
module Sp2db
|
2
|
+
class Config
|
3
|
+
|
4
|
+
attr_accessor \
|
5
|
+
:credential,
|
6
|
+
:personal_credential,
|
7
|
+
:client_id,
|
8
|
+
:client_secret,
|
9
|
+
:spreadsheet_id,
|
10
|
+
:export_location,
|
11
|
+
:default_file_extention,
|
12
|
+
:import_strategy,
|
13
|
+
:download_before_import,
|
14
|
+
:default_extensions,
|
15
|
+
:exception_handler,
|
16
|
+
:non_model_tables,
|
17
|
+
:default_find_columns
|
18
|
+
|
19
|
+
|
20
|
+
DEFAULT = {
|
21
|
+
personal_credential: "credentials/google_credentials.json",
|
22
|
+
import_strategy: :truncate_all,
|
23
|
+
export_location: "db/spreadsheets",
|
24
|
+
default_file_extention: :csv,
|
25
|
+
exception_handler: OpenStruct.new({
|
26
|
+
row_import_error: :raise,
|
27
|
+
table_import_error: :raise,
|
28
|
+
}),
|
29
|
+
non_model_tables: {}.with_indifferent_access,
|
30
|
+
download_before_import: false,
|
31
|
+
default_extensions: :csv,
|
32
|
+
default_find_columns: [:id],
|
33
|
+
}
|
34
|
+
|
35
|
+
SUPPORTED_EXTENSIONS = [:csv]
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
set_default
|
39
|
+
end
|
40
|
+
|
41
|
+
def import_strategy=s
|
42
|
+
s = s.to_sym
|
43
|
+
ImportStrategy.valid! s
|
44
|
+
@import_strategy = s
|
45
|
+
end
|
46
|
+
|
47
|
+
def export_folder
|
48
|
+
FileUtils.mkdir_p export_location
|
49
|
+
export_location
|
50
|
+
end
|
51
|
+
|
52
|
+
# File name or json string or hash
|
53
|
+
def credential=cr
|
54
|
+
if File.exist?(cr) && File.file?(cr)
|
55
|
+
cr = File.read cr
|
56
|
+
end
|
57
|
+
|
58
|
+
@credential = case cr
|
59
|
+
when Hash, ActiveSupport::HashWithIndifferentAccess
|
60
|
+
cr
|
61
|
+
when String
|
62
|
+
JSON.parse cr
|
63
|
+
else
|
64
|
+
raise "Invalid data type"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def default_find_columns= cols
|
69
|
+
@default_find_columns = cols.map &:to_sym
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
Google::Apis.logger.level
|
75
|
+
|
76
|
+
def set_default
|
77
|
+
DEFAULT.each do |k, v|
|
78
|
+
self.send("#{k}=", v)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Sp2db
|
2
|
+
module ExceptionHandler
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def row_import_error e
|
6
|
+
handle __method__, e
|
7
|
+
end
|
8
|
+
|
9
|
+
def table_import_error e
|
10
|
+
handle __method__, e
|
11
|
+
end
|
12
|
+
|
13
|
+
def handle action, e
|
14
|
+
case action = Sp2db.config.exception_handler[action]
|
15
|
+
when :skip
|
16
|
+
true
|
17
|
+
when :raise
|
18
|
+
raise e
|
19
|
+
when Proc
|
20
|
+
action.call(e)
|
21
|
+
else
|
22
|
+
raise e
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Sp2db
|
2
|
+
module ImportConcern
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
Sp2db::ModelTable.add_models self
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
def sp2db_options *args, &block
|
12
|
+
if args.first.is_a?(Hash)
|
13
|
+
args.first.each do |k, v|
|
14
|
+
send "sp2db_#{k}", v
|
15
|
+
end
|
16
|
+
else
|
17
|
+
meth = args.shift
|
18
|
+
send "sp2db_#{meth}", *args, &block
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def sp2db_config
|
23
|
+
@sp2db_config ||= {}.with_indifferent_access
|
24
|
+
end
|
25
|
+
|
26
|
+
[:find_columns, :required_columns].each do |opt|
|
27
|
+
define_method "sp2db_#{opt}" do |*cols|
|
28
|
+
cols = cols&.flatten
|
29
|
+
sp2db_config[opt] = cols.map(&:to_sym) if cols.present?
|
30
|
+
sp2db_config[opt]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def sp2db_priority pr=nil
|
35
|
+
sp2db_config[:priority] = pr if pr.present?
|
36
|
+
sp2db_config[:priority]
|
37
|
+
end
|
38
|
+
|
39
|
+
def sp2db_import_strategy s=nil
|
40
|
+
if s.present?
|
41
|
+
s = s.to_sym
|
42
|
+
ImportStrategy.valid! s
|
43
|
+
sp2db_config[:import_strategy] = s
|
44
|
+
end
|
45
|
+
|
46
|
+
sp2db_config[:import_strategy]
|
47
|
+
end
|
48
|
+
|
49
|
+
def sp2db_sheet_name s=nil
|
50
|
+
sp2db_config[:sheet_name] = s.to_sym if s.present?
|
51
|
+
sp2db_config[:sheet_name]
|
52
|
+
end
|
53
|
+
|
54
|
+
def sp2db_header_row s=nil
|
55
|
+
sp2db_config[:header_row] = s if s.present?
|
56
|
+
sp2db_config[:header_row]
|
57
|
+
end
|
58
|
+
|
59
|
+
def sp2db_spreadsheet_id s=nil
|
60
|
+
sp2db_config[:spreadsheet_id] = s if s.present?
|
61
|
+
sp2db_config[:spreadsheet_id]
|
62
|
+
end
|
63
|
+
|
64
|
+
[
|
65
|
+
:data_transform,
|
66
|
+
:process_data,
|
67
|
+
:before_import_row,
|
68
|
+
:after_import_row,
|
69
|
+
:after_import_table,
|
70
|
+
].each do |option|
|
71
|
+
define_method "sp2db_#{option}" do |method=nil, &block|
|
72
|
+
sp2db_config[option] = if method.present?
|
73
|
+
method.is_a?(Proc) ? method : method.to_sym
|
74
|
+
elsif block.present?
|
75
|
+
block
|
76
|
+
else
|
77
|
+
sp2db_config[option]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Sp2db
|
2
|
+
module ImportStrategy
|
3
|
+
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# Add strategy
|
7
|
+
def add label, strategy=nil, &block
|
8
|
+
strategy ||= Class.new(Base)
|
9
|
+
strategy.class_eval(&block) if block_given?
|
10
|
+
strategies[label.to_sym] = strategy
|
11
|
+
end
|
12
|
+
|
13
|
+
# @!strategies [ro] strategies
|
14
|
+
def strategies
|
15
|
+
@strategies ||= {}.with_indifferent_access
|
16
|
+
end
|
17
|
+
|
18
|
+
def strategy_by_name name
|
19
|
+
strategies[name.to_s] || raise("Invalid import strategy: #{name}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def labels
|
23
|
+
strategies.keys.map(&:to_sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid! s
|
27
|
+
raise "Unsuported strategies" unless labels.include?(s.to_sym)
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
class Base
|
32
|
+
|
33
|
+
include Logging
|
34
|
+
|
35
|
+
attr_accessor :table, :rows, :result
|
36
|
+
|
37
|
+
delegate :model,
|
38
|
+
:find_columns,
|
39
|
+
to: :table
|
40
|
+
|
41
|
+
def initialize table, rows
|
42
|
+
self.table = table
|
43
|
+
self.rows = rows
|
44
|
+
end
|
45
|
+
|
46
|
+
def result
|
47
|
+
@result ||= {
|
48
|
+
records: [],
|
49
|
+
errors: [],
|
50
|
+
}.with_indifferent_access
|
51
|
+
end
|
52
|
+
|
53
|
+
def errors
|
54
|
+
result[:errors]
|
55
|
+
end
|
56
|
+
|
57
|
+
def records
|
58
|
+
result[:records]
|
59
|
+
end
|
60
|
+
|
61
|
+
def before_import
|
62
|
+
logger.debug "Run before import table: #{self.table.name}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_db_row row
|
66
|
+
if find_columns.present?
|
67
|
+
cond = {}
|
68
|
+
find_columns.each do |col|
|
69
|
+
cond[col] = row[col]
|
70
|
+
end
|
71
|
+
model.find_by cond
|
72
|
+
else
|
73
|
+
nil # nil to skip
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def set_record_value record, row
|
78
|
+
row.each do |k, v|
|
79
|
+
record.send("#{k}=", v)
|
80
|
+
end
|
81
|
+
record
|
82
|
+
end
|
83
|
+
|
84
|
+
def import_row row
|
85
|
+
record = find_db_row(row) || model.new(row)
|
86
|
+
record = set_record_value record, row
|
87
|
+
return unless record.present?
|
88
|
+
record.save! if record.new_record? || record.changed?
|
89
|
+
record
|
90
|
+
end
|
91
|
+
|
92
|
+
def after_import
|
93
|
+
logger.debug "Run after import table: #{self.table.name}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def import
|
97
|
+
logger.debug "Start import table: #{self.table.name}"
|
98
|
+
ActiveRecord::Base.transaction(requires_new: true) do
|
99
|
+
before_import
|
100
|
+
rows.each do |row|
|
101
|
+
row = row.clone
|
102
|
+
begin
|
103
|
+
table.before_import_row row
|
104
|
+
record = import_row row
|
105
|
+
records << record
|
106
|
+
table.after_import_row record
|
107
|
+
rescue ActiveRecord::ActiveRecordError => e
|
108
|
+
logger.error e.try(:message)
|
109
|
+
errors << {
|
110
|
+
message: e.try(:message),
|
111
|
+
exception: e,
|
112
|
+
row: row,
|
113
|
+
table: table.name,
|
114
|
+
}
|
115
|
+
next unless ExceptionHandler.row_import_error e
|
116
|
+
end
|
117
|
+
end
|
118
|
+
after_import
|
119
|
+
table.after_import_table result
|
120
|
+
logger.debug "Import finished: #{self.table.name}"
|
121
|
+
return result
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
ImportStrategy.add :truncate_all do
|
130
|
+
def before_import
|
131
|
+
logger.info "Truncte all data: #{self.table.name}"
|
132
|
+
model.all.delete_all
|
133
|
+
end
|
134
|
+
|
135
|
+
def find_db_row row
|
136
|
+
nil
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
ImportStrategy.add :overwrite do
|
141
|
+
end
|
142
|
+
|
143
|
+
ImportStrategy.add :fill_empty do
|
144
|
+
def set_record_value record, row
|
145
|
+
row.each do |k, v|
|
146
|
+
record.send("#{k}=", v) if record.send(k).blank?
|
147
|
+
end
|
148
|
+
record
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
ImportStrategy.add :skip do
|
153
|
+
def set_record_value record, row
|
154
|
+
record
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Sp2db
|
2
|
+
module Logging
|
3
|
+
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# @!attribute [rw] logger
|
7
|
+
# @return [Logger] The logger.
|
8
|
+
def logger
|
9
|
+
@logger ||= get_logger
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Logger]
|
13
|
+
def logger= l
|
14
|
+
@logger = l
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Logger]
|
18
|
+
def get_logger
|
19
|
+
if defined?(::Rails) && ::Rails.respond_to?(:logger) && !::Rails.logger.nil?
|
20
|
+
::Rails.logger
|
21
|
+
else
|
22
|
+
logger = Logger.new($stdout)
|
23
|
+
logger.level = Logger::WARN
|
24
|
+
logger
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|