csv_model 0.2.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +61 -7
- data/lib/csv_model/model.rb +3 -3
- data/lib/csv_model/row.rb +37 -18
- data/lib/csv_model/{object_with_status_snapshot.rb → row_active_record_adaptor.rb} +1 -1
- data/lib/csv_model/version.rb +1 -1
- data/lib/csv_model.rb +2 -2
- data/spec/csv_model/{object_with_status_snapshot_spec.rb → row_active_record_adaptor_spec.rb} +1 -1
- data/spec/csv_model/row_spec.rb +75 -45
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5c7053ec54a07cf27b8e903276c04a728c01511
|
4
|
+
data.tar.gz: fbc25ab237e583a936f6e0e4619c078b966631a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 318238c605891112715aa69677b15f4bcfc6d35c8fcfa3376a1aeccd4e4da2b96059a87df834d167e741b5247998475850c7cfa7caed135b99f976854b5b3130
|
7
|
+
data.tar.gz: 34cddace105c379953649d4a477962d486b2d512558302437189d88335e37490959450fbe7454f5d34b41e41fac944d56bafb561ec21e8f5a83d581b5e9a05fa
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,17 +1,71 @@
|
|
1
|
-
|
1
|
+
CSV Model
|
2
2
|
=========
|
3
3
|
|
4
4
|
[![Build Status](https://travis-ci.org/Scrimmage/csv_model.svg)](https://travis-ci.org/Scrimmage/csv_model)
|
5
5
|
|
6
6
|
[![Code Climate](https://codeclimate.com/github/Scrimmage/csv_model.png)](https://codeclimate.com/github/Scrimmage/csv_model)
|
7
7
|
|
8
|
-
|
8
|
+
CSV Model is a bulk import library for ActiveRecord. It parses a CSV into memory, validates the structure, can check for duplicates, and creates or updates the relevant record for each row.
|
9
9
|
|
10
|
-
active_record?
|
11
10
|
|
11
|
+
Requirements
|
12
|
+
------------
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
### Ruby
|
15
|
+
|
16
|
+
CSV Model requires Ruby version **>= 2.0.0**
|
17
|
+
|
18
|
+
|
19
|
+
Installation
|
20
|
+
------------
|
21
|
+
|
22
|
+
CSVModel is distributed as a gem, which is how it should be used in your app.
|
23
|
+
|
24
|
+
Include the gem in your Gemfile:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
gem "csv_model", "~> 1.0"
|
28
|
+
```
|
29
|
+
|
30
|
+
Or, if you want to get the latest, you can get master from the main repository:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
gem "csv_model", :git => "git://github.com/Scrimmage/csv_model.git"
|
34
|
+
```
|
15
35
|
|
16
|
-
|
17
|
-
|
36
|
+
|
37
|
+
Example Usage
|
38
|
+
-----------
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
options = {
|
42
|
+
dry_run: is_dry_run?,
|
43
|
+
legal_columns: structure.legal_columns,
|
44
|
+
primary_key: structure.primary_key_columns,
|
45
|
+
required_columns: structure.required_columns,
|
46
|
+
row_model_finder: model_finder,
|
47
|
+
row_model_mapper: model_mapper,
|
48
|
+
}
|
49
|
+
|
50
|
+
cm = CSVModel::Model.new(data, options)
|
51
|
+
|
52
|
+
if cm.structure_valid?
|
53
|
+
puts "Found structural errors: #{csv.structure_errors.inspect}"
|
54
|
+
else
|
55
|
+
cm.rows.each do |row|
|
56
|
+
status = row.process_row
|
57
|
+
puts "Found row #{row.key} with status #{status} and errors #{row.errors.inspect}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
|
63
|
+
Internal Notes
|
64
|
+
--------------
|
65
|
+
|
66
|
+
Deployment:
|
67
|
+
|
68
|
+
```bash
|
69
|
+
gem build csv_model.gemspec
|
70
|
+
gem push csv_model-x.y.z.gem
|
71
|
+
```
|
data/lib/csv_model/model.rb
CHANGED
@@ -41,8 +41,8 @@ module CSVModel
|
|
41
41
|
header_class.new(row, options)
|
42
42
|
end
|
43
43
|
|
44
|
-
def create_row(row)
|
45
|
-
row = row_class.new(header, row, options)
|
44
|
+
def create_row(row, index)
|
45
|
+
row = row_class.new(header, row, index, options)
|
46
46
|
row.mark_as_duplicate if is_duplicate_key?(row.key)
|
47
47
|
row
|
48
48
|
end
|
@@ -80,7 +80,7 @@ module CSVModel
|
|
80
80
|
# end
|
81
81
|
|
82
82
|
if index > 0
|
83
|
-
@rows << create_row(row)
|
83
|
+
@rows << create_row(row, index)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
rescue CSV::MalformedCSVError => e
|
data/lib/csv_model/row.rb
CHANGED
@@ -4,14 +4,17 @@ module CSVModel
|
|
4
4
|
class Row
|
5
5
|
include Utilities::Options
|
6
6
|
|
7
|
-
attr_reader :data, :header, :marked_as_duplicate
|
7
|
+
attr_reader :data, :header, :model_index, :marked_as_duplicate
|
8
8
|
|
9
|
-
def initialize(header, data, options = {})
|
9
|
+
def initialize(header, data, model_index, options = {})
|
10
10
|
@header = header
|
11
11
|
@data = data
|
12
|
+
@model_index = model_index
|
12
13
|
@options = options
|
13
14
|
end
|
14
15
|
|
16
|
+
alias_method :csv_index, :model_index
|
17
|
+
|
15
18
|
def index(value)
|
16
19
|
index = column_index(value) || value
|
17
20
|
data[index] if index.is_a?(Fixnum) && index >= 0
|
@@ -36,6 +39,14 @@ module CSVModel
|
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
42
|
+
def map_all_attributes(attrs)
|
43
|
+
attrs
|
44
|
+
end
|
45
|
+
|
46
|
+
def map_key_attributes(attrs)
|
47
|
+
attrs
|
48
|
+
end
|
49
|
+
|
39
50
|
def marked_as_duplicate?
|
40
51
|
!!marked_as_duplicate
|
41
52
|
end
|
@@ -44,6 +55,16 @@ module CSVModel
|
|
44
55
|
@marked_as_duplicate = true
|
45
56
|
end
|
46
57
|
|
58
|
+
def process_row
|
59
|
+
return model_instance.status if @processed
|
60
|
+
@processed = true
|
61
|
+
|
62
|
+
model_instance.assign_attributes(all_attributes)
|
63
|
+
model_instance.mark_as_duplicate if marked_as_duplicate?
|
64
|
+
model_instance.save(dry_run: is_dry_run?)
|
65
|
+
model_instance.status
|
66
|
+
end
|
67
|
+
|
47
68
|
def status
|
48
69
|
model_instance.status
|
49
70
|
end
|
@@ -63,7 +84,7 @@ module CSVModel
|
|
63
84
|
private
|
64
85
|
|
65
86
|
def all_attributes
|
66
|
-
@all_attributes ||= column_attributes_with_values(columns)
|
87
|
+
@all_attributes ||= model_mapper.map_all_attributes(column_attributes_with_values(columns))
|
67
88
|
end
|
68
89
|
|
69
90
|
def columns
|
@@ -87,41 +108,39 @@ module CSVModel
|
|
87
108
|
option(:dry_run, false)
|
88
109
|
end
|
89
110
|
|
90
|
-
def
|
91
|
-
|
111
|
+
def model_adaptor
|
112
|
+
CSVModel::RowActiveRecordAdaptor
|
113
|
+
end
|
114
|
+
|
115
|
+
def model_finder
|
116
|
+
option(:row_model_finder)
|
92
117
|
end
|
93
118
|
|
94
119
|
def model_instance
|
95
120
|
@model_instance ||= begin
|
96
121
|
x = inherit_or_delegate(:find_row_model, key_attributes)
|
97
122
|
x ||= inherit_or_delegate(:new_row_model, key_attributes)
|
98
|
-
x =
|
123
|
+
x = model_adaptor.new(x)
|
99
124
|
end
|
100
125
|
end
|
101
126
|
|
127
|
+
def model_mapper
|
128
|
+
option(:row_model_mapper, self)
|
129
|
+
end
|
130
|
+
|
102
131
|
def key_attributes
|
103
132
|
cols = primary_key_columns.any? ? primary_key_columns : columns
|
104
|
-
@key_attributes ||= column_attributes_with_values(cols)
|
133
|
+
@key_attributes ||= model_mapper.map_key_attributes(column_attributes_with_values(cols))
|
105
134
|
end
|
106
135
|
|
107
|
-
|
108
136
|
def primary_key_columns
|
109
137
|
header.primary_key_columns
|
110
138
|
end
|
111
139
|
|
112
|
-
def process_row
|
113
|
-
return if @processed
|
114
|
-
@processed = true
|
115
|
-
|
116
|
-
model_instance.assign_attributes(all_attributes)
|
117
|
-
model_instance.mark_as_duplicate if marked_as_duplicate?
|
118
|
-
model_instance.save(dry_run: is_dry_run?)
|
119
|
-
end
|
120
|
-
|
121
140
|
private
|
122
141
|
|
123
142
|
def inherit_or_delegate(method, *args)
|
124
|
-
try(method, *args) ||
|
143
|
+
try(method, *args) || model_finder.try(method, *args)
|
125
144
|
end
|
126
145
|
|
127
146
|
end
|
data/lib/csv_model/version.rb
CHANGED
data/lib/csv_model.rb
CHANGED
@@ -7,10 +7,10 @@ require 'csv_model/record_status'
|
|
7
7
|
require 'csv_model/utilities'
|
8
8
|
|
9
9
|
require 'csv_model/column'
|
10
|
-
require 'csv_model/row'
|
11
10
|
require 'csv_model/header_row'
|
12
11
|
require 'csv_model/model'
|
13
|
-
require 'csv_model/
|
12
|
+
require 'csv_model/row'
|
13
|
+
require 'csv_model/row_active_record_adaptor'
|
14
14
|
require 'csv_model/version'
|
15
15
|
|
16
16
|
module CSVModel
|
data/spec/csv_model/{object_with_status_snapshot_spec.rb → row_active_record_adaptor_spec.rb}
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe CSVModel::
|
3
|
+
describe CSVModel::RowActiveRecordAdaptor do
|
4
4
|
let(:model) { double("model", changed?: false, marked_for_destruction?: false, new_record?: false, valid?: false) }
|
5
5
|
let(:subject) { described_class.new(model) }
|
6
6
|
|
data/spec/csv_model/row_spec.rb
CHANGED
@@ -5,10 +5,11 @@ describe CSVModel::Row do
|
|
5
5
|
let(:header) { double("header") }
|
6
6
|
let(:column) { double("column", key: "column one", model_attribute: :column_one, name: "Column One") }
|
7
7
|
let(:columns) { [column] }
|
8
|
+
let(:index) { 1 }
|
8
9
|
let(:primary_key_columns) { [] }
|
9
10
|
|
10
11
|
let(:data) { ["Value One"] }
|
11
|
-
let(:subject) { described_class.new(header, data) }
|
12
|
+
let(:subject) { described_class.new(header, data, index) }
|
12
13
|
|
13
14
|
before do
|
14
15
|
allow(header).to receive(:columns).and_return(columns)
|
@@ -17,14 +18,21 @@ describe CSVModel::Row do
|
|
17
18
|
allow(header).to receive(:primary_key_columns).and_return(primary_key_columns)
|
18
19
|
end
|
19
20
|
|
21
|
+
describe "#csv_index, #model_index" do
|
22
|
+
it "returns the index the row was instantiated with" do
|
23
|
+
expect(subject.csv_index).to eq(index)
|
24
|
+
expect(subject.model_index).to eq(index)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
20
28
|
describe "#errors" do
|
21
29
|
context "when no errors" do
|
22
|
-
let(:
|
23
|
-
let(:subject) { described_class.new(header, data,
|
30
|
+
let(:model_finder) { double("model-finder") }
|
31
|
+
let(:subject) { described_class.new(header, data, index, row_model_finder: model_finder) }
|
24
32
|
let(:model_instance) { double("model-instance", changed?: false, marked_for_destruction?: false, new_record?: false, valid?: true) }
|
25
33
|
|
26
34
|
before do
|
27
|
-
allow(
|
35
|
+
allow(model_finder).to receive(:find_row_model).and_return(model_instance)
|
28
36
|
allow(model_instance).to receive(:save)
|
29
37
|
end
|
30
38
|
|
@@ -45,7 +53,7 @@ describe CSVModel::Row do
|
|
45
53
|
end
|
46
54
|
|
47
55
|
context "during a dry-run" do
|
48
|
-
let(:subject) { described_class.new(header, data, dry_run: true) }
|
56
|
+
let(:subject) { described_class.new(header, data, index, dry_run: true) }
|
49
57
|
|
50
58
|
it "returns an error" do
|
51
59
|
expect(subject.errors).to include("Duplicate row")
|
@@ -62,13 +70,13 @@ describe CSVModel::Row do
|
|
62
70
|
end
|
63
71
|
|
64
72
|
context "when the model instance has errors" do
|
65
|
-
let(:
|
66
|
-
let(:subject) { described_class.new(header, data,
|
73
|
+
let(:model_finder) { double("model-finder") }
|
74
|
+
let(:subject) { described_class.new(header, data, index, row_model_finder: model_finder) }
|
67
75
|
let(:model_instance) { double("model-instance", changed?: false, errors: errors, marked_for_destruction?: false, new_record?: false, valid?: false) }
|
68
76
|
let(:errors) { ["Message one", "Message two"] }
|
69
77
|
|
70
78
|
before do
|
71
|
-
allow(
|
79
|
+
allow(model_finder).to receive(:find_row_model).and_return(model_instance)
|
72
80
|
end
|
73
81
|
|
74
82
|
it "includes the model instance errors" do
|
@@ -156,6 +164,30 @@ describe CSVModel::Row do
|
|
156
164
|
end
|
157
165
|
end
|
158
166
|
|
167
|
+
describe "#process_row" do
|
168
|
+
let(:model_finder) { double("model-finder") }
|
169
|
+
let(:model_instance) { double("model-instance", changed?: true, marked_for_destruction?: false, new_record?: false, valid?: true) }
|
170
|
+
let(:subject) { described_class.new(header, data, index, row_model_finder: model_finder) }
|
171
|
+
|
172
|
+
before do
|
173
|
+
allow(model_finder).to receive(:find_row_model).and_return(model_instance)
|
174
|
+
allow(subject).to receive(:all_attributes).and_return(:all_attributes)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "assigns attributes and saves the model instance" do
|
178
|
+
expect(model_instance).to receive(:assign_attributes).with(:all_attributes).ordered
|
179
|
+
expect(model_instance).to receive(:save)
|
180
|
+
subject.process_row
|
181
|
+
end
|
182
|
+
|
183
|
+
it "only processes a record once" do
|
184
|
+
expect(model_instance).to receive(:assign_attributes).with(:all_attributes).ordered
|
185
|
+
expect(model_instance).to receive(:save)
|
186
|
+
subject.process_row
|
187
|
+
subject.process_row
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
159
191
|
describe "#status" do
|
160
192
|
let(:model) { double("model") }
|
161
193
|
let(:wrapper) { double("wrapper", status: :some_status) }
|
@@ -167,7 +199,7 @@ describe CSVModel::Row do
|
|
167
199
|
end
|
168
200
|
|
169
201
|
it "is delegates status to the model" do
|
170
|
-
expect(CSVModel::
|
202
|
+
expect(CSVModel::RowActiveRecordAdaptor).to receive(:new).and_return(wrapper)
|
171
203
|
expect(subject.status).to eq(:some_status)
|
172
204
|
end
|
173
205
|
end
|
@@ -194,6 +226,19 @@ describe CSVModel::Row do
|
|
194
226
|
expect(subject.send(:all_attributes)).to eq(column_one: "Value One")
|
195
227
|
end
|
196
228
|
|
229
|
+
context "with a column mapping" do
|
230
|
+
let(:model_mapper) { double("model-mapper") }
|
231
|
+
let(:subject) { described_class.new(header, data, index, row_model_mapper: model_mapper) }
|
232
|
+
|
233
|
+
before do
|
234
|
+
allow(model_mapper).to receive(:map_all_attributes).with({ column_one: "Value One" }).and_return(mapped_key: "mapped_value")
|
235
|
+
end
|
236
|
+
|
237
|
+
it "maps attributes" do
|
238
|
+
expect(subject.send(:all_attributes)).to eq(mapped_key: "mapped_value")
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
197
242
|
context "with multiple columns" do
|
198
243
|
let(:columns) { [
|
199
244
|
double("column", key: "column one", model_attribute: :column_one),
|
@@ -214,8 +259,8 @@ describe CSVModel::Row do
|
|
214
259
|
end
|
215
260
|
|
216
261
|
describe "#inherit_or_delegate" do
|
217
|
-
let(:
|
218
|
-
let(:subject) { described_class.new(header, data,
|
262
|
+
let(:model_finder) { double("model-finder") }
|
263
|
+
let(:subject) { described_class.new(header, data, index, row_model_finder: model_finder) }
|
219
264
|
|
220
265
|
it "doesn't respond to inherit_or_delegate" do
|
221
266
|
expect(subject.respond_to?(:inherit_or_delegate)).to eq(false)
|
@@ -233,7 +278,7 @@ describe CSVModel::Row do
|
|
233
278
|
end
|
234
279
|
|
235
280
|
it "invokes delegate method if delegate exists and internal method is not defined" do
|
236
|
-
expect(
|
281
|
+
expect(model_finder).to receive(:some_method).with(:multiple, :args).and_return(:some_value)
|
237
282
|
expect(subject.send(:inherit_or_delegate, :some_method, :multiple, :args)).to eq(:some_value)
|
238
283
|
end
|
239
284
|
end
|
@@ -275,12 +320,25 @@ describe CSVModel::Row do
|
|
275
320
|
expect(subject.send(:key_attributes)).to eq(column_one: "Value One", column_two: "Value Two")
|
276
321
|
end
|
277
322
|
end
|
323
|
+
|
324
|
+
context "with a column mapping" do
|
325
|
+
let(:model_mapper) { double("model-mapper") }
|
326
|
+
let(:subject) { described_class.new(header, data, index, row_model_mapper: model_mapper) }
|
327
|
+
|
328
|
+
before do
|
329
|
+
allow(model_mapper).to receive(:map_key_attributes).with({ column_one: "Value One" }).and_return(mapped_key: "mapped_value")
|
330
|
+
end
|
331
|
+
|
332
|
+
it "maps attributes" do
|
333
|
+
expect(subject.send(:key_attributes)).to eq(mapped_key: "mapped_value")
|
334
|
+
end
|
335
|
+
end
|
278
336
|
end
|
279
337
|
|
280
338
|
describe "#model_instance" do
|
281
|
-
let(:
|
339
|
+
let(:model_finder) { double("model-finder") }
|
282
340
|
let(:model_instance) { double("model-instance") }
|
283
|
-
let(:subject) { described_class.new(header, data,
|
341
|
+
let(:subject) { described_class.new(header, data, index, row_model_finder: model_finder) }
|
284
342
|
|
285
343
|
before do
|
286
344
|
allow(subject).to receive(:key_attributes).and_return(:key_attributes)
|
@@ -298,7 +356,7 @@ describe CSVModel::Row do
|
|
298
356
|
end
|
299
357
|
|
300
358
|
it "tries to find an instance via model#find_row_model when #find_row_model does not exist" do
|
301
|
-
expect(
|
359
|
+
expect(model_finder).to receive(:find_row_model).with(:key_attributes).and_return(model_instance)
|
302
360
|
expect(subject.send(:model_instance)).to eq(model_instance)
|
303
361
|
end
|
304
362
|
|
@@ -313,39 +371,11 @@ describe CSVModel::Row do
|
|
313
371
|
end
|
314
372
|
|
315
373
|
it "tries to instantiate a new model via model#new_row_model when a model cannot be found and #new_row_model does not exist" do
|
316
|
-
expect(
|
317
|
-
expect(
|
374
|
+
expect(model_finder).to receive(:find_row_model).with(:key_attributes).and_return(nil)
|
375
|
+
expect(model_finder).to receive(:new_row_model).with(:key_attributes).and_return(model_instance)
|
318
376
|
expect(subject.send(:model_instance)).to eq(model_instance)
|
319
377
|
end
|
320
378
|
end
|
321
|
-
|
322
|
-
describe "#process_row" do
|
323
|
-
let(:model) { double("model") }
|
324
|
-
let(:model_instance) { double("model-instance", changed?: true, marked_for_destruction?: false, new_record?: false, valid?: true) }
|
325
|
-
let(:subject) { described_class.new(header, data, model: model) }
|
326
|
-
|
327
|
-
before do
|
328
|
-
allow(model).to receive(:find_row_model).and_return(model_instance)
|
329
|
-
allow(subject).to receive(:all_attributes).and_return(:all_attributes)
|
330
|
-
end
|
331
|
-
|
332
|
-
it "doesn't respond to process_row" do
|
333
|
-
expect(subject.respond_to?(:process_row)).to eq(false)
|
334
|
-
end
|
335
|
-
|
336
|
-
it "assigns attributes and saves the model instance" do
|
337
|
-
expect(model_instance).to receive(:assign_attributes).with(:all_attributes).ordered
|
338
|
-
expect(model_instance).to receive(:save)
|
339
|
-
subject.send(:process_row)
|
340
|
-
end
|
341
|
-
|
342
|
-
it "only processes a record once" do
|
343
|
-
expect(model_instance).to receive(:assign_attributes).with(:all_attributes).ordered
|
344
|
-
expect(model_instance).to receive(:save)
|
345
|
-
subject.send(:process_row)
|
346
|
-
subject.send(:process_row)
|
347
|
-
end
|
348
|
-
end
|
349
379
|
end
|
350
380
|
|
351
381
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Chadwick
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -73,15 +73,15 @@ files:
|
|
73
73
|
- lib/csv_model/extensions.rb
|
74
74
|
- lib/csv_model/header_row.rb
|
75
75
|
- lib/csv_model/model.rb
|
76
|
-
- lib/csv_model/object_with_status_snapshot.rb
|
77
76
|
- lib/csv_model/record_status.rb
|
78
77
|
- lib/csv_model/row.rb
|
78
|
+
- lib/csv_model/row_active_record_adaptor.rb
|
79
79
|
- lib/csv_model/utilities.rb
|
80
80
|
- lib/csv_model/version.rb
|
81
81
|
- spec/csv_model/column_spec.rb
|
82
82
|
- spec/csv_model/header_row_spec.rb
|
83
83
|
- spec/csv_model/model_spec.rb
|
84
|
-
- spec/csv_model/
|
84
|
+
- spec/csv_model/row_active_record_adaptor_spec.rb
|
85
85
|
- spec/csv_model/row_spec.rb
|
86
86
|
- spec/csv_model/utilities_spec.rb
|
87
87
|
- spec/spec_helper.rb
|
@@ -113,7 +113,7 @@ test_files:
|
|
113
113
|
- spec/csv_model/column_spec.rb
|
114
114
|
- spec/csv_model/header_row_spec.rb
|
115
115
|
- spec/csv_model/model_spec.rb
|
116
|
-
- spec/csv_model/
|
116
|
+
- spec/csv_model/row_active_record_adaptor_spec.rb
|
117
117
|
- spec/csv_model/row_spec.rb
|
118
118
|
- spec/csv_model/utilities_spec.rb
|
119
119
|
- spec/spec_helper.rb
|