xls_porter 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/xls_porter.rb +133 -0
  2. 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: []