importr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 857d9822884da68d290b3a2af294e8ca18b6e85a
4
+ data.tar.gz: 8472573b2d917b39b2db4b0f354b3509960c2f90
5
+ SHA512:
6
+ metadata.gz: 2ea9144af7cbeee9f1f35d9648e0b4f2803c0d6ef3fcb4c5d5edbbc4e4c1cf6a4790fe37188d2e1291c5d93fbb2fc049510e4b420e031c2e6dbadc0e794f3b70
7
+ data.tar.gz: 5cbeb3872a7da2cd441155527c1ce5ccb7f122b59a3f33879052417eb44dd7e757f204b78ff7f8ec54f0cbd313f368b371c75508da44a21b03c0ff14ab17a1e1
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Continuum
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ #rescue LoadError
2
+ # puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
3
+ #end
4
+
5
+
6
+ require 'rspec/core/rake_task'
7
+ require 'bundler'
8
+ Bundler::GemHelper.install_tasks
9
+
10
+ desc 'Default: run unit specs.'
11
+ task :default => :spec
12
+
13
+ desc 'Test the lazy_high_charts plugin.'
14
+ RSpec::Core::RakeTask.new('spec') do |t|
15
+ t.pattern = FileList['spec/**/*_spec.rb']
16
+ end
17
+
18
+ require 'rdoc/task'
19
+ RDoc::Task.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'Importr'
22
+ rdoc.options << '--line-numbers'
23
+ rdoc.rdoc_files.include('README.rdoc')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ #APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
28
+ #load 'rails/tasks/engine.rake'
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,4 @@
1
+ module Importr
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Importr
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,44 @@
1
+ module Importr
2
+ class DataImport < ActiveRecord::Base
3
+ belongs_to :user
4
+ mount_uploader :document, Importr::Uploader
5
+ serialize :error_messages, Array
6
+
7
+ def websocket_channel(scope)
8
+ #return "/#{resource.resource_type}/#{self.importer_type}/#{scope}"
9
+ return "/#{self.importer_type}/#{scope}-#{self.uuid}"
10
+ end
11
+
12
+ def generate_uuid
13
+ self.uuid = Digest::SHA1.hexdigest(Time.now.to_i.to_s)
14
+ end
15
+
16
+ def progress_text
17
+ total_rows.blank? ? "None" : "#{processed_rows || 0} / #{total_rows}"
18
+ end
19
+
20
+ def error_count_text
21
+ error_count.blank? ? "None" : error_count
22
+ end
23
+
24
+ def status_text
25
+ if finished
26
+ total_rows.blank? ? "Failed" : "Finished"
27
+ else
28
+ "In progress"
29
+ end
30
+ end
31
+
32
+ def importer_class
33
+ self.importer_type.constantize
34
+ end
35
+
36
+ def file_path
37
+ self.document.file.file
38
+ end
39
+
40
+ def perform
41
+ importer_class.import(file_path, context: self)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,15 @@
1
+
2
+ module Importr
3
+ class Uploader < CarrierWave::Uploader::Base
4
+ storage :file
5
+ after :store, :importer
6
+
7
+ def store_dir
8
+ "uploads/#{model.class.to_s.underscore}/#{model.id}"
9
+ end
10
+
11
+ def importer(new_file)
12
+ Importr::Worker.perform_in(5.seconds, model.id)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ = javascript_include_tag "#{root_url(:port => 8000)}faye/client.js"
2
+ = render "importr/admin/data_imports/ws_client"
3
+
4
+ .attributes_table
5
+ %table
6
+ %tbody
7
+ %tr.row
8
+ %th
9
+ Status
10
+ %td#process-status
11
+ = @data_import.status_text
12
+ %tr.row
13
+ %th
14
+ Rows processed
15
+ %td#rows-processed
16
+ = @data_import.progress_text
17
+ %tr.row
18
+ %th
19
+ Rows with errors
20
+ %td#rows-with-errors
21
+ = @data_import.error_count_text
@@ -0,0 +1,9 @@
1
+ %table
2
+ %thead
3
+ %tr
4
+ %th
5
+ Row Number
6
+ %th
7
+ Error Messages
8
+ %tbody
9
+ %tr
@@ -0,0 +1,30 @@
1
+ :javascript
2
+ (function() {
3
+
4
+ var client = new Faye.Client("#{root_url(port: 8000)}faye", { retry: 5 });
5
+
6
+ function update_row_count(message) {
7
+ if (typeof(message.processed_rows) != 'undefined') {
8
+ $('#rows-processed').html('' + message.processed_rows + ' / ' + message.total_rows)
9
+ }
10
+ console.log(message)
11
+ }
12
+
13
+ client.subscribe("#{@data_import.websocket_channel(:base)}", function(message) {
14
+ update_row_count(message)
15
+ $("#process-status").html(message.error)
16
+ });
17
+
18
+ client.subscribe("#{@data_import.websocket_channel(:error)}", function(message) {
19
+ update_row_count(message)
20
+ $('#rows-with-errors').html(message.error_count)
21
+
22
+ $('#row-errors-panel tbody').append("<tr><td>" + message.index + "</td><td>" + message.error + "</td></tr>")
23
+ $('#row-errors-panel').show();
24
+ });
25
+
26
+ client.subscribe("#{@data_import.websocket_channel(:success)}", function(message) {
27
+ update_row_count(message)
28
+ });
29
+
30
+ })();
@@ -0,0 +1,6 @@
1
+ = semantic_form_for @data_import, url: { :action => "import_excel" } do |f|
2
+ = f.inputs do
3
+ = f.input :document, as: :file
4
+ = f.input :uuid, as: :hidden
5
+ = f.input :importer_type, as: :hidden
6
+ = f.submit
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Importr</title>
5
+ <%= stylesheet_link_tag "importr/application", media: "all" %>
6
+ <%= javascript_include_tag "importr/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,10 @@
1
+ module Importr
2
+ class Worker
3
+ include Sidekiq::Worker
4
+
5
+ def perform(data_import_id)
6
+ data_import = Importr::DataImport.find(data_import_id)
7
+ data_import.perform
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,2 @@
1
+ Importr::Engine.routes.draw do
2
+ end
@@ -0,0 +1,19 @@
1
+ class CreateImportrDataImports < ActiveRecord::Migration
2
+ def change
3
+ create_table :importr_data_imports do |t|
4
+ t.string :importer_type
5
+ t.string :resource_type
6
+ t.string :document
7
+ t.boolean :finished, default: false
8
+ t.references :user, index: true
9
+ t.text :error_messages
10
+ t.integer :success_count
11
+ t.integer :error_count
12
+ t.integer :processed_rows
13
+ t.integer :total_rows
14
+ t.string :uuid
15
+
16
+ t.timestamps
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ require "importr/engine"
2
+ require "active_importer"
3
+
4
+ module Importr
5
+ autoload :VERSION, 'importr/version.rb'
6
+ autoload :Config, 'importr/config.rb'
7
+ autoload :Notifier, 'importr/notifier.rb'
8
+ autoload :Importer, 'importr/importer'
9
+ autoload :ActiveAdmin, 'importr/active_admin' if defined? ::ActiveAdmin
10
+ end
11
+
@@ -0,0 +1,35 @@
1
+ module Importr
2
+ module ActiveAdmin
3
+
4
+ def data_import_interface(importer_type = nil)
5
+ klass = config.resource_class.name
6
+ importer_type ||= "#{klass}Importer".constantize
7
+
8
+ action_item :only => :index do
9
+ link_to 'Import from Excel', :action => 'upload_excel'
10
+ end
11
+
12
+ collection_action :upload_excel do
13
+ @data_import = DataImport.new(importer_type: importer_type)
14
+ @data_import.generate_uuid
15
+ render "importr/admin/data_imports/form"
16
+ end
17
+
18
+ collection_action :import_excel, :method => :post do
19
+ @data_import = DataImport.new(permitted_params[:data_import])
20
+ @data_import.resource_type = klass
21
+ @data_import.user_id = current_admin_user.id
22
+ @data_import.importer_type = importer_type.to_s.to_sym
23
+ @data_import.save
24
+ redirect_to [:admin, @data_import]
25
+ end
26
+
27
+ controller do
28
+ def permitted_params
29
+ params.permit data_import: [:document, :uuid, :importer_type]
30
+ end
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ require "active_support/core_ext/module/attribute_accessors"
2
+
3
+ module Importr
4
+ class Config
5
+
6
+ def self.setup
7
+ yield self
8
+ end
9
+
10
+ mattr_accessor :web_socket_class, :web_socket_method
11
+
12
+
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Importr
3
+ class Engine < ::Rails::Engine
4
+
5
+ isolate_namespace Importr
6
+ config.generators do |g|
7
+ g.test_framework :rspec,
8
+ :fixture_replacement => :factory_girl ,
9
+ :dir => "spec/factories"
10
+ g.integration_tool :rspec
11
+ end
12
+
13
+ initializer "Activeadmin Importer interface" do |app|
14
+ ::ActiveAdmin::ResourceDSL.send(:include, Importr::ActiveAdmin) if defined? ::ActiveAdmin
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,55 @@
1
+ # require 'active_importer'
2
+
3
+ module Importr
4
+ class Importer < ActiveImporter::Base
5
+ def initialize(file, options = {})
6
+ # TODO: ensure that data_import.model_class == self.class.model_class
7
+
8
+ super
9
+
10
+ if data_import && data_import.finished
11
+ raise "Data import #{data_import.id} was already processed"
12
+ end
13
+ end
14
+
15
+ alias_method :data_import, :context
16
+
17
+ def row_success
18
+ super
19
+ update_counters
20
+ notify(:success, @counters)
21
+ end
22
+
23
+ def row_error(error_message)
24
+ super
25
+ update_counters
26
+ notify(:error, @counters.merge(index: row_index, error: error_message))
27
+ end
28
+
29
+ def import_failed(error_message)
30
+ super
31
+ notify(:base, error: error_message)
32
+ end
33
+
34
+ def import_finished
35
+ data_import.update_attribute(:finished, true) if data_import
36
+ end
37
+
38
+ private
39
+
40
+ def notify(subchannel, message)
41
+ channel = ["/#{self.class}/#{subchannel}", data_import.try(:uuid)].compact.join("-")
42
+ Importr::Notifier.notify(channel, message)
43
+ end
44
+
45
+ def update_counters
46
+ @counters = {
47
+ success_count: row_success_count,
48
+ error_count: row_error_count,
49
+ processed_rows: row_processed_count,
50
+ total_rows: row_count,
51
+ }
52
+ data_import.update_attributes(@counters) if data_import
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module Importr
3
+ class Notifier
4
+
5
+ def self.notify(channel, msg)
6
+ if Importr::Config.web_socket_class.present? and defined?(Importr::Config.web_socket_class.constantize)
7
+ Importr::Config.web_socket_class.constantize.send(Importr::Config.web_socket_method.to_sym, channel, msg)
8
+ end
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Importr
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :importr do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,238 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: importr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ernesto Garcia
8
+ - Miguel Michelson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-11-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 4.0.1.rc3
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 4.0.1.rc3
28
+ - !ruby/object:Gem::Dependency
29
+ name: active_importer
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: carrierwave
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: haml
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: roo
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: sqlite3
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rspec-rails
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: factory_girl
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: factory_girl_rails
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: shoulda-matchers
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ~>
145
+ - !ruby/object:Gem::Version
146
+ version: '1.0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ~>
152
+ - !ruby/object:Gem::Version
153
+ version: '1.0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: database_cleaner
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - '>='
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ - !ruby/object:Gem::Dependency
169
+ name: capybara
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ type: :development
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ description: Full Stack rails engine for xls import to activerecord, with process
183
+ notification through websockets, and activeadmin integration, works with rails 4.0.+.
184
+ email:
185
+ - gnapse@gmail.com
186
+ - miguelmichelson@gmail.com
187
+ executables: []
188
+ extensions: []
189
+ extra_rdoc_files: []
190
+ files:
191
+ - app/assets/javascripts/importr/application.js
192
+ - app/assets/stylesheets/importr/application.css
193
+ - app/controllers/importr/application_controller.rb
194
+ - app/helpers/importr/application_helper.rb
195
+ - app/models/importr/data_import.rb
196
+ - app/uploaders/importr/uploader.rb
197
+ - app/views/importr/admin/data_imports/_progress.haml
198
+ - app/views/importr/admin/data_imports/_rows_with_errors.haml
199
+ - app/views/importr/admin/data_imports/_ws_client.haml
200
+ - app/views/importr/admin/data_imports/form.haml
201
+ - app/views/layouts/importr/application.html.erb
202
+ - app/workers/importr/worker.rb
203
+ - config/routes.rb
204
+ - db/migrate/20131025012832_create_importr_data_imports.rb
205
+ - lib/importr/active_admin.rb
206
+ - lib/importr/config.rb
207
+ - lib/importr/engine.rb
208
+ - lib/importr/importer.rb
209
+ - lib/importr/notifier.rb
210
+ - lib/importr/version.rb
211
+ - lib/importr.rb
212
+ - lib/tasks/importr_tasks.rake
213
+ - MIT-LICENSE
214
+ - Rakefile
215
+ homepage: http://todo.cl
216
+ licenses: []
217
+ metadata: {}
218
+ post_install_message:
219
+ rdoc_options: []
220
+ require_paths:
221
+ - lib
222
+ required_ruby_version: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - '>='
225
+ - !ruby/object:Gem::Version
226
+ version: '0'
227
+ required_rubygems_version: !ruby/object:Gem::Requirement
228
+ requirements:
229
+ - - '>='
230
+ - !ruby/object:Gem::Version
231
+ version: '0'
232
+ requirements: []
233
+ rubyforge_project:
234
+ rubygems_version: 2.0.6
235
+ signing_key:
236
+ specification_version: 4
237
+ summary: Full Stack rails engine for xls import to activerecord.
238
+ test_files: []