takenoko 0.0.4 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6c6846bb822d84f908f35ea7e6737e87b20f5c17
4
- data.tar.gz: 9c1533aaa9e1d993f7beb2f5ae8265f59a4fb697
3
+ metadata.gz: afd7651c59b5026c0129a6844a0d4fc84a9e581c
4
+ data.tar.gz: dfe614608f5718772f113611324231918c4b1bf3
5
5
  SHA512:
6
- metadata.gz: 9d2627e910529f9c04a3b57477e46e4e738115a3cf8224f7c7e92151d471ac84c790265fa90a3c1e7688ea7e705fcb03ccbfd1885287d332b174c94a3be0cf6b
7
- data.tar.gz: a700a1f350e7214fb1a1cb4d688d87ac0494531c7f50f7ee60ccfd4b77cc23cc3e4209bca8f3a8ba2f0a1186c326493c54699220d5e2d35da4d556b6985dad32
6
+ metadata.gz: da1b26dc90fc9409d533d03d70c41ec50824a575021ed9d7087fff3ed9f79eb37f68a6179472dc14ea5b2364c5e49af9926097402d9b0dede187593adf5b1572
7
+ data.tar.gz: 2b69692d6580d799e0e0d2f4571162e86cb064e5389db08936cc6bec88adad525e201819267ed98e06f0f37a67afe61c8679140a79f98c6cf32f8ef59d9b5fd2
@@ -1,4 +1,38 @@
1
1
  Takenoko.config do |conf|
2
+
3
+ # Path to service account cridential file when using account service permission
4
+ # If not set, Takenoko will use persional cridential auto matically and as you for permission at the first time via command line
2
5
  # conf.google_cridential_file = "path to google credential file.json"
6
+
7
+ # Path to mapping file, if not be set, Takenoko will fetch all worksheet and export base on worksheet
3
8
  # conf.mapping_file = "path to mapping file.yml"
9
+
10
+
11
+ # GLOBAL CONFIG, you can overwrite under config for each table in mapping_file.yml
12
+ # Global Spreadsheet id, optain via url of your spreadsheet
13
+ # conf.sheet_id = "SPREADSHEET_ID" ###IMPORTANT###, Must set this value here or in mapping file
14
+
15
+ # Export file format, default :csv, support: csv,yaml,json
16
+ # conf.file_extension = :csv
17
+
18
+ # Truncate all data before saving, default: false
19
+ # conf.truncate_all_data = false
20
+
21
+ # Export file location, default: db/spreadsheet
22
+ # conf.export_file_location = "db/spreadsheet"
23
+
24
+ # Allow overwrite duplicated row, default: true
25
+ # conf.allow_overwrite = true
26
+
27
+ # Enable post processing after get row from spreadsheet, default false
28
+ # Define three more method on your post process class to handle it
29
+ # spreadsheet_row_valid? : skip invalid rows, return bool (Optional)
30
+ # postprocess_spreadsheet_row : modify row, return processed row(Optional)
31
+ # postprocess_spreadsheet_table : modify whole talbe, return processed table(Optional)
32
+
33
+ # conf.enable_postprocess = false
34
+
35
+ # Class for post processing, nil for Class = table class name
36
+ # conf.postprocess_class = nil
37
+
4
38
  end
@@ -1,14 +1,29 @@
1
1
  module Takenoko
2
2
  class GoogleClient
3
- def initialize(cridential_file)
4
- @cridential = JSON.parse(File.read(cridential_file)).with_indifferent_access
3
+ def initialize(cridential_file=nil)
4
+ if cridential_file && ::File.exist?(cridential_file)
5
+ @cridential = JSON.parse(File.read(cridential_file)).with_indifferent_access
6
+ end
5
7
  end
6
8
 
7
9
  def get_table(table_name)
8
10
  table = Takenoko.table_config(table_name)
9
11
  raise "GoogleDrive: Sheet not found" unless sheet = session.spreadsheet_by_key(table['sheet_id'])
10
- raise "GoogleDrive: Worksheet not found: worksheet_id #{table['worksheet_id']}" unless worksheet = sheet.worksheet_by_gid(table['worksheet_id'])
11
- header = worksheet.header.select {|h| table[:columns_mapping].keys.include?(h)}
12
+
13
+ if table[:worksheet_id].present?
14
+ worksheet = sheet.worksheet_by_gid(table[:worksheet_id])
15
+ table[:worksheet] = worksheet.title
16
+ elsif table[:worksheet].present?
17
+ raise "Worksheet #{table[:worksheet]} not found" unless worksheet = sheet.worksheet_by_title(table[:worksheet])
18
+ table[:worksheet_id] = worksheet.gid.to_i
19
+ elsif
20
+ raise "You must specify worksheet or worksheet_id if mapping_file.yml"
21
+ end
22
+
23
+ update_table_config(table,worksheet.header)
24
+ postprocess_class = Object.const_get(table[:postprocess_class]) if table[:enable_postprocess]
25
+
26
+ Rails.logger.info "Getting table #{table_name}"
12
27
  rows = worksheet.populated_rows.map do |r|
