xls_porter 0.0.7
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/lib/xls_porter.rb +133 -0
- metadata +77 -0
data/lib/xls_porter.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
module XlsPorter
|
2
|
+
|
3
|
+
class XlsUploader < CarrierWave::Uploader::Base
|
4
|
+
include CarrierWave::MimeTypes
|
5
|
+
process :set_content_type
|
6
|
+
|
7
|
+
# Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
|
8
|
+
include Sprockets::Helpers::RailsHelper
|
9
|
+
include Sprockets::Helpers::IsolatedHelper
|
10
|
+
|
11
|
+
# Choose what kind of storage to use for this uploader:
|
12
|
+
storage :file
|
13
|
+
# storage :fog
|
14
|
+
|
15
|
+
# Override the directory where uploaded files will be stored.
|
16
|
+
# This is a sensible default for uploaders that are meant to be mounted:
|
17
|
+
def store_dir
|
18
|
+
"#{Rails.root}/tmp/upload/"
|
19
|
+
end
|
20
|
+
|
21
|
+
# Override the filename of the uploaded files:
|
22
|
+
# Avoid using model.id or version_name here, see uploader/store.rb for details.
|
23
|
+
# def filename
|
24
|
+
# "something.jpg" if original_filename
|
25
|
+
# end
|
26
|
+
|
27
|
+
def extension_white_list
|
28
|
+
known=%w(xls xlsx)
|
29
|
+
known << /\w+/
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_xls(list, columns, name)
|
34
|
+
book = Spreadsheet::Workbook.new
|
35
|
+
sheet = book.create_worksheet :name => name
|
36
|
+
row = sheet.row(0)
|
37
|
+
columns.each {|column| row.push(column)}
|
38
|
+
idx = 0
|
39
|
+
list.each do |it|
|
40
|
+
row = sheet.row(idx += 1)
|
41
|
+
columns.each {|column| row.push(it[column])}
|
42
|
+
end
|
43
|
+
return book
|
44
|
+
end
|
45
|
+
|
46
|
+
def model_to_xls(model)
|
47
|
+
to_xls(model.all, model.column_names, model.name)
|
48
|
+
end
|
49
|
+
|
50
|
+
# sanitize and prefix filename with timestamp
|
51
|
+
# store the uploaded file
|
52
|
+
def store_uploaded_file(uploaded_file)
|
53
|
+
uploaded_file.original_filename = "#{Time.now.to_i}_#{File.basename(uploaded_file.original_filename)}"
|
54
|
+
file = XlsUploader.new
|
55
|
+
file.store!(uploaded_file)
|
56
|
+
return file
|
57
|
+
end
|
58
|
+
|
59
|
+
def xls_to_model(xls_file_path, model, ignore=[])
|
60
|
+
#TODO exception handling
|
61
|
+
|
62
|
+
book = Spreadsheet.open(xls_file_path)
|
63
|
+
sheet = book.worksheet(0)
|
64
|
+
columns = sheet.row(0)
|
65
|
+
ignore_columns = (columns - model.column_names) + ignore
|
66
|
+
id_idx = columns.find_index("id")
|
67
|
+
updates = []
|
68
|
+
# Read each row, skip the first (column names)
|
69
|
+
sheet.each 1 do |row|
|
70
|
+
id = row[id_idx]
|
71
|
+
record = nil
|
72
|
+
if id.nil?
|
73
|
+
record = model.new
|
74
|
+
record["update"] = "new"
|
75
|
+
else
|
76
|
+
begin
|
77
|
+
record = model.find(id)
|
78
|
+
record["update"] = "exist"
|
79
|
+
rescue
|
80
|
+
record = model.new
|
81
|
+
record["update"] = "new"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
(0..(columns.size - 1)).each do |i|
|
85
|
+
value = row[i]
|
86
|
+
value = value.strip if value.is_a?(String)
|
87
|
+
column = columns[i]
|
88
|
+
if column == "id" and record["update"] == "new"
|
89
|
+
record["id"] = value
|
90
|
+
elsif ignore_columns.include?(column)
|
91
|
+
#skip if column is ignored
|
92
|
+
elsif record[column].blank? and value.blank?
|
93
|
+
#skip if both are either nil or empty
|
94
|
+
elsif [DateTime, Time, Date].include?(value.class)
|
95
|
+
#puts "#{column} #{record[column]} == #{value} ? #{record[column].to_i == value.to_i}"
|
96
|
+
#TODO comparator and assigner for date types
|
97
|
+
else
|
98
|
+
if record[column] != value
|
99
|
+
record[column] = value
|
100
|
+
record["update"] = "updated" if record["update"] == "exist"
|
101
|
+
record["update_notes"] = [] if record["update_notes"].nil?
|
102
|
+
record["update_notes"] << column
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
#track all updates
|
107
|
+
updates << record if %w(new updated).include?(record["update"]) #not record.changed.empty?
|
108
|
+
end
|
109
|
+
#commit changes only after processing all updates
|
110
|
+
updates.each do |update|
|
111
|
+
begin
|
112
|
+
update.save
|
113
|
+
rescue Exception => exception
|
114
|
+
#track validation exception
|
115
|
+
update["update"] = "exception"
|
116
|
+
update["update_notes"] = exception.to_s
|
117
|
+
end
|
118
|
+
end
|
119
|
+
return {:columns => (%w(update update_notes) + columns), :updates => updates, :model => model.name}
|
120
|
+
end
|
121
|
+
|
122
|
+
def cleanup_tmp_file(file_path)
|
123
|
+
File.delete(file_path) if File.exist?(file_path)
|
124
|
+
end
|
125
|
+
|
126
|
+
def xls_upload_and_update_model(uploaded_file, model)
|
127
|
+
file_path = store_uploaded_file(uploaded_file).store_path
|
128
|
+
model_updates = xls_to_model(file_path, model)
|
129
|
+
cleanup_tmp_file(file_path)
|
130
|
+
return model_updates
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xls_porter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Reyes
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: carrierwave
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sprockets
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Export to and Import from XLS for Ruby and Rails apps
|
47
|
+
email: mikereyes.kg77@gmail.com
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- lib/xls_porter.rb
|
53
|
+
homepage: http://rubygems.org/gems/xls_porter
|
54
|
+
licenses: []
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.9.2
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.8.24
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: Export to and Import from XLS
|
77
|
+
test_files: []
|