rails_admin_import 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +29 -0
- data/README.md +44 -19
- data/app/views/rails_admin/main/_results.html.erb +35 -0
- data/app/views/rails_admin/main/_section.html.erb +21 -0
- data/app/views/rails_admin/main/import.html.erb +102 -0
- data/config/locales/import.en.yml +47 -44
- data/lib/rails_admin_import/action.rb +1 -1
- data/lib/rails_admin_import/config.rb +2 -0
- data/lib/rails_admin_import/formats/csv_importer.rb +5 -4
- data/lib/rails_admin_import/import_logger.rb +1 -1
- data/lib/rails_admin_import/importer.rb +4 -0
- data/lib/rails_admin_import/version.rb +1 -1
- metadata +11 -11
- data/app/views/rails_admin/main/_results.html.haml +0 -18
- data/app/views/rails_admin/main/_section.html.haml +0 -10
- data/app/views/rails_admin/main/import.html.haml +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 83c7b4f8595f9938d575df4a7550537d04eaa6d1dd52e9bf0d1adbbabd09df4e
|
4
|
+
data.tar.gz: 1b74f9a44d0cffb8062d5efd7e016989ac2003b804329c9adfcb931320944178
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50d6d0ef870a078688946f7615eb863886e807a4375b4ea62471a64e13a60b12a91a5b6944b22eddd1d0d5809003ff37c64d330eed310285bb6e744430dc1096
|
7
|
+
data.tar.gz: 0fc377a823623ca96162234f8604de9a71a03a527ac7929aaa49a6dc5a294a520d9bee1acda219b91c40b320556bdc5246cdc8823eb36d57b6a400f1aedb797e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,34 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
# 3.0.0 / 2022-01-29
|
4
|
+
|
5
|
+
- BREAKING CHANGE: Templates are now compatible with Rails Admin 3.x. For Rails Admin 2.x, continue using version 2.3.1. Thanks @Wowu
|
6
|
+
|
7
|
+
# 2.3.1 / 2022-01-29
|
8
|
+
|
9
|
+
- Mark compatibility to Rails Admin < 3.0
|
10
|
+
- Bump Nokogiri in tests
|
11
|
+
|
12
|
+
# 2.3.0 / 2021-06-11
|
13
|
+
|
14
|
+
- Added an option to pass filename for each record. Thanks @waheedi
|
15
|
+
- Enumeration translation. Thanks @zaknafain
|
16
|
+
|
17
|
+
# 2.2.0 / 2019-02-24
|
18
|
+
|
19
|
+
- Switch to using CharlockHolmes for character detection. Thanks @codealchemy
|
20
|
+
- Readme improvements. Thanks @olleolleolle
|
21
|
+
|
22
|
+
# 2.1.0 / 2017-11-18
|
23
|
+
|
24
|
+
- French translation. Thanks @rodinux
|
25
|
+
- Check for blank headers. Thanks @JuandGirald
|
26
|
+
- Italian translation. Thanks @aprofiti
|
27
|
+
- Remove haml dependency. Thanks @prem-prakash
|
28
|
+
- Japanese translation. Thanks @higumachan
|
29
|
+
- Multiple mapping keys. Thanks @dmitrypol
|
30
|
+
- Add more hooks during import
|
31
|
+
|
3
32
|
# 2.0.0 / 2016-05-04
|
4
33
|
|
5
34
|
- Pull in the encoding list from the Encoding module instead of RailsAdmin. Thanks @baldursson, @patricklewis and @lucasff
|
data/README.md
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
# Rails Admin Import
|
2
2
|
|
3
|
-
[![Build Status](https://
|
3
|
+
[![Build Status](https://github.com/stephskardal/rails_admin_import/actions/workflows/ruby.yml/badge.svg)](https://github.com/stephskardal/rails_admin_import/actions/workflows/ruby.yml)
|
4
4
|
|
5
5
|
Plugin functionality to add generic import to Rails Admin from CSV, JSON and XLSX files
|
6
6
|
|
7
|
+
## Versions
|
8
|
+
|
9
|
+
Rails Admin Import 3.x is compatible with Rails Admin 3.x.
|
10
|
+
|
11
|
+
If you're still using Rails Admin 2.x, use Rails Admin Import 2.3.1
|
12
|
+
|
7
13
|
## Installation
|
8
14
|
|
9
15
|
* First, add to Gemfile:
|
10
16
|
|
11
|
-
```
|
12
|
-
gem "rails_admin_import", "~>
|
17
|
+
```ruby
|
18
|
+
gem "rails_admin_import", "~> 3.0"
|
13
19
|
```
|
14
20
|
|
15
21
|
* Define configuration in `config/initializers/rails_admin_import.rb`:
|
@@ -26,8 +32,10 @@ RailsAdmin.config do |config|
|
|
26
32
|
|
27
33
|
# Optional:
|
28
34
|
# Configure global RailsAdminImport options
|
35
|
+
# Configure pass filename to records hashes
|
29
36
|
config.configure_with(:import) do |config|
|
30
37
|
config.logging = true
|
38
|
+
config.pass_filename = true
|
31
39
|
end
|
32
40
|
|
33
41
|
# Optional:
|
@@ -72,11 +80,13 @@ our mapping key and then provide that field on each record in our data,
|
|
72
80
|
allowing us to update existing records with matching emails.
|
73
81
|
|
74
82
|
Using a csv formatted example:
|
83
|
+
|
75
84
|
```
|
76
85
|
Email,First name,Last name
|
77
86
|
peter.gibbons@initech.com,Peter,Gibbons
|
78
87
|
michael.bolton@initech.com,Michael,Bolton
|
79
88
|
```
|
89
|
+
|
80
90
|
would look for existing users with those emails. If one was found, its name
|
81
91
|
fields would be updated. Otherwise, a new one would be created.
|
82
92
|
|
@@ -91,17 +101,19 @@ a user record would have one or more fields named "Book" that include each
|
|
91
101
|
associated book's ISBN.
|
92
102
|
|
93
103
|
Again using a csv formatted example:
|
104
|
+
|
94
105
|
```
|
95
106
|
Email, Book, Book, Book
|
96
107
|
peter.gibbons@initech.com, 9781119997870, 9780671027032
|
97
108
|
michael.bolton@initech.com, 9780446677479
|
98
109
|
```
|
110
|
+
|
99
111
|
would look up books with those ISBNs and attach them to those users.
|
100
112
|
|
101
113
|
Mapping keys can be selected on the import page. Their defaults can also be
|
102
114
|
globally configured in the config file:
|
103
115
|
|
104
|
-
```
|
116
|
+
```ruby
|
105
117
|
RailsAdmin.config do |config|
|
106
118
|
config.model 'User' do
|
107
119
|
import do
|
@@ -128,7 +140,7 @@ existed through an intermediary model called `ServiceProvider`, we could
|
|
128
140
|
provide a `user_email` field in our records and handle the actual
|
129
141
|
association with an import hook:
|
130
142
|
|
131
|
-
```
|
143
|
+
```ruby
|
132
144
|
class Service < ActiveRecord::Base
|
133
145
|
belongs_to :service_provider
|
134
146
|
has_one :user, through: :service_provider
|
@@ -193,11 +205,10 @@ RailsAdmin.config do |config|
|
|
193
205
|
config.logging = false
|
194
206
|
config.line_item_limit = 1000
|
195
207
|
config.update_if_exists = false
|
208
|
+
config.pass_filename = false
|
196
209
|
config.rollback_on_error = false
|
197
210
|
config.header_converter = lambda do |header|
|
198
|
-
|
199
|
-
next if header.blank?
|
200
|
-
header.parameterize.underscore
|
211
|
+
header.parameterize.underscore if header.present?
|
201
212
|
end
|
202
213
|
config.csv_options = {}
|
203
214
|
end
|
@@ -215,6 +226,7 @@ end
|
|
215
226
|
* __header_converter__ (default `lambda { ... }`): a lambda to convert each CSV header text string to a model attribute name. The default header converter converts to lowercase and replaces spaces with underscores.
|
216
227
|
|
217
228
|
* __csv_options__ (default `{}`): a hash of options that will be passed to a new [CSV](http://ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html) instance
|
229
|
+
* __pass_filename__ (default `false`): Access the uploaded file name in your model actions, for example if set to true, inside each record, there will be an addtional property `record[:filename_importer]` which contains the file name of the currently uploaded file.
|
218
230
|
|
219
231
|
### Model-specific configuration
|
220
232
|
|
@@ -346,7 +358,7 @@ For example, you could
|
|
346
358
|
|
347
359
|
* Import an image into Carrierwave via a URL provided in the CSV.
|
348
360
|
|
349
|
-
```
|
361
|
+
```ruby
|
350
362
|
def before_import_save(record)
|
351
363
|
self.remote_image_url = record[:image] if record[:image].present?
|
352
364
|
end
|
@@ -354,7 +366,7 @@ end
|
|
354
366
|
|
355
367
|
* Skip some validations when importing.
|
356
368
|
|
357
|
-
```
|
369
|
+
```ruby
|
358
370
|
class User < ActiveRecord::Base
|
359
371
|
# Non-persistent attribute to allow creating a new user without a password
|
360
372
|
# Password will be set by the user by following a link in the invitation email
|
@@ -388,25 +400,36 @@ Since the import functionality is rarely used in many applications, some gems ar
|
|
388
400
|
|
389
401
|
If you prefer to eager load all dependecies at boot, use this line in your `Gemfile`.
|
390
402
|
|
391
|
-
```
|
392
|
-
gem "rails_admin_import", "~>
|
403
|
+
```ruby
|
404
|
+
gem "rails_admin_import", "~> 3.0", require: "rails_admin_import/eager_load"
|
393
405
|
```
|
394
406
|
|
395
407
|
## Import error due to Rails class reloading
|
396
408
|
|
409
|
+
![error due to class reloading](https://user-images.githubusercontent.com/2566348/51355874-0f83ad00-1a7e-11e9-8e58-46bc4699f2e6.jpg)
|
410
|
+
|
397
411
|
If you get an error like `Error during import: MyModel(#70286054976500) expected, got MyModel(#70286114743280)`, you need restart the rails server and redo the import. This is due to the fact that Rails reloads the ActiveRecord model classes in development when you make changes to them and Rails Admin is still using the old class.
|
398
412
|
|
413
|
+
Another suggestion is to set `config.cache_classes = true` to true in your `development.rb` for Rails Admin Import to work around the ActiveRecord model class reloading issue. See [this comment](https://github.com/stephskardal/rails_admin_import/issues/88#issuecomment-455374671) for more information.
|
414
|
+
|
399
415
|
## Customize the UI
|
400
416
|
|
401
|
-
If you want to hide all the advanced fields from the import UI, you can copy [`app/views/rails_admin/main/import.html.haml`](app/views/rails_admin/main/import.html.
|
417
|
+
If you want to hide all the advanced fields from the import UI, you can copy [`app/views/rails_admin/main/import.html.haml`](app/views/rails_admin/main/import.html.erb) to your project at the same path. Add `hidden` class to elements you want to hide.
|
402
418
|
|
403
419
|
For example:
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
420
|
+
|
421
|
+
```erb
|
422
|
+
<div class="form-group control-group hidden">
|
423
|
+
<label class="col-sm-2 control-label">
|
424
|
+
<%= t("admin.import.update_if_exists") %>
|
425
|
+
</label>
|
426
|
+
<div class="col-sm-10 controls">
|
427
|
+
<%= check_box_tag :update_if_exists, '1', RailsAdminImport.config.update_if_exists, :class => "form-control" %>
|
428
|
+
<p class="help-block">
|
429
|
+
<%= t('admin.import.help.update_if_exists') %>
|
430
|
+
</p>
|
431
|
+
</div>
|
432
|
+
</div>
|
410
433
|
```
|
411
434
|
|
412
435
|
## Upgrading
|
@@ -431,6 +454,8 @@ For example:
|
|
431
454
|
|
432
455
|
* [Japanese translation](https://gist.github.com/higumachan/c4bf669d6446ec509386229f916ba5fc) by Yuta Hinokuma
|
433
456
|
|
457
|
+
* [Brazilian Portuguese translation](https://gist.github.com/tteurs/5a87ff4bc5f24692dab05b3cde0ca9df) by Matheo Gracia Pegoraro
|
458
|
+
|
434
459
|
## Run tests
|
435
460
|
|
436
461
|
1. Clone the repository to your machine
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<% if @results && @results[:success].any? %>
|
2
|
+
<div class="alert alert-success form-horizontal denser">
|
3
|
+
<fieldset>
|
4
|
+
<legend>
|
5
|
+
<i class="fas fa-chevron-right"></i>
|
6
|
+
<%= @results[:success_message] %>
|
7
|
+
</legend>
|
8
|
+
<ul class="control-group" style="display: none">
|
9
|
+
<% @results[:success].each do |message| %>
|
10
|
+
<li>
|
11
|
+
<%= message %>
|
12
|
+
</li>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
</fieldset>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<% if @results && @results[:error].any? %>
|
20
|
+
<div class="alert alert-danger form-horizontal denser">
|
21
|
+
<fieldset>
|
22
|
+
<legend>
|
23
|
+
<i class="fas fa-chevron-down"></i>
|
24
|
+
<%= @results[:error_message] %>
|
25
|
+
</legend>
|
26
|
+
<ul class="control-group">
|
27
|
+
<% @results[:error].each do |message| %>
|
28
|
+
<li>
|
29
|
+
<%= message %>
|
30
|
+
</li>
|
31
|
+
<% end %>
|
32
|
+
</ul>
|
33
|
+
</fieldset>
|
34
|
+
</div>
|
35
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<% if fields.any? %>
|
2
|
+
<div class="form-group control-group">
|
3
|
+
<label class="col-sm-2 control-label">
|
4
|
+
<%= t("admin.import.#{section}") %>
|
5
|
+
</label>
|
6
|
+
<div class="col-sm-10 controls">
|
7
|
+
<ul class="list-unstyled">
|
8
|
+
<% fields.each do |field| %>
|
9
|
+
<li>
|
10
|
+
<label>
|
11
|
+
<%= field.label %>
|
12
|
+
</label>
|
13
|
+
</li>
|
14
|
+
<% end %>
|
15
|
+
</ul>
|
16
|
+
<p class="help-block">
|
17
|
+
<%= t("admin.import.help.#{section}") %>
|
18
|
+
</p>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
<% end %>
|
@@ -0,0 +1,102 @@
|
|
1
|
+
<%
|
2
|
+
translations = {
|
3
|
+
add: t('admin.import.enumeration.add'),
|
4
|
+
chooseAll: t('admin.import.enumeration.choose_all'),
|
5
|
+
clearAll: t('admin.import.enumeration.clear_all'),
|
6
|
+
down: t('admin.import.enumeration.down'),
|
7
|
+
remove: t('admin.import.enumeration.remove'),
|
8
|
+
search: t('admin.import.enumeration.search'),
|
9
|
+
up: t('admin.import.enumeration.up')
|
10
|
+
}
|
11
|
+
%>
|
12
|
+
|
13
|
+
<%= render "results" %>
|
14
|
+
<%= form_tag import_path(@abstract_model), :multipart => true, class: 'form-horizontal denser' do %>
|
15
|
+
<input name="send_data" type="hidden" value="true">/</input>
|
16
|
+
<fieldset>
|
17
|
+
<legend>
|
18
|
+
<i class="fas fa-chevron-down"></i>
|
19
|
+
<%= t('admin.import.legend.fields') %>
|
20
|
+
</legend>
|
21
|
+
<%= render "section", section: "model_fields", fields: @import_model.model_fields %>
|
22
|
+
<%= render "section", section: "association_fields", fields: @import_model.association_fields %>
|
23
|
+
</fieldset>
|
24
|
+
<fieldset>
|
25
|
+
<legend>
|
26
|
+
<i class="fas fa-chevron-down"></i>
|
27
|
+
<%= t('admin.import.legend.upload') %>
|
28
|
+
</legend>
|
29
|
+
<div class="form-group control-group">
|
30
|
+
<label class="col-sm-2 control-label" for="file">
|
31
|
+
<%= t("admin.import.file") %>
|
32
|
+
</label>
|
33
|
+
<div class="col-sm-10 controls">
|
34
|
+
<%= file_field_tag :file, :class => "form-control" %>
|
35
|
+
<p class="help-block">
|
36
|
+
<%= t('admin.import.help.file_limit', limit: RailsAdminImport.config.line_item_limit) %>
|
37
|
+
</p>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
<div class="form-group control-group">
|
41
|
+
<label class="col-sm-2 control-label" for="encoding">
|
42
|
+
<%= t("admin.import.encoding") %>
|
43
|
+
</label>
|
44
|
+
<div class="col-sm-10 controls">
|
45
|
+
<%= select_tag 'encoding', options_for_select(Encoding.name_list.sort), include_blank: true, data: { enumeration: true, options: { regional: translations } } %>
|
46
|
+
<p class="help-block">
|
47
|
+
<%= t('admin.import.help.encoding', name: 'UTF-8') %>
|
48
|
+
</p>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
<div class="form-group control-group">
|
52
|
+
<label class="col-sm-2 control-label">
|
53
|
+
<%= t("admin.import.update_if_exists") %>
|
54
|
+
</label>
|
55
|
+
<div class="col-sm-10 controls">
|
56
|
+
<%= check_box_tag :update_if_exists, '1', RailsAdminImport.config.update_if_exists, :class => "form-control" %>
|
57
|
+
<p class="help-block">
|
58
|
+
<%= t('admin.import.help.update_if_exists') %>
|
59
|
+
</p>
|
60
|
+
</div>
|
61
|
+
</div>
|
62
|
+
<div class="form-group control-group">
|
63
|
+
<label class="col-sm-2 control-label" for="update_lookup">
|
64
|
+
<%= t("admin.import.update_lookup") %>
|
65
|
+
</label>
|
66
|
+
<div class="col-sm-10 controls">
|
67
|
+
<%= select_tag 'update_lookup', options_for_select(@import_model.update_lookup_field_names, Array.wrap(@import_model.config.mapping_key).map(&:to_s)), multiple: true, data: { enumeration: true, options: { regional: translations } } %>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
</fieldset>
|
71
|
+
<% unless @import_model.association_fields.empty? %>
|
72
|
+
<fieldset>
|
73
|
+
<legend>
|
74
|
+
<i class="fas fa-chevron-down"></i>
|
75
|
+
<%= t('admin.import.legend.mapping') %>
|
76
|
+
</legend>
|
77
|
+
<% @import_model.association_fields.each do |field| %>
|
78
|
+
<div class="form-group control-group">
|
79
|
+
<label class="col-sm-2 control-label">
|
80
|
+
<%= field.label %>
|
81
|
+
<%= t("admin.import.mapping") %>
|
82
|
+
</label>
|
83
|
+
<div class="col-sm-10 controls">
|
84
|
+
<%= select_tag "associations[#{field.name}]", options_for_select(@import_model.associated_model_fields(field), Array.wrap(@import_model.associated_config(field).mapping_key).first.to_s), data: { enumeration: true, options: { regional: translations } } %>
|
85
|
+
</div>
|
86
|
+
</div>
|
87
|
+
<% end %>
|
88
|
+
</fieldset>
|
89
|
+
<% end %>
|
90
|
+
<br/>
|
91
|
+
<div class="form-actions">
|
92
|
+
<input name="return_to" type="<%= :hidden %>" value="<%= (request.params[:return_to].presence || request.referer) %>"></input>
|
93
|
+
<button class="btn btn-primary" data_disable_with="Uploading..." name="commit" type="submit">
|
94
|
+
<i class="fas fa-check"></i>
|
95
|
+
<%= t("admin.form.save") %>
|
96
|
+
</button>
|
97
|
+
<button class="btn" name="_continue" type="submit">
|
98
|
+
<i class="fas fa-times"></i>
|
99
|
+
<%= t("admin.form.cancel") %>
|
100
|
+
</button>
|
101
|
+
</div>
|
102
|
+
<% end %>
|
@@ -1,50 +1,53 @@
|
|
1
|
-
|
2
1
|
en:
|
3
2
|
admin:
|
4
3
|
actions:
|
5
4
|
import:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
link:
|
10
|
-
|
11
|
-
|
5
|
+
breadcrumb: Import
|
6
|
+
bulk_link: Import
|
7
|
+
done: Imported
|
8
|
+
link: Import
|
9
|
+
menu: Import
|
10
|
+
title: Import
|
12
11
|
import:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
legend:
|
27
|
-
fields: "Fields to import"
|
28
|
-
upload: "Upload file"
|
29
|
-
mapping: "Related fields mapping"
|
30
|
-
import_success:
|
31
|
-
create: "Created %{name}"
|
32
|
-
update: "Updated %{name}"
|
33
|
-
import_error:
|
34
|
-
create: "Failed to create %{name}: %{error}"
|
35
|
-
update: "Failed to update %{name}: %{error}"
|
36
|
-
general: "Error during import: %{error}"
|
37
|
-
line_item_limit: "Please limit upload file to %{limit} line items."
|
38
|
-
old_import_hook: >
|
39
|
-
The import hook %{model}.%{method} should take only 1 argument.
|
40
|
-
Data may not imported correctly.
|
41
|
-
See Upgrading section readme in Rails Admin Import.
|
42
|
-
association_not_found: "Association not found. %{error}"
|
12
|
+
association_fields: Association fields
|
13
|
+
association_not_found: 'Association not found. %{error}'
|
14
|
+
encoding: Encoding
|
15
|
+
enumeration:
|
16
|
+
add: Add new
|
17
|
+
choose_all: Choose all
|
18
|
+
clear_all: Clear all
|
19
|
+
down: Down
|
20
|
+
remove: Remove
|
21
|
+
search: Search
|
22
|
+
up: Up
|
23
|
+
file: Data file
|
24
|
+
format: File format
|
43
25
|
help:
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
26
|
+
association_fields: |
|
27
|
+
These fields map to other tables in the database, lookup via attribute selected below. For "many" associations, you may include multiple columns with the same header in the CSV file.
|
28
|
+
encoding: Choose file encoding. Leave empty to auto-detect. Ignored for JSON.
|
29
|
+
file_limit: 'Please limit upload file to %{limit} line items.'
|
30
|
+
model_fields: The fields above may be included in the import file.
|
31
|
+
update_if_exists: Update records found with the lookup field below instead of creating new records
|
32
|
+
import_error:
|
33
|
+
create: 'Failed to create %{name}: %{error}'
|
34
|
+
general: 'Error during import: %{error}'
|
35
|
+
line_item_limit: 'Please limit upload file to %{limit} line items.'
|
36
|
+
old_import_hook: |
|
37
|
+
The import hook %{model}.%{method} should take only 1 argument. Data may not imported correctly. See Upgrading section readme in Rails Admin Import.
|
38
|
+
update: 'Failed to update %{name}: %{error}'
|
39
|
+
import_success:
|
40
|
+
create: 'Created %{name}'
|
41
|
+
update: 'Updated %{name}'
|
42
|
+
invalid_format: Invalid import format.
|
43
|
+
invalid_json: 'The JSON data should be an array of records or an object with a key ''%{root_key}'' set to an array of records'
|
44
|
+
legend:
|
45
|
+
fields: Fields to import
|
46
|
+
mapping: Related fields mapping
|
47
|
+
upload: Upload file
|
48
|
+
mapping: mapping
|
49
|
+
missing_file: You must select a file
|
50
|
+
missing_update_lookup: Your file must contain a column for the 'Update lookup field' you selected.
|
51
|
+
model_fields: Model fields
|
52
|
+
update_if_exists: Update if exists
|
53
|
+
update_lookup: Update lookup field(s)
|
@@ -9,6 +9,7 @@ module RailsAdminImport
|
|
9
9
|
attr_accessor :update_if_exists
|
10
10
|
attr_accessor :header_converter
|
11
11
|
attr_accessor :csv_options
|
12
|
+
attr_accessor :pass_filename
|
12
13
|
|
13
14
|
# Default is to downcase headers and add underscores to convert into attribute names
|
14
15
|
HEADER_CONVERTER = lambda do |header|
|
@@ -36,6 +37,7 @@ module RailsAdminImport
|
|
36
37
|
@rollback_on_error = false
|
37
38
|
@update_if_exists = false
|
38
39
|
@header_converter = HEADER_CONVERTER
|
40
|
+
@pass_filename = false
|
39
41
|
@csv_options = {}
|
40
42
|
end
|
41
43
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "csv"
|
2
|
+
require "charlock_holmes"
|
2
3
|
|
3
4
|
module RailsAdminImport
|
4
5
|
module Formats
|
@@ -16,7 +17,7 @@ module RailsAdminImport
|
|
16
17
|
|
17
18
|
# A method that yields a hash of attributes for each record to import
|
18
19
|
def each_record
|
19
|
-
CSV.foreach(filename, csv_options) do |row|
|
20
|
+
CSV.foreach(filename, **csv_options) do |row|
|
20
21
|
attr = convert_to_attributes(row)
|
21
22
|
yield attr unless attr.all? { |field, value| value.blank? }
|
22
23
|
end
|
@@ -53,9 +54,9 @@ module RailsAdminImport
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def detect_encoding
|
56
|
-
charset =
|
57
|
-
if charset[
|
58
|
-
from_encoding = charset[
|
57
|
+
charset = CharlockHolmes::EncodingDetector.detect File.read(filename)
|
58
|
+
if charset[:confidence] > 0.6
|
59
|
+
from_encoding = charset[:encoding]
|
59
60
|
from_encoding = "UTF-8" if from_encoding == "ascii"
|
60
61
|
end
|
61
62
|
from_encoding
|
@@ -70,6 +70,10 @@ module RailsAdminImport
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def import_record(record)
|
73
|
+
if params["file"] && RailsAdminImport.config.pass_filename
|
74
|
+
record.merge!({:filename_importer => params[:file].original_filename})
|
75
|
+
end
|
76
|
+
|
73
77
|
perform_model_callback(import_model.model, :before_import_find, record)
|
74
78
|
|
75
79
|
if update_lookup && !(update_lookup - record.keys).empty?
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_admin_import
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steph Skardal
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-01-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -31,28 +31,28 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.
|
34
|
+
version: 3.0.0.beta
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0.
|
41
|
+
version: 3.0.0.beta
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: charlock_holmes
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '0.7'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '0.7'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: simple_xlsx_reader
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -79,9 +79,9 @@ files:
|
|
79
79
|
- MIT-LICENSE
|
80
80
|
- README.md
|
81
81
|
- Rakefile
|
82
|
-
- app/views/rails_admin/main/_results.html.
|
83
|
-
- app/views/rails_admin/main/_section.html.
|
84
|
-
- app/views/rails_admin/main/import.html.
|
82
|
+
- app/views/rails_admin/main/_results.html.erb
|
83
|
+
- app/views/rails_admin/main/_section.html.erb
|
84
|
+
- app/views/rails_admin/main/import.html.erb
|
85
85
|
- config/locales/README.md
|
86
86
|
- config/locales/import.en.yml
|
87
87
|
- lib/rails_admin_import.rb
|
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
122
|
version: '0'
|
123
123
|
requirements: []
|
124
124
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.
|
125
|
+
rubygems_version: 2.7.6
|
126
126
|
signing_key:
|
127
127
|
specification_version: 4
|
128
128
|
summary: Import functionality for Rails Admin
|
@@ -1,18 +0,0 @@
|
|
1
|
-
- if @results && @results[:success].any?
|
2
|
-
.alert.alert-success.form-horizontal.denser
|
3
|
-
%fieldset
|
4
|
-
%legend
|
5
|
-
%i.icon-chevron-right
|
6
|
-
= @results[:success_message]
|
7
|
-
%ul.control-group{style: 'display: none'}
|
8
|
-
- @results[:success].each do |message|
|
9
|
-
%li= message
|
10
|
-
- if @results && @results[:error].any?
|
11
|
-
.alert.alert-danger.form-horizontal.denser
|
12
|
-
%fieldset
|
13
|
-
%legend
|
14
|
-
%i.icon-chevron-down
|
15
|
-
= @results[:error_message]
|
16
|
-
%ul.control-group
|
17
|
-
- @results[:error].each do |message|
|
18
|
-
%li= message
|
@@ -1,10 +0,0 @@
|
|
1
|
-
- if fields.any?
|
2
|
-
.form-group.control-group
|
3
|
-
%label.col-sm-2.control-label= t("admin.import.#{section}")
|
4
|
-
.col-sm-10.controls
|
5
|
-
%ul.list-unstyled
|
6
|
-
- fields.each do |field|
|
7
|
-
%li
|
8
|
-
%label= capitalize_first_letter(field.label)
|
9
|
-
%p.help-block= t("admin.import.help.#{section}")
|
10
|
-
|
@@ -1,69 +0,0 @@
|
|
1
|
-
= render "results"
|
2
|
-
|
3
|
-
= form_tag import_path(@abstract_model), :multipart => true, class: 'form-horizontal denser' do
|
4
|
-
|
5
|
-
%input{name: "send_data", type: "hidden", value: "true"}/
|
6
|
-
%fieldset
|
7
|
-
%legend
|
8
|
-
%i.icon-chevron-down
|
9
|
-
= t('admin.import.legend.fields')
|
10
|
-
|
11
|
-
= render "section", section: "model_fields", fields: @import_model.model_fields
|
12
|
-
= render "section", section: "association_fields", fields: @import_model.association_fields
|
13
|
-
|
14
|
-
%fieldset
|
15
|
-
%legend
|
16
|
-
%i.icon-chevron-down
|
17
|
-
= t('admin.import.legend.upload')
|
18
|
-
.form-group.control-group
|
19
|
-
%label.col-sm-2.control-label{for: "file"}= t("admin.import.file")
|
20
|
-
.col-sm-10.controls
|
21
|
-
= file_field_tag :file, :class => "form-control"
|
22
|
-
%p.help-block= t('admin.import.help.file_limit', limit: RailsAdminImport.config.line_item_limit)
|
23
|
-
.form-group.control-group
|
24
|
-
%label.col-sm-2.control-label{for: "encoding"}= t("admin.import.encoding")
|
25
|
-
.col-sm-10.controls
|
26
|
-
= select_tag 'encoding',
|
27
|
-
options_for_select(Encoding.name_list.sort),
|
28
|
-
include_blank: true, data: { enumeration: true }
|
29
|
-
%p.help-block= t('admin.import.help.encoding', name: 'UTF-8')
|
30
|
-
.form-group.control-group
|
31
|
-
%label.col-sm-2.control-label= t("admin.import.update_if_exists")
|
32
|
-
.col-sm-10.controls
|
33
|
-
= check_box_tag :update_if_exists, '1', RailsAdminImport.config.update_if_exists, :class => "form-control"
|
34
|
-
%p.help-block= t('admin.import.help.update_if_exists')
|
35
|
-
.form-group.control-group
|
36
|
-
%label.col-sm-2.control-label{for: "update_lookup"}= t("admin.import.update_lookup")
|
37
|
-
.col-sm-10.controls
|
38
|
-
= select_tag 'update_lookup',
|
39
|
-
options_for_select(@import_model.update_lookup_field_names,
|
40
|
-
Array.wrap(@import_model.config.mapping_key).map(&:to_s)),
|
41
|
-
multiple: true,
|
42
|
-
data: { enumeration: true }
|
43
|
-
|
44
|
-
- unless @import_model.association_fields.empty?
|
45
|
-
%fieldset
|
46
|
-
%legend
|
47
|
-
%i.icon-chevron-down
|
48
|
-
= t('admin.import.legend.mapping')
|
49
|
-
|
50
|
-
- @import_model.association_fields.each do |field|
|
51
|
-
.form-group.control-group
|
52
|
-
%label.col-sm-2.control-label
|
53
|
-
= capitalize_first_letter(field.label)
|
54
|
-
= t("admin.import.mapping")
|
55
|
-
.col-sm-10.controls
|
56
|
-
= select_tag "associations[#{field.name}]",
|
57
|
-
options_for_select(@import_model.associated_model_fields(field),
|
58
|
-
Array.wrap(@import_model.associated_config(field).mapping_key).first.to_s),
|
59
|
-
data: { enumeration: true }
|
60
|
-
|
61
|
-
%br
|
62
|
-
.form-actions
|
63
|
-
%input{type: :hidden, name: 'return_to', value: (request.params[:return_to].presence || request.referer)}
|
64
|
-
%button.btn.btn-primary{type: "submit", name: "commit", data: {disable_with: "Uploading..."} }
|
65
|
-
%i.icon-white.icon-ok
|
66
|
-
= t("admin.form.save")
|
67
|
-
%button.btn{type: "submit", name: "_continue"}
|
68
|
-
%i.icon-remove
|
69
|
-
= t("admin.form.cancel")
|