csv_step_importer 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 930cc2407877056e544604dab4c86d885349db9206e217e6518ccddda4969a06
4
- data.tar.gz: 2e2a217f8832430d9365018bfb0c9b99fa6f28787a25230748c74890d0efa5b3
3
+ metadata.gz: a36a92f9240a933980983aff9d079724cc44882cd914ed2d6c2b51c1fbb47cca
4
+ data.tar.gz: 57dbea48c65e11867605da9621029b5da65d6700ffda0f092dfbe0c00e5b2858
5
5
  SHA512:
6
- metadata.gz: 596bd1bce8110e37d1ab496cb75a2469d2e0bc438ecf2389764b28f82e940003cf10a4e296c28ef6e4a36d30dbf835023d23793b70fdea59a64b1d2d4e774a0a
7
- data.tar.gz: 1e296ae4f9c321f90f129eedaa4a26a55e8b5d472239d2d9061a639bec184a39162e5bf9277be66f8f754fb0e8a6e5e0d6853efe7ce555f43744b58436ae6135
6
+ metadata.gz: 15157867c54bdd4d7868901c353667775f24a9b9ae5a34cc98659184bb52d0119f923cfa4577a4e6385b440da810c2fca4ba03ae2c1bce35cdf07d70045c6b98
7
+ data.tar.gz: 94f5eebbdc2fac03edcf0a18d3727bc0681f062a8f2cc631f201a8c2e94a2b97460fdb8370615f8dc262ae7e152de58dec77772a13a36ebe4685fd1cd02a0793
data/CHANGELOG.md CHANGED
@@ -86,3 +86,46 @@ See lib/csv_step_importer/file.rb for more options
86
86
 
87
87
  - Changed README, especially a note to include smarter_csv 2.0.0.pre1 into your project
88
88
  - Chunks default for the first row index is now 0
89
+
90
+ ## 2018-09-11 Version 0.11.0
91
+ ### Added
92
+ - Added methods to DAO
93
+ - dao_for(model:, pluralize: false)
94
+ retrieve a dao for a different model using the same CSV row. This is useful e.g. if you use the reflector to get ids of related data
95
+ - link!
96
+ link this dao to a row
97
+ - unlink!
98
+ unlink this dao from the row and replace it with a different dao
99
+ - Model allows now to specify a unique composite key `composite_key_columns` to avoid duplicated daos.
100
+
101
+ Usage:
102
+
103
+ ```ruby
104
+ class Author < ApplicationRecord
105
+ class ImportableModel < CSVStepImporter::Model::ImportableModel
106
+ def composite_key_columns
107
+ [:name]
108
+ end
109
+ end
110
+ end
111
+ ```
112
+
113
+ And a CSV which contains the same name twice or more, like this:
114
+
115
+ ```csv
116
+ Author,Book
117
+ A1,B1
118
+ A1,B2
119
+ A2,B3
120
+ ```
121
+
122
+ If you do NOT specify `composite_key_columns` you will get three DAOs for A1, A1 and A2.
123
+ If you specify `composite_key_columns` non unique daos will be removed and you only will get A1 and A2.
124
+
125
+ - The `Model`'s `cache_key` method allows now a `pluralize` option.
126
+ - The `Model`'s `cache_key` method is now available in the instance as well.
127
+
128
+ ### Changed
129
+
130
+ - ImportableModel's finder_keys method now defaults to composite_key_columns
131
+ - ImportableModel's Importer (uses ActiveRecord::Import) now raises an exception if the import fails
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- csv_step_importer (0.10.0)
4
+ csv_step_importer (0.11.0)
5
5
  activemodel
6
6
  activerecord-import
7
7
  activesupport
data/README.md CHANGED
@@ -53,14 +53,23 @@ class Author < ApplicationRecord
53
53
  class ImportableModel < CSVStepImporter::Model::ImportableModel
54
54
  # The model to be updated
55
55
  def model_class
56
- puts Module.nesting.inspect
57
56
  Module.nesting[1]
58
57
  end
59
58
 
