rails_admin_import 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/README.md +24 -7
- data/Rakefile +2 -2
- data/app/views/rails_admin/main/import.html.haml +1 -7
- data/lib/rails_admin_import/action.rb +2 -1
- data/lib/rails_admin_import/config.rb +6 -1
- data/lib/rails_admin_import/eager_load.rb +3 -0
- data/lib/rails_admin_import/formats.rb +6 -0
- data/lib/rails_admin_import/formats/csv_importer.rb +2 -6
- data/lib/rails_admin_import/formats/xlsx_importer.rb +48 -0
- data/lib/rails_admin_import/import_model.rb +17 -7
- data/lib/rails_admin_import/importer.rb +6 -6
- data/lib/rails_admin_import/version.rb +1 -1
- metadata +32 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d22596961dbc1568f035e4f5c6e5896fcfb01474
|
4
|
+
data.tar.gz: 407a068d2bf2d62e096ec46c4c061b559db98bec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1d2338cbf97015e11c114b1ee6d68994c8517942497ce839f029ac02e36d133f8bd9866634e23e5e2825d9a88033c25e5508016a209f39d48d593edcf2c376f
|
7
|
+
data.tar.gz: 82fa136b73f126c8dcabaa7e83e472b0815b0231286d505be16718c15a7b8f9aa425fee723e67424419dd5e94a51182adbd6133238f4382b2d4f36df5ce96f80
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [1.2.0] - 2015-08-27
|
4
|
+
### Changed
|
5
|
+
- Existing records can now be updated based on a belongs_to foreign key. Thanks Diego Carrion!
|
6
|
+
- Add Excel file format support
|
7
|
+
- Autoload the Excel import and encoding detection gems
|
8
|
+
|
3
9
|
## [1.1.0] - 2015-08-04
|
4
10
|
### Changed
|
5
11
|
- `csv_options` config added. Thanks Maksim Burnin!
|
@@ -23,4 +29,4 @@ Major rework of the gem by new maintainer.
|
|
23
29
|
- Updated/corrected README
|
24
30
|
- Merged ImportLogger work
|
25
31
|
- Merged modifications to import view
|
26
|
-
- Merged post save hook on models
|
32
|
+
- Merged post save hook on models
|
data/README.md
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/monkbroc/rails_admin_import)
|
4
4
|
|
5
|
-
Plugin functionality to add generic import to Rails Admin from CSV and
|
5
|
+
Plugin functionality to add generic import to Rails Admin from CSV, JSON and XLSX files
|
6
6
|
|
7
|
-
*This Readme is for version 1.
|
7
|
+
*This Readme is for version 1.x. If you are still using version 0.1.x, see [this branch](https://github.com/stephskardal/rails_admin_import/tree/legacy)*
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
11
11
|
* First, add to Gemfile:
|
12
12
|
|
13
13
|
```
|
14
|
-
gem "rails_admin_import", "~> 1.
|
14
|
+
gem "rails_admin_import", "~> 1.2"
|
15
15
|
```
|
16
16
|
|
17
17
|
* Define configuration in `config/initializers/rails_admin_import.rb`:
|
@@ -52,6 +52,8 @@ can :import, [User, Model1, Model2]
|
|
52
52
|
|
53
53
|
## File format
|
54
54
|
|
55
|
+
The format is inferred by the extension (.csv, .json or .xlsx).
|
56
|
+
|
55
57
|
### CSV
|
56
58
|
|
57
59
|
The first line must contain attribute names. They will be converted to lowercase and underscored (First Name ==> first_name).
|
@@ -72,6 +74,11 @@ Michael,Bolton,IT,
|
|
72
74
|
|
73
75
|
The file must be an array or an object with a root key the same name as the plural model name, i.e. the default Rails JSON output format with include_root_in_json on or off.
|
74
76
|
|
77
|
+
### XLSX
|
78
|
+
|
79
|
+
The Microsoft Excel XLM format (XLSX) is supported, but not the old binary Microsoft Excel format (XLS).
|
80
|
+
|
81
|
+
The expected rows and columns are the same as for the CSV format (first line contains headers, multiple columns for "many" associations).
|
75
82
|
|
76
83
|
## Configuration
|
77
84
|
|
@@ -83,7 +90,7 @@ The file must be an array or an object with a root key the same name as the plur
|
|
83
90
|
|
84
91
|
* __rollback_on_error__ (default `false`): import records in a transaction and rollback if there is one error. Only for ActiveRecord, not Mongoid.
|
85
92
|
|
86
|
-
* __header_converter__ (default `
|
93
|
+
* __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.
|
87
94
|
|
88
95
|
* __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
|
89
96
|
|
@@ -175,6 +182,16 @@ The gem is tested to work with ActiveRecord and Mongoid.
|
|
175
182
|
Support for Mongoid is early, so if you can suggest improvements (especially around importing embedded models), open an issue.
|
176
183
|
|
177
184
|
|
185
|
+
## Eager loading
|
186
|
+
|
187
|
+
Since the import functionality is rarely used in many applications, some gems are autoloaded when first used during an import in order to save memory at boot.
|
188
|
+
|
189
|
+
If you prefer to eager load all dependecies at boot, use this line in your `Gemfile`.
|
190
|
+
|
191
|
+
```
|
192
|
+
gem "rails_admin_import", "~> 1.2.0", require: "rails_admin_import/eager_load"
|
193
|
+
```
|
194
|
+
|
178
195
|
## Upgrading
|
179
196
|
|
180
197
|
* Move global config to `config.configure_with(:import)` in `config/initializers/rails_admin_import.rb`.
|
@@ -194,7 +211,7 @@ Support for Mongoid is early, so if you can suggest improvements (especially aro
|
|
194
211
|
git clone https://github.com/stephskardal/rails_admin_import
|
195
212
|
|
196
213
|
2. Run `bundle install`
|
197
|
-
3. Run `rspec`
|
214
|
+
3. Run `bundle exec rspec`
|
198
215
|
|
199
216
|
The structure of the tests is taken from the Rails Admin gem.
|
200
217
|
|
@@ -209,8 +226,8 @@ Maintainer (since May 2015): [Julien Vanier](https://github.com/monkbroc)
|
|
209
226
|
|
210
227
|
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
211
228
|
|
212
|
-
- [Report bugs](https://github.com/
|
213
|
-
- Fix bugs and [submit pull requests](https://github.com/
|
229
|
+
- [Report bugs](https://github.com/stephskardal/rails_admin_import/issues)
|
230
|
+
- Fix bugs and [submit pull requests](https://github.com/stephskardal/rails_admin_import/pulls)
|
214
231
|
- Write, clarify, or fix documentation
|
215
232
|
- Suggest or add new features
|
216
233
|
|
data/Rakefile
CHANGED
@@ -20,12 +20,6 @@
|
|
20
20
|
.col-sm-10.controls
|
21
21
|
= file_field_tag :file, :class => "form-control"
|
22
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: "import_format"}= t("admin.import.format")
|
25
|
-
.col-sm-10.controls
|
26
|
-
= select_tag 'import_format',
|
27
|
-
options_for_select(RailsAdminImport::Formats.all),
|
28
|
-
data: { enumeration: true }
|
29
23
|
.form-group.control-group
|
30
24
|
%label.col-sm-2.control-label{for: "encoding"}= t("admin.import.encoding")
|
31
25
|
.col-sm-10.controls
|
@@ -42,7 +36,7 @@
|
|
42
36
|
%label.col-sm-2.control-label{for: "update_lookup"}= t("admin.import.update_lookup")
|
43
37
|
.col-sm-10.controls
|
44
38
|
= select_tag 'update_lookup',
|
45
|
-
options_for_select(@import_model.
|
39
|
+
options_for_select(@import_model.update_lookup_field_names,
|
46
40
|
@import_model.config.mapping_key.to_s), data: { enumeration: true }
|
47
41
|
|
48
42
|
- unless @import_model.association_fields.empty?
|
@@ -19,8 +19,9 @@ module RailsAdmin
|
|
19
19
|
@import_model = RailsAdminImport::ImportModel.new(@abstract_model)
|
20
20
|
|
21
21
|
if request.post?
|
22
|
+
format = RailsAdminImport::Formats.from_file(params[:file])
|
22
23
|
record_importer = RailsAdminImport::Formats.for(
|
23
|
-
|
24
|
+
format, @import_model, params)
|
24
25
|
|
25
26
|
if record_importer.valid?
|
26
27
|
importer = RailsAdminImport::Importer.new(
|
@@ -9,6 +9,11 @@ module RailsAdminImport
|
|
9
9
|
attr_accessor :header_converter
|
10
10
|
attr_accessor :csv_options
|
11
11
|
|
12
|
+
# Default is to downcase headers and add underscores to convert into attribute names
|
13
|
+
HEADER_CONVERTER = lambda do |header|
|
14
|
+
header.parameterize.underscore
|
15
|
+
end
|
16
|
+
|
12
17
|
def model(model_name, &block)
|
13
18
|
unless @deprecation_shown
|
14
19
|
warn "RailsAdminImport::Config#model is deprecated. " \
|
@@ -26,7 +31,7 @@ module RailsAdminImport
|
|
26
31
|
@logging = false
|
27
32
|
@line_item_limit = 1000
|
28
33
|
@rollback_on_error = false
|
29
|
-
@header_converter =
|
34
|
+
@header_converter = HEADER_CONVERTER
|
30
35
|
@csv_options = {}
|
31
36
|
end
|
32
37
|
end
|
@@ -5,6 +5,11 @@ module RailsAdminImport
|
|
5
5
|
@registry[format.to_s] = klass
|
6
6
|
end
|
7
7
|
|
8
|
+
def from_file(file)
|
9
|
+
return unless file
|
10
|
+
File.extname(file.original_filename).sub(/^\./, '')
|
11
|
+
end
|
12
|
+
|
8
13
|
def for(format, *args)
|
9
14
|
@registry.fetch(format.to_s, DummyImporter).new(*args)
|
10
15
|
end
|
@@ -26,3 +31,4 @@ require "rails_admin_import/formats/dummy_importer"
|
|
26
31
|
require "rails_admin_import/formats/file_importer"
|
27
32
|
require "rails_admin_import/formats/csv_importer"
|
28
33
|
require "rails_admin_import/formats/json_importer"
|
34
|
+
require "rails_admin_import/formats/xlsx_importer"
|
@@ -1,20 +1,16 @@
|
|
1
1
|
require "csv"
|
2
|
-
require "rchardet"
|
3
2
|
|
4
3
|
module RailsAdminImport
|
5
4
|
module Formats
|
6
5
|
class CSVImporter < FileImporter
|
7
6
|
Formats.register(:csv, self)
|
8
7
|
|
9
|
-
|
10
|
-
HEADER_CONVERTER = lambda do |header|
|
11
|
-
header.parameterize.underscore
|
12
|
-
end
|
8
|
+
autoload :CharDet, "rchardet"
|
13
9
|
|
14
10
|
def initialize(import_model, params)
|
15
11
|
super
|
16
12
|
@encoding = params[:encoding]
|
17
|
-
@header_converter = RailsAdminImport.config.header_converter
|
13
|
+
@header_converter = RailsAdminImport.config.header_converter
|
18
14
|
end
|
19
15
|
|
20
16
|
# A method that yields a hash of attributes for each record to import
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "csv"
|
2
|
+
|
3
|
+
module RailsAdminImport
|
4
|
+
module Formats
|
5
|
+
class XLSXImporter < FileImporter
|
6
|
+
Formats.register(:xlsx, self)
|
7
|
+
|
8
|
+
autoload :SimpleXlsxReader, "simple_xlsx_reader"
|
9
|
+
|
10
|
+
def initialize(import_model, params)
|
11
|
+
super
|
12
|
+
@header_converter = RailsAdminImport.config.header_converter
|
13
|
+
end
|
14
|
+
|
15
|
+
# A method that yields a hash of attributes for each record to import
|
16
|
+
def each_record
|
17
|
+
doc = SimpleXlsxReader.open(filename)
|
18
|
+
sheet = doc.sheets.first
|
19
|
+
@headers = convert_headers(sheet.headers)
|
20
|
+
sheet.data.each do |row|
|
21
|
+
yield convert_to_attributes(row)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def convert_headers(headers)
|
28
|
+
headers.map do |h|
|
29
|
+
@header_converter.call(h || "")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def convert_to_attributes(row)
|
34
|
+
row_with_headers = @headers.zip(row)
|
35
|
+
row_with_headers.each_with_object({}) do |(field, value), record|
|
36
|
+
break if field.nil?
|
37
|
+
field = field.to_sym
|
38
|
+
if import_model.has_multiple_values?(field)
|
39
|
+
field = import_model.pluralize_field(field)
|
40
|
+
(record[field] ||= []) << value
|
41
|
+
else
|
42
|
+
record[field] = value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -44,18 +44,28 @@ module RailsAdminImport
|
|
44
44
|
}
|
45
45
|
end
|
46
46
|
|
47
|
-
def
|
48
|
-
@
|
47
|
+
def single_association_fields
|
48
|
+
@single_association_fields ||= association_fields.select { |f|
|
49
49
|
!f.multiple?
|
50
50
|
}
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
54
|
-
@
|
55
|
-
|
53
|
+
def belongs_to_fields
|
54
|
+
@belongs_to_fields ||= single_association_fields.select { |f|
|
55
|
+
f.type == :belongs_to_association
|
56
56
|
}
|
57
57
|
end
|
58
58
|
|
59
|
+
def many_association_fields
|
60
|
+
@many_association_fields ||= association_fields.select { |f|
|
61
|
+
f.multiple?
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def update_lookup_field_names
|
66
|
+
@update_lookup_field_names ||= model_fields.map(&:name) + belongs_to_fields.map(&:foreign_key)
|
67
|
+
end
|
68
|
+
|
59
69
|
def associated_object(field, mapping_field, value)
|
60
70
|
klass = association_class(field)
|
61
71
|
klass.where(mapping_field => value).first or
|
@@ -79,11 +89,11 @@ module RailsAdminImport
|
|
79
89
|
|
80
90
|
def has_multiple_values?(field_name)
|
81
91
|
plural_name = pluralize_field(field_name)
|
82
|
-
|
92
|
+
many_association_fields.any? { |field| field.name == field_name || field.name == plural_name }
|
83
93
|
end
|
84
94
|
|
85
95
|
def pluralize_field(field_name)
|
86
|
-
@plural_fields ||=
|
96
|
+
@plural_fields ||= many_association_fields.map(&:name).each_with_object({}) { |name, h|
|
87
97
|
h[name.to_s.singularize.to_sym] = name
|
88
98
|
}
|
89
99
|
@plural_fields[field_name] || field_name
|
@@ -70,8 +70,8 @@ module RailsAdminImport
|
|
70
70
|
action = object.new_record? ? :create : :update
|
71
71
|
|
72
72
|
begin
|
73
|
-
|
74
|
-
|
73
|
+
import_single_association_data(object, record)
|
74
|
+
import_many_association_data(object, record)
|
75
75
|
rescue AssociationNotFound => e
|
76
76
|
error = I18n.t("admin.import.association_not_found", :error => e.to_s)
|
77
77
|
report_error(object, action, error)
|
@@ -185,8 +185,8 @@ module RailsAdminImport
|
|
185
185
|
object
|
186
186
|
end
|
187
187
|
|
188
|
-
def
|
189
|
-
import_model.
|
188
|
+
def import_single_association_data(object, record)
|
189
|
+
import_model.single_association_fields.each do |field|
|
190
190
|
mapping_key = params[:associations][field.name]
|
191
191
|
value = extract_mapping(record[field.name], mapping_key)
|
192
192
|
|
@@ -196,8 +196,8 @@ module RailsAdminImport
|
|
196
196
|
end
|
197
197
|
end
|
198
198
|
|
199
|
-
def
|
200
|
-
import_model.
|
199
|
+
def import_many_association_data(object, record)
|
200
|
+
import_model.many_association_fields.each do |field|
|
201
201
|
if record.has_key? field.name
|
202
202
|
mapping_key = params[:associations][field.name]
|
203
203
|
values = record[field.name].reject { |value| value.blank? }.map { |value|
|
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: 1.
|
4
|
+
version: 1.2.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: 2015-08-
|
12
|
+
date: 2015-08-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -67,6 +67,34 @@ dependencies:
|
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '1.6'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: simple_xlsx_reader
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '1.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rubygems-tasks
|
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'
|
70
98
|
description:
|
71
99
|
email:
|
72
100
|
- steph@endpoint.com
|
@@ -88,12 +116,14 @@ files:
|
|
88
116
|
- lib/rails_admin_import/config.rb
|
89
117
|
- lib/rails_admin_import/config/legacy_model.rb
|
90
118
|
- lib/rails_admin_import/config/sections/import.rb
|
119
|
+
- lib/rails_admin_import/eager_load.rb
|
91
120
|
- lib/rails_admin_import/engine.rb
|
92
121
|
- lib/rails_admin_import/formats.rb
|
93
122
|
- lib/rails_admin_import/formats/csv_importer.rb
|
94
123
|
- lib/rails_admin_import/formats/dummy_importer.rb
|
95
124
|
- lib/rails_admin_import/formats/file_importer.rb
|
96
125
|
- lib/rails_admin_import/formats/json_importer.rb
|
126
|
+
- lib/rails_admin_import/formats/xlsx_importer.rb
|
97
127
|
- lib/rails_admin_import/import_logger.rb
|
98
128
|
- lib/rails_admin_import/import_model.rb
|
99
129
|
- lib/rails_admin_import/importer.rb
|
@@ -124,4 +154,3 @@ signing_key:
|
|
124
154
|
specification_version: 4
|
125
155
|
summary: Import functionality for Rails Admin
|
126
156
|
test_files: []
|
127
|
-
has_rdoc:
|