sp2db 0.0.3
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.
- 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
|