13
28
  hash = HashWithIndifferentAccess.new
14
29
  table['columns_mapping'].each do |key,val|
@@ -23,27 +38,82 @@ module Takenoko
23
38
  end
24
39
  end
25
40
  hash
41
+ end.reject do |row|
42
+ begin
43
+ table[:enable_postprocess] && !postprocess_class.public_send("spreadsheet_row_valid?",row)
44
+ rescue NoMethodError => e
45
+ Rails.logger.warn e.message
46
+ false
47
+ end
48
+ end.map do |row|
49
+ begin
50
+ table[:enable_postprocess] ? postprocess_class.public_send("postprocess_spreadsheet_row",row) : row
51
+ rescue NoMethodError => e
52
+ Rails.logger.warn e.message
53
+ row
54
+ end
26
55
  end
56
+
27
57
  table[:rows] = rows
58
+ if table[:enable_postprocess]
59
+ begin
60
+ table = postprocess_class.public_send("postprocess_spreadsheet_table",table)
61
+ rescue NoMethodError => e
62
+ Rails.logger.warn e.message
63
+ end
64
+ end
28
65
  return table
29
66
  end
30
67
 
31
68
  def session
32
- key = OpenSSL::PKey::RSA.new(@cridential['private_key'])
33
- auth = Signet::OAuth2::Client.new(
34
- token_credential_uri: @cridential['token_uri'],
35
- audience: @cridential['token_uri'],
36
- scope: %w(
37
- https://www.googleapis.com/auth/drive
38
- https://spreadsheets.google.com/feeds/
39
- ),
40
- issuer: @cridential['client_email'],
41
- signing_key: key
42
- )
43
-
44
- auth.fetch_access_token!
45
- session = GoogleDrive.login_with_oauth(auth.access_token)
46
- return session
69
+ Rails.logger.info "Init session"
70
+ unless @cridential
71
+ return GoogleDrive.saved_session(Takenoko.personal_cridential_file)
72
+ end
73
+
74
+ key = OpenSSL::PKey::RSA.new(@cridential['private_key'])
75
+ auth = Signet::OAuth2::Client.new(
76
+ token_credential_uri: @cridential['token_uri'],
77
+ audience: @cridential['token_uri'],
78
+ scope: %w(
79
+ https://www.googleapis.com/auth/drive
80
+ https://spreadsheets.google.com/feeds/
81
+ ),
82
+ issuer: @cridential['client_email'],
83
+ signing_key: key
84
+ )
85
+
86
+ auth.fetch_access_token!
87
+ session = GoogleDrive.login_with_oauth(auth.access_token)
88
+ return session
89
+ end
90
+
91
+ def spreadsheet(sheet_id=Takenoko.sheet_id)
92
+ session.spreadsheet_by_key(sheet_id)
93
+ end
94
+
95
+ private
96
+ def update_table_config(table,ws_header)
97
+ columns_mapping = HashWithIndifferentAccess.new
98
+ ws_header.select do |col|
99
+ col.present? && ! col.match(/\s*#.*/)
100
+ end.each do |col|
101
+ if(table[:columns_mapping].present?)
102
+ columns_mapping[col] = col && next unless table[:columns_mapping][col].present?
103
+ next if table[:columns_mapping][col] == false
104
+ columns_mapping[col] = table[:columns_mapping][col]
105
+ else
106
+ columns_mapping[col] = col
107
+ end
108
+ end
109
+
110
+ table[:columns_mapping] = columns_mapping
111
+ unless table[:columns_mapping].key?(table[:find_column])
112
+ table[:columns_mapping][table[:find_column]] = table[:find_column]
113
+ end
114
+
115
+ table[:header] = table[:columns_mapping].keys
116
+ return table
47
117
  end
48
118
  end
49
119
  end
@@ -1,3 +1,3 @@
1
1
  module Takenoko
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.2"
3
3
  end
data/lib/takenoko.rb CHANGED
@@ -7,6 +7,9 @@ module Takenoko
7
7
  mattr_accessor :google_cridential_file
8
8
  @@google_cridential_file = nil
9
9
 
10
+ mattr_accessor :personal_cridential_file
11
+ @@personal_cridential_file = "config/my_cridential.json"
12
+
10
13
  mattr_accessor :mapping_file
11
14
  @@mapping_file = false
12
15
 
@@ -26,6 +29,15 @@ module Takenoko
26
29
  mattr_accessor :allow_overwrite
27
30
  @@allow_overwrite = true
28
31
 
32
+ mattr_accessor :sheet_id
33
+ @@sheet_id = nil
34
+
35
+ mattr_accessor :enable_postprocess
36
+ @@enable_postprocess = false
37
+
38
+ mattr_accessor :postprocess_class
39
+ @@postprocess_class = nil
40
+
29
41
  require 'takenoko/exporter'
30
42
  require 'takenoko/google_client'
31
43
 
@@ -33,50 +45,53 @@ module Takenoko
33
45
  yield self
34
46
  end
35
47
 
36
- def import
37
- check_config
38
- end
39
-
40
48
  def google_client
41
49
  @@google_client ||= GoogleClient.new(@@google_cridential_file)
42
50
  return @@google_client
43
51
  end
44
52
 
45
53
  def check_config
46
- raise "google_cridential_file setting cannot be nil" unless @@google_cridential_file
47
- raise "file not found:#{@@google_cridential_file}" unless ::File.exist?(@@google_cridential_file)
48
- raise "mapping_file cannot be nil" unless @@mapping_file
49
- raise "file not found:#{@@mapping_file}" unless ::File.exist?(@@mapping_file)
54
+ raise "Must specify mapping_file or sheet_id" unless (@@mapping_file || @@sheet_id)
55
+ raise "file not found:#{@@mapping_file}" if @@mapping_file && !::File.exist?(@@mapping_file)
50
56
  return true
51
57
  end
52
58
 
53
59
  def mapping_config
54
- return @@mapping_config if @@mapping_config
55
- conf = YAML.load_file(@@mapping_file).with_indifferent_access
56
- raise "tables not exists" if conf[:tables].blank?
60
+ return unless check_config
61
+ if @@mapping_file
62
+ conf = YAML.load_file(@@mapping_file).with_indifferent_access
63
+ raise "tables not exists" if conf[:tables].blank?
64
+ else
65
+ conf = HashWithIndifferentAccess.new({tables: {}})
66
+ google_client.spreadsheet.worksheets.each do |ws|
67
+ next if ws.title.match(/\s*#.*/)
68
+ conf[:tables][ws.title] = {
69
+ worksheet_id: ws.gid,
70
+ worksheet: ws.title
71
+ }
72
+ end
73
+ end
57
74
  conf[:tables].each do |t, v|
58
75
  table = conf[:tables][t]
59
76
  raise "Table config cannot be nil" unless table
60
- [:sheet_id, :worksheet_id, :columns_mapping].each do |f|
61
- raise "#{f} cannot be blank" if table[f].blank?
62
- end
77
+ raise "#{f} cannot be blank" unless table[:sheet_id] ||= @@sheet_id
78
+ table[:worksheet] = t if table[:worksheet].blank? && table[:worksheet_id].blank?
63
79
  table[:find_column] = table[:find_column] || :id
64
- table_name = table[:table_name] = t if table[:table_name].blank?
80
+ table_name = table[:table_name] = t.pluralize if table[:table_name].blank?
65
81
  table[:class_name] = table[:class_name] || (table_name && table_name.singularize.camelize) || table[:table_name].singularize.camelize
66
- unless table[:columns_mapping].key?(table[:find_column])
67
- if(table[:find_column] == :id)
68
- table[:columns_mapping] = {id: nil}.merge!(table[:columns_mapping])
69
- else
70
- table[:columns_mapping][table[:find_column]] = nil
71
- end
72
- end
73
- table[:columns_mapping].each do |s_col,db_col|
74
- table[:columns_mapping][s_col] = s_col unless db_col
82
+ [
83
+ :allow_overwrite,
84
+ :truncate_all_data,
85
+ :file_extension,
86
+ :export_file_location,
87
+ :enable_postprocess,
88
+ :postprocess_class
89
+ ].each do |f|
90
+ table[f] = class_variable_get("@@" + f.to_s) unless table.key?(f)
75
91
  end
76
92
 
77
- table[:header] = table[:columns_mapping].keys
78
- [:allow_overwrite,:truncate_all_data, :file_extension, :export_file_location].each do |f|
79
- table[f] = class_variable_get("@@" + f.to_s) unless table.key?(f)
93
+ if table[:enable_postprocess] && table[:postprocess_class].blank?
94
+ table[:postprocess_class] = table[:class_name]
80
95
  end
81
96
 
82
97
  raise "Not support file extension: #{table[:file_extension]}" unless SUPPORTED_FILE_EXT.include?(table[:file_extension])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: takenoko
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - KhiemNS
@@ -66,7 +66,7 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: Import data from google spreadsheet to database or files
69
+ description: Import data from google spreadsheet to database or files for Rails
70
70
  email:
71
71
  - khiemns54@gmail.com
72
72
  executables: []
@@ -107,7 +107,7 @@ rubyforge_project:
107
107
  rubygems_version: 2.5.1
108
108
  signing_key:
109
109
  specification_version: 4
110
- summary: Import data from google spreadsheet to database or files
110
+ summary: Import data from google spreadsheet to database or files for Rails
111
111
  test_files:
112
112
  - test/takenoko_test.rb
113
113
  - test/test_helper.rb