rails_admin_import 0.1.9 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,37 +1,107 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_admin_import
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steph Skardal
8
+ - Julien Vanier
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-05-22 00:00:00.000000000 Z
12
- dependencies: []
12
+ date: 2015-06-09 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: '3.2'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '3.2'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rails_admin
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.6.6
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 0.6.6
42
+ - !ruby/object:Gem::Dependency
43
+ name: haml
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '4.0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '4.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rchardet
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.6'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.6'
13
70
  description:
14
- email: steph@endpoint.com
71
+ email:
72
+ - steph@endpoint.com
73
+ - jvanier@gmail.com
15
74
  executables: []
16
75
  extensions: []
17
76
  extra_rdoc_files: []
18
77
  files:
78
+ - CHANGELOG.md
19
79
  - MIT-LICENSE
20
80
  - README.md
21
- - RELEASE_NOTES
22
81
  - Rakefile
23
- - app/views/rails_admin/main/import.html.erb
82
+ - app/views/rails_admin/main/_results.html.haml
83
+ - app/views/rails_admin/main/_section.html.haml
84
+ - app/views/rails_admin/main/import.html.haml
24
85
  - config/locales/import.en.yml
25
86
  - lib/rails_admin_import.rb
87
+ - lib/rails_admin_import/action.rb
26
88
  - lib/rails_admin_import/config.rb
27
- - lib/rails_admin_import/config/base.rb
28
- - lib/rails_admin_import/config/model.rb
89
+ - lib/rails_admin_import/config/legacy_model.rb
90
+ - lib/rails_admin_import/config/sections/import.rb
29
91
  - lib/rails_admin_import/engine.rb
30
- - lib/rails_admin_import/import.rb
92
+ - lib/rails_admin_import/formats.rb
93
+ - lib/rails_admin_import/formats/csv_importer.rb
94
+ - lib/rails_admin_import/formats/dummy_importer.rb
95
+ - lib/rails_admin_import/formats/file_importer.rb
96
+ - lib/rails_admin_import/formats/json_importer.rb
31
97
  - lib/rails_admin_import/import_logger.rb
98
+ - lib/rails_admin_import/import_model.rb
99
+ - lib/rails_admin_import/importer.rb
100
+ - lib/rails_admin_import/rails_admin_plugin.rb
32
101
  - lib/rails_admin_import/version.rb
33
- homepage:
34
- licenses: []
102
+ homepage: https://github.com/stephskardal/rails_admin_import
103
+ licenses:
104
+ - MIT
35
105
  metadata: {}
36
106
  post_install_message:
37
107
  rdoc_options: []
@@ -49,8 +119,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
119
  version: '0'
50
120
  requirements: []
51
121
  rubyforge_project:
52
- rubygems_version: 2.2.2
122
+ rubygems_version: 2.4.5
53
123
  signing_key:
54
124
  specification_version: 4
55
- summary: Import functionality for rails admin
125
+ summary: Import functionality for Rails Admin
56
126
  test_files: []
@@ -1,143 +0,0 @@
1
- <% if @response -%>
2
- <% if @response.has_key?(:error) -%>
3
- <div class="alert-error alert"><%= @response[:error] %></div>
4
- <% end -%>
5
- <% if @response.has_key?(:notice) -%>
6
- <div class="alert-success alert"><%= @response[:notice] %></div>
7
- <% end -%>
8
- <% end -%>
9
-
10
- <%= form_tag rails_admin.import_url(@abstract_model.to_param), :multipart => true, :class => 'form-horizontal' do |f| -%>
11
- <fieldset>
12
- <legend>
13
- <i class="icon-chevron-down"></i>
14
- Fields to import
15
- </legend>
16
- <div class="control-group">
17
- <label class="control-label" data-original-title="Click to reverse selection" onclick="jQuery(this).siblings('.controls').find('input').click()" rel="tooltip">Fields from <%= @abstract_model.to_param %></label>
18
- <div class="controls">
19
- <ul>
20
- <% @abstract_model.model.import_fields.each do |field| -%>
21
- <li><%= field %></li>
22
- <% end -%>
23
- </ul>
24
- <p class="help-block">The following fields may be included in the import file.</p>
25
- </div>
26
- </div>
27
- <% if @abstract_model.model.belongs_to_fields.any? -%>
28
- <div class="control-group">
29
- <label class="control-label" data-original-title="Click to reverse selection" onclick="jQuery(this).siblings('.controls').find('input').click()" rel="tooltip">Belongs To Fields</label>
30
- <div class="controls">
31
- <ul>
32
- <% @abstract_model.model.belongs_to_fields.each do |field| -%>
33
- <li><a href="<%= url_for(:action => :index, :model_name => field) %>"><%= field.to_s.titleize %></a></li>
34
- <% end -%>
35
- </ul>
36
- <p class="help-block">These fields map to other items in the database, lookup via attribute selected below.</p>
37
- </div>
38
- </div>
39
- <% end -%>
40
- <% if @abstract_model.model.file_fields.any? -%>
41
- <div class="control-group">
42
- <label class="control-label" data-original-title="Click to reverse selection" onclick="jQuery(this).siblings('.controls').find('input').click()" rel="tooltip">Belongs To Fields</label>
43
- <div class="controls">
44
- <ul>
45
- <% @abstract_model.model.file_fields.each do |field| -%>
46
- <li><%= field %></li>
47
- <% end -%>
48
- </ul>
49
- <p class="help-block">These must be a downloadable URL.</p>
50
- </div>
51
- </div>
52
- <% end -%>
53
- <% if @abstract_model.model.many_fields.any? -%>
54
- <div class="control-group">
55
- <label class="control-label" data-original-title="Click to reverse selection" onclick="jQuery(this).siblings('.controls').find('input').click()" rel="tooltip">Belongs To Fields</label>
56
- <div class="controls">
57
- <ul>
58
- <% @abstract_model.model.many_fields.each do |field| -%>
59
- <li><%= field %></li>
60
- <% end -%>
61
- </ul>
62
- <p class="help-block">These fields map to other columns in the database, lookup via attribute selected below. There may be multiple columns with this header in the spreadsheet.</p>
63
- </div>
64
- </div>
65
- <% end -%>
66
- <% if RailsAdminImport.config(@abstract_model.model).extra_fields.any? -%>
67
- <div class="control-group">
68
- <label class="control-label" data-original-title="Click to reverse selection" onclick="jQuery(this).siblings('.controls').find('input').click()" rel="tooltip">Belongs To Fields</label>
69
- <div class="controls">
70
- <ul>
71
- <% RailsAdminImport.config(@abstract_model.model).extra_fields.each do |field| -%>
72
- <li><%= field %></li>
73
- <% end -%>
74
- </ul>
75
- <p class="help-block">Additional application specific fields.</p>
76
- </div>
77
- </div>
78
- <% end -%>
79
- </fieldset>
80
- <fieldset>
81
- <legend>
82
- <i class="icon-chevron-down"></i>
83
- Upload file
84
- </legend>
85
- <div class="control-group">
86
- <label class="control-label" data-original-title="Click to reverse selection" onclick="jQuery(this).siblings('.controls').find('input').click()" rel="tooltip">File</label>
87
- <div class="controls">
88
- <%= file_field_tag :file %>
89
- <p class="help-block">Please limit upload file to <%= RailsAdminImport.config.line_item_limit %> line items.</p>
90
- </div>
91
- </div>
92
- <div class="control-group">
93
- <label class="control-label" data-original-title="Click to reverse selection" onclick="jQuery(this).siblings('.controls').find('input').click()" rel="tooltip">Update if exists</label>
94
- <div class="controls">
95
- <label class="checkbox">
96
- <%= check_box_tag :update_if_exists %>
97
- </label>
98
- </div>
99
- </div>
100
- <div class="control-group">
101
- <label class="control-label" data-original-title="Click to reverse selection" onclick="jQuery(this).siblings('.controls').find('input').click()" rel="tooltip">Update lookup field</label>
102
- <div class="controls">
103
- <select name="update_lookup">
104
- <% @abstract_model.model.new.attributes.keys.each do |key| -%>
105
- <option value="<%= key %>"><%= key %></option>
106
- <% end -%>
107
- </select>
108
- </div>
109
- </div>
110
-
111
- </fieldset>
112
- <% if @abstract_model.model.belongs_to_fields.any? -%>
113
- <fieldset>
114
- <legend>
115
- <i class="icon-chevron-down"></i>
116
- Related fields mapping
117
- </legend>
118
- <% [@abstract_model.model.belongs_to_fields, @abstract_model.model.many_fields].flatten.each do |field| -%>
119
- <div class="control-group">
120
- <label class="control-label" for="csv_options_encoding_to"><a href="<%= url_for(:action => :index, :model_name => field) %>"><%= field.to_s.titleize %></a> mapping</label>
121
- <div class="controls">
122
- <select name="<%= field %>">
123
- <% field.to_s.classify.constantize.new.attributes.keys.each do |key| -%>
124
- <option value="<%= key %>"><%= key %></option>
125
- <% end -%>
126
- </select>
127
- </div>
128
- </div>
129
- <% end -%>
130
- </fieldset>
131
- <% end -%>
132
- <div class="form-actions">
133
- <button class="btn btn-primary" name="commit" type="submit" data-disable-with="Uploading...">
134
- <i class="icon-white icon-ok"></i>
135
- Import
136
- </button>
137
- <button class="btn" name="_continue" type="submit">
138
- <i class="icon-remove"></i>
139
- Cancel
140
- </button>
141
- <!--<%= submit_tag "Upload", :disable_with => "Uploading..." %>-->
142
- </div>
143
- <% end -%>
@@ -1,62 +0,0 @@
1
- module RailsAdminImport
2
- module Config
3
- class Base
4
- def initialize(parent = nil)
5
- end
6
-
7
- # Register an instance option for this object only
8
- def register_instance_option(option_name, &default)
9
- scope = class << self; self; end;
10
- self.class.register_instance_option(option_name, scope, &default)
11
- end
12
-
13
- # Register an instance option. Instance option is a configuration
14
- # option that stores its value within an instance variable and is
15
- # accessed by an instance method. Both go by the name of the option.
16
- def self.register_instance_option(option_name, scope = self, &default)
17
- unless options = scope.instance_variable_get("@config_options")
18
- options = scope.instance_variable_set("@config_options", {})
19
- end
20
-
21
- option_name = option_name.to_s
22
-
23
- options[option_name] = nil
24
-
25
- # If it's a boolean create an alias for it and remove question mark
26
- if "?" == option_name[-1, 1]
27
- scope.send(:define_method, "#{option_name.chop!}?") do
28
- send(option_name)
29
- end
30
- end
31
-
32
- # Define getter/setter by the option name
33
- scope.send(:define_method, option_name) do |*args, &block|
34
- if !args[0].nil? || block
35
- # Invocation with args --> This is the declaration of the option, i.e. setter
36
- instance_variable_set("@#{option_name}_registered", args[0].nil? ? block : args[0])
37
- else
38
- # Invocation without args nor block --> It's the use of the option, i.e. getter
39
- value = instance_variable_get("@#{option_name}_registered")
40
- case value
41
- when Proc
42
- # Track recursive invocation with an instance variable. This prevents run-away recursion
43
- # and allows configurations such as
44
- # label { "#{label}".upcase }
45
- # This will use the default definition when called recursively.
46
- if instance_variable_get("@#{option_name}_recurring")
47
- value = instance_eval &default
48
- else
49
- instance_variable_set("@#{option_name}_recurring", true)
50
- value = instance_eval &value
51
- instance_variable_set("@#{option_name}_recurring", false)
52
- end
53
- when nil
54
- value = instance_eval &default
55
- end
56
- value
57
- end
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,23 +0,0 @@
1
- require 'rails_admin_import/config'
2
- require 'rails_admin_import/config/base'
3
-
4
- module RailsAdminImport
5
- module Config
6
- class Model < RailsAdminImport::Config::Base
7
- def initialize(entity)
8
- end
9
-
10
- register_instance_option(:label) do
11
- :id
12
- end
13
-
14
- register_instance_option(:excluded_fields) do
15
- []
16
- end
17
-
18
- register_instance_option(:extra_fields) do
19
- []
20
- end
21
- end
22
- end
23
- end
@@ -1,218 +0,0 @@
1
- require 'open-uri'
2
- require "rails_admin_import/import_logger"
3
-
4
- module RailsAdminImport
5
- module Import
6
- extend ActiveSupport::Concern
7
-
8
- module ClassMethods
9
- def file_fields
10
- attrs = []
11
- if self.methods.include?(:attachment_definitions) && !self.attachment_definitions.nil?
12
- attrs = self.attachment_definitions.keys
13
- end
14
- attrs - RailsAdminImport.config(self).excluded_fields
15
- end
16
-
17
- def import_fields
18
- fields = []
19
-
20
- fields = self.new.attributes.keys.collect { |key| key.to_sym }
21
-
22
- self.belongs_to_fields.each do |key|
23
- fields.delete("#{key}_id".to_sym)
24
- end
25
-
26
- self.file_fields.each do |key|
27
- fields.delete("#{key}_file_name".to_sym)
28
- fields.delete("#{key}_content_type".to_sym)
29
- fields.delete("#{key}_file_size".to_sym)
30
- fields.delete("#{key}_updated_at".to_sym)
31
- end
32
-
33
- excluded_fields = RailsAdminImport.config(self).excluded_fields
34
- [:id, :created_at, :updated_at, excluded_fields].flatten.each do |key|
35
- fields.delete(key)
36
- end
37
-
38
- fields
39
- end
40
-
41
- def belongs_to_fields
42
- attrs = self.reflections.select { |k, v| v.macro == :belongs_to }.keys
43
- attrs - RailsAdminImport.config(self).excluded_fields
44
- end
45
-
46
- def many_fields
47
- attrs = []
48
- self.reflections.each do |k, v|
49
- if [:has_and_belongs_to_many, :has_many].include?(v.macro)
50
- attrs << k.to_s.singularize.to_sym
51
- end
52
- end
53
-
54
- attrs - RailsAdminImport.config(self).excluded_fields
55
- end
56
-
57
- def run_import(params)
58
- begin
59
- if !params.has_key?(:file)
60
- return results = { :success => [], :error => ["You must select a file."] }
61
- end
62
-
63
- if RailsAdminImport.config.logging
64
- FileUtils.copy(params[:file].tempfile, "#{Rails.root}/log/import/#{Time.now.strftime("%Y-%m-%d-%H-%M-%S")}-import.csv")
65
- end
66
-
67
- text = File.read(params[:file].tempfile)
68
- clean = text.force_encoding('BINARY').encode('UTF-8', :undef => :replace, :replace => '').gsub(/\n$/, '')
69
- file_check = CSV.new(clean)
70
- logger = ImportLogger.new
71
-
72
- if file_check.readlines.size > RailsAdminImport.config.line_item_limit
73
- return results = { :success => [], :error => ["Please limit upload file to #{RailsAdminImport.config.line_item_limit} line items."] }
74
- end
75
-
76
- map = {}
77
-
78
- file = CSV.new(clean)
79
- file.readline.each_with_index do |key, i|
80
- if self.many_fields.include?(key.to_sym)
81
- map[key.to_sym] ||= []
82
- map[key.to_sym] << i
83
- else
84
- map[key.to_sym] = i
85
- end
86
- end
87
-
88
- update = params.has_key?(:update_if_exists) && params[:update_if_exists] ? params[:update_lookup].to_sym : nil
89
-
90
- if update && !map.has_key?(params[:update_lookup].to_sym)
91
- return results = { :success => [], :error => ["Your file must contain a column for the 'Update lookup field' you selected."] }
92
- end
93
-
94
- results = { :success => [], :error => [] }
95
-
96
- associated_map = {}
97
- self.belongs_to_fields.flatten.each do |field|
98
- associated_map[field] = field.to_s.classify.constantize.all.inject({}) { |hash, c| hash[c.send(params[field]).to_s] = c.id; hash }
99
- end
100
- self.many_fields.flatten.each do |field|
101
- associated_map[field] = field.to_s.classify.constantize.all.inject({}) { |hash, c| hash[c.send(params[field]).to_s] = c; hash }
102
- end
103
-
104
- label_method = RailsAdminImport.config(self).label
105
-
106
- file.each do |row|
107
- object = self.import_initialize(row, map, update)
108
- object.import_belongs_to_data(associated_map, row, map)
109
- object.import_many_data(associated_map, row, map)
110
- object.before_import_save(row, map)
111
-
112
- object.import_files(row, map)
113
-
114
- verb = object.new_record? ? "Create" : "Update"
115
- if object.errors.empty?
116
- if object.save
117
- logger.info "#{Time.now.to_s}: #{verb}d: #{object.send(label_method)}"
118
- results[:success] << "#{verb}d: #{object.send(label_method)}"
119
- object.after_import_save(row, map)
120
- else
121
- logger.info "#{Time.now.to_s}: Failed to #{verb}: #{object.send(label_method)}. Errors: #{object.errors.full_messages.join(', ')}."
122
- results[:error] << "Failed to #{verb}: #{object.send(label_method)}. Errors: #{object.errors.full_messages.join(', ')}."
123
- end
124
- else
125
- logger.info "#{Time.now.to_s}: Errors before save: #{object.send(label_method)}. Errors: #{object.errors.full_messages.join(', ')}."
126
- results[:error] << "Errors before save: #{object.send(label_method)}. Errors: #{object.errors.full_messages.join(', ')}."
127
- end
128
- end
129
-
130
- results
131
- rescue Exception => e
132
- logger.info "#{Time.now.to_s}: Unknown exception in import: #{e.inspect}"
133
- return results = { :success => [], :error => ["Could not upload. Unexpected error: #{e.to_s}"] }
134
- end
135
- end
136
-
137
- def import_initialize(row, map, update)
138
- new_attrs = {}
139
- self.import_fields.each do |key|
140
- new_attrs[key] = row[map[key]] if map[key]
141
- end
142
-
143
- item = nil
144
- if update.present?
145
- item = self.send("find_by_#{update}", row[map[update]])
146
- end
147
-
148
- if item.nil?
149
- item = self.new(new_attrs)
150
- else
151
- item.attributes = new_attrs.except(update.to_sym)
152
- item.save
153
- end
154
-
155
- item
156
- end
157
- end
158
-
159
- def before_import_save(*args)
160
- # Meant to be overridden to do special actions
161
- end
162
-
163
- def after_import_save(*args)
164
- # Meant to be overridden to do special actions
165
- end
166
-
167
- def import_display
168
- self.id
169
- end
170
-
171
- def import_files(row, map)
172
- if self.new_record? && self.valid?
173
- self.class.file_fields.each do |key|
174
- if map[key] && !row[map[key]].nil?
175
- begin
176
- # Strip file
177
- row[map[key]] = row[map[key]].gsub(/\s+/, "")
178
- format = row[map[key]].match(/[a-z0-9]+$/)
179
- open("#{Rails.root}/tmp/#{self.permalink}.#{format}", 'wb') { |file| file << open(row[map[key]]).read }
180
- self.send("#{key}=", File.open("#{Rails.root}/tmp/#{self.permalink}.#{format}"))
181
- rescue Exception => e
182
- self.errors.add(:base, "Import error: #{e.inspect}")
183
- end
184
- end
185
- end
186
- end
187
- end
188
-
189
- def import_belongs_to_data(associated_map, row, map)
190
- self.class.belongs_to_fields.each do |key|
191
- if map.has_key?(key) && row[map[key]] != ""
192
- self.send("#{key}_id=", associated_map[key][row[map[key]]])
193
- end
194
- end
195
- end
196
-
197
- def import_many_data(associated_map, row, map)
198
- self.class.many_fields.each do |key|
199
- values = []
200
-
201
- map[key] ||= []
202
- map[key].each do |pos|
203
- if row[pos] != "" && associated_map[key][row[pos]]
204
- values << associated_map[key][row[pos]]
205
- end
206
- end
207
-
208
- if values.any?
209
- self.send("#{key.to_s.pluralize}=", values)
210
- end
211
- end
212
- end
213
- end
214
- end
215
-
216
- class ActiveRecord::Base
217
- include RailsAdminImport::Import
218
- end