rails_admin_import 0.1.9 → 1.0.0

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.
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