59
+ # return CSVStepImporter::Model::Reflector in order to enable reflections (e.g. get ids of all rows)
60
+ # disabled by default
61
+ def reflector_class
62
+ CSVStepImporter::Model::Reflector
63
+ end
64
+
60
65
  def columns
61
66
  [:name, :email, :created_at, :updated_at]
62
67
  end
63
68
 
69
+ def composite_key_columns
70
+ [:name]
71
+ end
72
+
64
73
  def on_duplicate_key_update
65
74
  [:email, :updated_at]
66
75
  end
@@ -68,7 +77,7 @@ class Author < ApplicationRecord
68
77
  end
69
78
  ```
70
79
 
71
- ### Simple upload of a single row
80
+ ### Import a single data row
72
81
 
73
82
  ```shell
74
83
  rails c
@@ -116,7 +125,7 @@ irb(main)> puts JSON.parse(Author.all.to_json).to_yaml # Isn't there an easy way
116
125
  updated_at: '2018-09-11T12:19:17.000Z'
117
126
  ```
118
127
 
119
- ### File import using [tilo/smarter_csv](https://github.com/tilo/smarter_csv)
128
+ ### Import a CSV data file
120
129
 
121
130
  ```shell
122
131
  rails c
@@ -153,7 +162,7 @@ irb(main)> puts JSON.parse(Author.all.to_json).to_yaml
153
162
  ### Simple model
154
163
 
155
164
  By default, for each row read from the CSV file, a DAO belonging to a model will be created.
156
- These models will be validated and saved in the order specified by the processor_classes option.
165
+ These models will be validated and saved in the order specified by the `processor_classes` option.
157
166
 
158
167
  The simplest model is one, which simply calls `save` on all DAOs, which calls internally `create_or_update`.
159
168
  `create_or_update` is customizable.
@@ -165,7 +174,7 @@ This example will call `find_or_create_by` for each row after all validations ha
165
174
  ```ruby
166
175
  class SimpleDAO < CSVStepImporter::Model::DAO
167
176
  def create_or_update
168
- Currency.find_or_create_by( name: row.name, code: row.code )
177
+ Currency.find_or_create_by(name: row.name, code: row.code)
169
178
  end
170
179
  end
171
180
 
@@ -182,7 +191,7 @@ CSVStepImporter::Loader.new(path: 'currencies.csv', processor_classes: [SimpleMo
182
191
 
183
192
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
184
193
 
185
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
194
+ To install this gem onto your local machine, run `rake install`. To release a new version, update the version number in `version.rb`, and then run `rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
186
195
 
187
196
  ## Contributing
188
197
 
@@ -20,12 +20,14 @@ module CSVStepImporter
20
20
  parent.parent
21
21
  end
22
22
 
23
+ # returns an array of all column values, used for batch importing
23
24
  def value
24
25
  @value ||= columns.each_with_object({}) do |key, values|
25
26
  values[key] = value_for_key key
26
27
  end
27
28
  end
28
29
 
30
+ # retrieve a value for a key from the dao or row
29
31
  def value_for_key(key)
30
32
  if respond_to?(key)
31
33
  send key
@@ -41,7 +43,7 @@ module CSVStepImporter
41
43
  end
42
44
 
43
45
  def create_or_update
44
- # Daoの保存処理は基本的にstepsで行います
46
+ # DAOs are usually processed in batches by the model and not saved one by one
45
47
  true
46
48
  end
47
49
 
@@ -56,6 +58,32 @@ module CSVStepImporter
56
58
  def updated_at
57
59
  current_timestamp
58
60
  end
61
+
62
+ # retrieve a dao for a different model using the same CSV row. This is useful e.g. if you use the reflector to get ids of related data
63
+ def dao_for model:, pluralize: false
64
+ row.cache[model.cache_key(pluralize: pluralize)]
65
+ end
66
+
67
+ # link this dao to a row
68
+ def link!
69
+ # add to cache with pluralized key
70
+ (row.cache[model.cache_key(pluralize: true)] ||= []) << self
71
+
72
+ # add to cache with singular key (for convenience)
73
+ row.cache[model.cache_key(pluralize: false)] = self
74
+ end
75
+
76
+ # unlink this dao from the row and replace it with a different dao
77
+ def unlink! replace_with: nil
78
+ cached_daos = row.cache[model.cache_key(pluralize: true)]
79
+
80
+ # remove from cache with pluralized key
81
+ cached_daos.delete self
82
+ cached_daos << replace_with
83
+
84
+ # set any dao to cache with singular key (for convenience)
85
+ row.cache[model.cache_key(pluralize: false)] = cached_daos.first
86
+ end
59
87
  end
60
88
  end
61
89
  end
@@ -32,7 +32,7 @@ module CSVStepImporter
32
32
  # NOTE: required only when reflector class is set
33
33
  # example: [:email]
34
34
  def finder_keys
35
- raise "please extend and implement"
35
+ composite_key_columns || raise("please extend and implement")
36
36
  end
37
37
 
38
38
  # NOTE: required only when importer class is set
@@ -14,7 +14,7 @@ module CSVStepImporter
14
14
  delegate :dao_values, to: :parent
15
15
 
16
16
  def create_or_update
17
- model_class.import(
17
+ model_class.import!(
18
18
  columns,
19
19
  dao_values,
20
20
  on_duplicate_key_ignore: on_duplicate_key_ignore,
@@ -7,11 +7,13 @@ module CSVStepImporter
7
7
  class Model < CSVStepImporter::Node
8
8
  attr_accessor :dao_values
9
9
  delegate :rows, :cache, to: :parent
10
+ delegate :cache_key, to: :class
10
11
 
11
12
  def initialize(**attributes)
12
13
  super **attributes
13
14
 
14
15
  add_daos
16
+ filter_daos! if composite_key_columns
15
17
  add_model_children
16
18
  end
17
19
 
@@ -19,8 +21,9 @@ module CSVStepImporter
19
21
  # Configuration
20
22
  #########################################################
21
23
 
22
- def self.cache_key
23
- name.underscore.split("/").last.to_sym
24
+ def self.cache_key pluralize: false
25
+ key = name.underscore.gsub('/', '_')
26
+ (pluralize ? key.pluralize : key.singularize).to_sym
24
27
  end
25
28
 
26
29
  # example: [:email, :updated_at, :created_at]
@@ -32,6 +35,11 @@ module CSVStepImporter
32
35
  CSVStepImporter::Model::DAO
33
36
  end
34
37
 
38
+ # specify to an array of columns in order filter duplicates from daos
39
+ def composite_key_columns
40
+ nil
41
+ end
42
+
35
43
  #########################################################
36
44
  # Logic
37
45
  #########################################################
@@ -67,15 +75,24 @@ module CSVStepImporter
67
75
  dao_class.new parent: dao_node, row: row
68
76
  end
69
77
 
70
- def link_rows_to_daos(daos:)
71
- daos.each do |dao|
72
- # add to cache with pluralized key
73
- (dao.row.cache[self.class.cache_key.to_s.pluralize.to_sym] ||= []) << dao
78
+ # TODO a possible feature would be to add validation errors if the duplicates do not match in all columns (columns other than the composite key)
79
+ def filter_daos!
80
+ unique_daos = {}
81
+
82
+ daos.delete_if do |dao|
83
+ hash = dao.value.slice(composite_key_columns).hash
84
+ should_delete = (unique_daos[hash] ||= dao) == dao
74
85
 
75
- # add dao to cache
76
- dao.row.cache[self.class.cache_key] = dao
86
+ # unlink to be deleted dao and add a link to
87
+ dao.unlink! replace_with: unique_daos[hash] unless should_delete
88
+
89
+ should_delete
77
90
  end
78
91
  end
92
+
93
+ def link_rows_to_daos(daos:)
94
+ daos.each(&:link!)
95
+ end
79
96
  end
80
97
  end
81
98
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CSVStepImporter
4
- VERSION = "0.10.0"
4
+ VERSION = "0.11.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csv_step_importer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian-Manuel Butzke
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-11 00:00:00.000000000 Z
11
+ date: 2018-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler