speaky_csv 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9f27598188d01a1f54fc451cd37a7bf147030b8
4
- data.tar.gz: b140a75185fbe65047c91b60dc041f11bcbe7f08
3
+ metadata.gz: d017f2f25bab00a7df4f498e877f6ef2ba04a5f9
4
+ data.tar.gz: 9fda5afbd14f9f576a146e68508f376e0b6b19c2
5
5
  SHA512:
6
- metadata.gz: bd17153298a4ace51d67c96698fc5454c5e27f93652ac651cdb3241779bb4347e177fc5385e044d08d14ecab326568db5f9fc4235791343e03ea6fa7a28d348f
7
- data.tar.gz: ad3848f06899fca0b59bb0adb3e5534c4ea18886fec66cfd10e2ac07241a299fa0dae6807f774b2826281437a68102cb80230c8e3efb09268206198e8661c309
6
+ metadata.gz: 3aaa6af2837e4813370d9f3c3b3c1089921e24f4ab4f8f1a12765cc72b22824654945b55fcb8adabfda66986d51eecc6fc54a70e7bc288bb20e3e5dfcd36ce6a
7
+ data.tar.gz: 4618b193794df6419843ac667126d3bdf3649fa39989d97ddbf3795cfa815ea4a99a0775e58300daee52233f867704520865f210f12e05d0523ceaeab9d6fcc9
data/.gitignore CHANGED
@@ -1 +1,3 @@
1
- spec/active_record.log
1
+ log/*.log
2
+ speaky_csv*.gem
3
+ Gemfile.lock
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "speaky_csv"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -1,5 +1,6 @@
1
1
  require 'csv'
2
2
  require 'active_record'
3
+ require 'English'
3
4
 
4
5
  module SpeakyCsv
5
6
  # Imports a csv file as unsaved active record instances
@@ -9,46 +10,45 @@ module SpeakyCsv
9
10
  QUERY_BATCH_SIZE = 20
10
11
  TRUE_VALUES = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
11
12
 
12
- attr_accessor :errors
13
+ attr_accessor :logger
13
14
 
14
- def initialize(config, input_io, klass)
15
+ def initialize(config, input_io_or_enumerable, klass)
15
16
  @config = config
16
- @errors = ActiveModel::Errors.new(self)
17
17
  @klass = klass
18
18
 
19
- @attr_import = AttrImport.new @config, input_io
20
- @attr_import.errors = @errors
19
+ @log_output = StringIO.new
20
+ @logger = Logger.new @log_output
21
+
22
+ if duck_type_is_io?(input_io_or_enumerable)
23
+ @rx = AttrImport.new @config, input_io_or_enumerable
24
+ @rx.logger = @logger
25
+ else
26
+ @rx = input_io_or_enumerable
27
+ end
21
28
  end
22
29
 
23
30
  def each
24
- errors.clear
25
31
  block_given? ? enumerator.each { |a| yield a } : enumerator
26
32
  end
27
33
 
34
+ # Returns a string of all the log output from the import. Or returns
35
+ # nothing if a custom logger was used.
36
+ def log
37
+ @log_output.string
38
+ end
39
+
28
40
  private
29
41
 
30
42
  def enumerator
31
- Enumerator.new do |yielder|
32
- attr_enumerator = @attr_import.each
33
- done = false
34
-
35
- row_index = 1
36
-
37
- while done == false
38
- rows = []
39
-
40
- QUERY_BATCH_SIZE.times do
41
- begin
42
- rows << attr_enumerator.next
43
- rescue StopIteration
44
- done = true
45
- end
46
- end
43
+ # One based index, where the header is row 1 and first record is row 2
44
+ row_index = 1
47
45
 
46
+ Enumerator.new do |yielder|
47
+ @rx.each_slice(QUERY_BATCH_SIZE) do |rows|
48
48
  keys = rows.map { |attrs| attrs[@config.primary_key.to_s] }
49
49
  records = @klass.includes(@config.has_manys.keys)
50
- .where(@config.primary_key => keys)
51
- .inject({}) { |a, e| a[e.send(@config.primary_key).to_s] = e; a }
50
+ .where(@config.primary_key => keys)
51
+ .inject({}) { |a, e| a[e.send(@config.primary_key).to_s] = e; a }
52
52
 
53
53
  rows.each do |attrs|
54
54
  row_index += 1
@@ -60,7 +60,8 @@ module SpeakyCsv
60
60
  end
61
61
 
62
62
  unless record
63
- errors.add "row_#{row_index}", "record not found with primary key #{attrs[@config.primary_key]}"
63
+ logger.error "[row #{row_index}] record not found with primary key #{attrs[@config.primary_key]}"
64
+ yielder << nil
64
65
  next
65
66
  end
66
67
 
@@ -85,7 +86,7 @@ module SpeakyCsv
85
86
  begin
86
87
  record.attributes = attrs
87
88
  rescue ActiveRecord::UnknownAttributeError
88
- errors.add "row_#{row_index}", "record doesn't respond to some configured fields: #{$!.message}"
89
+ logger.error "[row #{row_index}] record doesn't respond to some configured fields: #{$ERROR_INFO.message}"
89
90
  end
90
91
 
91
92
  yielder << record
@@ -93,5 +94,10 @@ module SpeakyCsv
93
94
  end
94
95
  end
95
96
  end
97
+
98
+ def duck_type_is_io?(val)
99
+ # check some arbitrary methods
100
+ val.respond_to?(:gets) && val.respond_to?(:seek)
101
+ end
96
102
  end
97
103
  end
@@ -1,70 +1,93 @@
1
1
  require 'csv'
2
+ require 'English'
2
3
 
3
4
  module SpeakyCsv
4
5
  # Imports a csv file as attribute hashes.
5
6
  class AttrImport
6
7
  include Enumerable
7
8
 
8
- attr_accessor :errors
9
+ attr_accessor :logger
9
10
 
10
11
  def initialize(config, input_io)
11
12
  @config = config
12
13
  @input_io = input_io
13
- @errors = ActiveModel::Errors.new(self)
14
+ @log_output = StringIO.new
15
+ @logger = Logger.new @log_output
14
16
  end
15
17
 
16
- # yields successive
18
+ # Yields successive attribute hashes for rows in the csv file
17
19
  def each
18
- errors.clear
19
20
  block_given? ? enumerator.each { |a| yield a } : enumerator
20
21
  end
21
22
 
23
+ # Returns a string of all the log output from the import. Or returns
24
+ # nothing if a custom logger was used.
25
+ def log
26
+ @log_output.string
27
+ end
28
+
22
29
  private
23
30
 
24
31
  def enumerator
25
- Enumerator.new do |yielder|
32
+ return @enumerator if defined? @enumerator
33
+
34
+ @enumerator = Enumerator.new do |yielder|
26
35
  begin
27
36
  csv = CSV.new @input_io, headers: true
28
37
 
29
38
  csv.each do |row|
30
39
  attrs = {}
40
+ add_fields row, attrs
41
+ add_has_manys row, attrs
42
+ yielder << attrs
43
+ end
31
44
 
32
- row.headers.compact.each do |h|
33
- next unless @config.fields.include?(h.to_sym)
34
- next if @config.export_only_fields.include?(h.to_sym)
35
- attrs[h] = row.field h
36
- end
45
+ rescue CSV::MalformedCSVError
46
+ logger.error "csv is malformed: #{$ERROR_INFO.message}"
47
+ end
48
+ end
49
+ end
37
50
 
38
- headers_length = row.headers.compact.length
39
- pairs_start_on_evens = headers_length.even?
40
- (headers_length..row.fields.length).each do |i|
41
- i.send(pairs_start_on_evens ? :even? : :odd?) || next
42
- row[i] || next
51
+ # Adds configured fields to attrs
52
+ def add_fields(row, attrs)
53
+ row.headers.compact.each do |h|
54
+ unless @config.fields.include?(h.to_sym)
55
+ logger.warn "ignoring unknown column #{h}"
56
+ next
57
+ end
58
+ if @config.export_only_fields.include?(h.to_sym)
59
+ logger.warn "ignoring unknown column #{h}"
60
+ next
61
+ end
43
62
 
44
- m = row[i].match(/^(\w+)_(\d+)_(\w+)$/)
45
- m || next
46
- has_many_name = m[1].pluralize
47
- has_many_index = m[2].to_i
48
- has_many_field = m[3]
49
- has_many_value = row[i + 1]
63
+ attrs[h] = row.field h
64
+ end
65
+ end
50
66
 
51
- has_many_config = @config.has_manys[has_many_name.to_sym]
67
+ # Adds configured has manys to attrs
68
+ def add_has_manys(row, attrs)
69
+ headers_length = row.headers.compact.length
70
+ pairs_start_on_evens = headers_length.even?
71
+ (headers_length..row.fields.length).each do |i|
72
+ i.send(pairs_start_on_evens ? :even? : :odd?) || next
73
+ row[i] || next
52
74
 
53
- next unless has_many_config
54
- next unless has_many_config.fields.include?(has_many_field.to_sym)
55
- next if has_many_config.export_only_fields.include?(has_many_field.to_sym)
75
+ m = row[i].match(/^(\w+)_(\d+)_(\w+)$/)
76
+ m || next
77
+ has_many_name = m[1].pluralize
78
+ has_many_index = m[2].to_i
79
+ has_many_field = m[3]
80
+ has_many_value = row[i + 1]
56
81
 
57
- attrs[has_many_name] ||= []
58
- attrs[has_many_name][has_many_index] ||= {}
59
- attrs[has_many_name][has_many_index][has_many_field] = has_many_value
60
- end
82
+ has_many_config = @config.has_manys[has_many_name.to_sym]
61
83
 
62
- yielder << attrs
63
- end
84
+ next unless has_many_config
85
+ next unless has_many_config.fields.include?(has_many_field.to_sym)
86
+ next if has_many_config.export_only_fields.include?(has_many_field.to_sym)
64
87
 
65
- rescue CSV::MalformedCSVError
66
- errors.add :csv, "is malformed: #{$!.message}"
67
- end
88
+ attrs[has_many_name] ||= []
89
+ attrs[has_many_name][has_many_index] ||= {}
90
+ attrs[has_many_name][has_many_index][has_many_field] = has_many_value
68
91
  end
69
92
  end
70
93
  end
@@ -1,5 +1,4 @@
1
1
  module SpeakyCsv
2
-
3
2
  # An instance of this class is yielded to the block passed to
4
3
  # define_csv_fields. Used to configure speaky csv.
5
4
  class Builder
@@ -36,7 +35,7 @@ module SpeakyCsv
36
35
  # Define a custom primary key. By default an `id` column as used.
37
36
  #
38
37
  # Accepts the same options as #field
39
- def primary_key=(name, options={})
38
+ def primary_key=(name, options = {})
40
39
  field name, options
41
40
  @primary_key = name.to_sym
42
41
  end
@@ -75,20 +74,61 @@ module SpeakyCsv
75
74
  end
76
75
 
77
76
  # Return a new exporter instance
78
- def exporter(records_enumerator)
79
- Export.new self.class.csv_field_builder,
77
+ def self.exporter(records_enumerator)
78
+ Export.new csv_field_builder,
80
79
  records_enumerator
81
80
  end
82
81
 
82
+ # Return a new attr importer instance from the given IO, which is expected
83
+ # to be able to read a csv file. The importer will be an Enumerator that returns successive attribute hashes.
84
+ #
85
+ # For example:
86
+ #
87
+ # class SomeFormat < SpeakyCsv::Base
88
+ # define_csv_fields do |c|
89
+ # c.fields :id, :name
90
+ # end
91
+ # end
92
+ #
93
+ # File.open('sample.csv', 'r') do |io|
94
+ # importer = SomeFormat.new.attr_importer io
95
+ #
96
+ # importer.each do |attrs|
97
+ # # attrs will be hashes like { "id" => 123, "name" => "Curley" }
98
+ # end
99
+ # end
100
+ #
83
101
  def attr_importer(input_io)
84
102
  AttrImport.new self.class.csv_field_builder,
85
103
  input_io
86
104
  end
87
105
 
88
- def active_record_importer(input_io, klass)
106
+ # Return a new active record instance from the given IO, which is expected
107
+ # to be able to read a csv file. The importer will be an Enumerator that returns successive active records.
108
+ #
109
+ # For example:
110
+ #
111
+ # class UserCsv < SpeakyCsv::Base
112
+ # define_csv_fields do |c|
113
+ # c.fields :id, :name
114
+ # end
115
+ # end
116
+ #
117
+ # File.open('sample.csv', 'r') do |io|
118
+ # importer = SomeFormat.new.active_record_importer io, User
119
+ #
120
+ # importer.each do |record|
121
+ # # record will be a User instance or nil
122
+ # end
123
+ # end
124
+ #
125
+ # Optionally an Enumerable instance can be passed instead of an IO
126
+ # instance. The enumerable should return attr hashes. This may be helpful
127
+ # for transforming or chaining Enumerables.
128
+ def active_record_importer(input_io_or_enumerable, klass)
89
129
  ActiveRecordImport.new \
90
130
  self.class.csv_field_builder,
91
- input_io,
131
+ input_io_or_enumerable,
92
132
  klass
93
133
  end
94
134
  end
@@ -1,24 +1,31 @@
1
1
  require 'csv'
2
2
  require 'active_model'
3
+ require 'stringio'
4
+ require 'logger'
3
5
 
4
6
  module SpeakyCsv
5
7
  # Exports records as csv. Will write a csv to the given IO object
6
8
  class Export
7
9
  include Enumerable
8
10
 
11
+ attr_accessor :logger
12
+
9
13
  def initialize(config, records_enumerator)
10
14
  @config = config
11
15
  @records_enumerator = records_enumerator
16
+ @log_output = StringIO.new
17
+ @logger = Logger.new @log_output
12
18
  end
13
19
 
14
20
  # Writes csv string to io
15
21
  def each
16
- errors.clear
17
22
  block_given? ? enumerator.each { |a| yield a } : enumerator
18
23
  end
19
24
 
20
- def errors
21
- @errors ||= ActiveModel::Errors.new(self)
25
+ # Returns a string of all the log output from the import. Or returns
26
+ # nothing if a custom logger was used.
27
+ def log
28
+ @log_output.string
22
29
  end
23
30
 
24
31
  private
@@ -27,16 +34,15 @@ module SpeakyCsv
27
34
  return true if record.respond_to? field
28
35
 
29
36
  error_name = prefix ? "#{prefix}_#{field}" : field
30
-
31
- if errors[error_name].blank?
32
- errors.add error_name, "is not a method for class #{record.class}"
33
- end
37
+ logger.error "#{error_name} is not a method for class #{record.class}"
34
38
 
35
39
  false
36
40
  end
37
41
 
38
42
  def enumerator
39
- Enumerator.new do |yielder|
43
+ return @enumerator if defined? @enumerator
44
+
45
+ @enumerator = Enumerator.new do |yielder|
40
46
  # header row
41
47
  yielder << CSV::Row.new(@config.fields, @config.fields, true).to_csv
42
48
 
@@ -1,3 +1,3 @@
1
1
  module SpeakyCsv
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
data/log/.gitkeep ADDED
File without changes
@@ -131,9 +131,13 @@ id,name,author
131
131
  CSV
132
132
  end
133
133
 
134
+ it 'returns nil so row number is can known' do
135
+ expect(subject.each_with_index.to_a).to eq [[nil, 0]]
136
+ end
137
+
134
138
  it 'returns an error' do
135
- expect(subject.to_a).to eq []
136
- expect(subject.errors[:row_2]).to be_present
139
+ subject.to_a
140
+ expect(subject.log).to match(/\[row 2\]/)
137
141
  end
138
142
  end
139
143
 
@@ -157,7 +161,7 @@ id,whats_this
157
161
 
158
162
  it 'adds an error' do
159
163
  expect(record).to eq book
160
- expect(subject.errors[:row_2]).to be_present
164
+ expect(subject.log).to match(/\[row 2\]/)
161
165
  end
162
166
  end
163
167
 
@@ -246,8 +250,6 @@ id
246
250
  end
247
251
  end
248
252
 
249
- it "should fail when all headers aren't to the left"
250
- it 'should ignore undefined variable columns'
251
253
  it 'should fail when variable columns not pair up correctly'
252
254
 
253
255
  describe 'batch behavior' do
@@ -332,7 +334,93 @@ id,name,author,_destroy
332
334
 
333
335
  it 'adds an error' do
334
336
  expect(subject.to_a).to eq []
335
- expect(subject.errors[:csv]).to be_present
337
+ expect(subject.log).to match(/csv is malformed/)
338
+ end
339
+ end
340
+
341
+ context 'with weird rows' do
342
+ before do
343
+ presenter_klass.class_eval do
344
+ define_csv_fields do |d|
345
+ d.field 'name', 'author'
346
+ end
347
+ end
348
+ end
349
+
350
+ let(:io) do
351
+ StringIO.new <<-CSV
352
+ foo,bar,bax
353
+ 1,2,3,2,1
354
+ ,,
355
+
356
+ hihihi
357
+ CSV
358
+ end
359
+
360
+ it 'always returns a something per row' do
361
+ expect(subject.to_a.length).to eq 4
362
+ end
363
+ end
364
+
365
+ context 'with enumerator' do
366
+ subject { presenter_klass.new.active_record_importer enumerator, Book }
367
+
368
+ before do
369
+ presenter_klass.class_eval do
370
+ define_csv_fields do |d|
371
+ d.field :id, :name, :author, :_destroy
372
+ end
373
+ end
374
+ end
375
+
376
+ before do
377
+ Book.create! id: 1, name: 'Big Fiction', author: 'Sneed'
378
+ Book.create! id: 2, name: 'Small Fiction', author: 'Sneed'
379
+ Book.create! id: 3, name: 'Awful', author: 'Snore'
380
+ end
381
+
382
+ let(:enumerator) do
383
+ Enumerator.new do |yielder|
384
+ [
385
+ { 'id' => nil,
386
+ 'name' => 'New Fiction',
387
+ 'author' => 'Sneed',
388
+ '_destroy' => nil },
389
+ { 'id' => '1',
390
+ 'name' => 'Big Fiction',
391
+ 'author' => 'Sneed',
392
+ '_destroy' => nil },
393
+ { 'id' => '2',
394
+ 'name' => 'Wee Little Fiction',
395
+ 'author' => 'Sneed',
396
+ '_destroy' => nil },
397
+ { 'id' => '3',
398
+ 'name' => nil,
399
+ 'author' => nil,
400
+ '_destroy' => 'true' }
401
+ ].each { |h| yielder << h }
402
+ end
403
+ end
404
+
405
+ it 'works' do
406
+ records = subject.to_a
407
+ expect(records.length).to eq(4)
408
+
409
+ aggregate_failures do
410
+ expect(records[0]).to be_new_record
411
+ expect(records[0].attributes).to include('name' => 'New Fiction',
412
+ 'author' => 'Sneed')
413
+
414
+ expect(records[1]).to_not be_changed
415
+ expect(records[1].attributes).to include('id' => 1,
416
+ 'name' => 'Big Fiction',
417
+ 'author' => 'Sneed')
418
+
419
+ expect(records[2].name).to eq 'Wee Little Fiction'
420
+ expect(records[2]).to be_changed # not saved yet
421
+
422
+ expect(records[3]).to be_marked_for_destruction
423
+ end
336
424
  end
337
425
  end
338
426
  end
@@ -49,7 +49,12 @@ id,name
49
49
  end
50
50
 
51
51
  it 'should exclude field' do
52
- expect(subject.to_a).to eq([{'id' => '22'}])
52
+ expect(subject.to_a).to eq([{ 'id' => '22' }])
53
+ end
54
+
55
+ it 'should log it' do
56
+ subject.to_a
57
+ expect(subject.log).to match(/name/)
53
58
  end
54
59
  end
55
60
 
@@ -76,6 +81,11 @@ True story,NYC
76
81
  { 'name' => 'True story' }
77
82
  ])
78
83
  end
84
+
85
+ it 'should log it' do
86
+ subject.to_a
87
+ expect(subject.log).to match(/setting/)
88
+ end
79
89
  end
80
90
 
81
91
  context 'with has_many fields' do
@@ -195,11 +205,33 @@ Big Fiction,review_0_tomatoes,99,review_0_auther,Meanie
195
205
 
196
206
  it 'adds an error' do
197
207
  expect(subject.to_a).to eq []
198
- expect(subject.errors[:csv]).to be_present
208
+ expect(subject.log).to match(/csv is malformed/)
209
+ end
210
+ end
211
+
212
+ context 'with weird rows' do
213
+ before do
214
+ presenter_klass.class_eval do
215
+ define_csv_fields do |d|
216
+ d.field 'name', 'author'
217
+ end
218
+ end
219
+ end
220
+
221
+ let(:io) do
222
+ StringIO.new <<-CSV
223
+ foo,bar,bax
224
+ 1,2,3,2,1
225
+ ,,
226
+
227
+ hihihi
228
+ CSV
229
+ end
230
+
231
+ it 'always returns a hash per row' do
232
+ expect(subject.to_a.length).to eq 4
199
233
  end
200
234
  end
201
235
 
202
- it "should fail when all headers aren't to the left"
203
- it 'should ignore undefined variable columns'
204
236
  it 'should fail when variable columns not pair up correctly'
205
237
  end
data/spec/export_spec.rb CHANGED
@@ -5,7 +5,7 @@ describe SpeakyCsv::Export do
5
5
  let(:presenter_klass) { Class.new SpeakyCsv::Base }
6
6
 
7
7
  let(:io) { StringIO.new }
8
- subject { presenter_klass.new.exporter records.each }
8
+ subject { presenter_klass.exporter records.each }
9
9
 
10
10
  def output
11
11
  subject.to_a.join
@@ -66,9 +66,9 @@ Big Fiction
66
66
 
67
67
  let(:records) { [double('book1')] }
68
68
 
69
- it 'adds an error' do
69
+ it 'adds an error to the log' do
70
70
  subject.to_a
71
- expect(subject.errors[:unknown]).to be_present
71
+ expect(subject.log).to match(/unknown is not a method/)
72
72
  end
73
73
  end
74
74
 
@@ -148,7 +148,7 @@ id
148
148
 
149
149
  it 'adds an error' do
150
150
  subject.to_a
151
- expect(subject.errors[:reviews_unknown]).to be_present
151
+ expect(subject.log).to match(/reviews_unknown is not a method/)
152
152
  end
153
153
  end
154
154
 
@@ -168,7 +168,7 @@ id
168
168
 
169
169
  it 'adds an error' do
170
170
  subject.to_a
171
- expect(subject.errors[:unknowns]).to be_present
171
+ expect(subject.log).to match(/unknowns is not a method/)
172
172
  end
173
173
  end
174
174
  end
@@ -3,7 +3,7 @@ require 'database_cleaner'
3
3
  require 'pathname'
4
4
 
5
5
  ActiveRecord::Base.logger = Logger.new \
6
- Pathname.new(__dir__).join('../active_record.log').to_s
6
+ Pathname.new(__dir__).join('../../log/active_record.log').to_s
7
7
 
8
8
  ActiveRecord::Base.establish_connection adapter: 'sqlite3',
9
9
  database: ':memory:'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: speaky_csv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Hartford
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-19 00:00:00.000000000 Z
11
+ date: 2015-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -210,7 +210,9 @@ description: CSV importing and exporting for ActiveRecord and ActiveModel with a
210
210
  flavor
211
211
  email:
212
212
  - andy.hartford@cohealo.com
213
- executables: []
213
+ executables:
214
+ - console
215
+ - setup
214
216
  extensions: []
215
217
  extra_rdoc_files: []
216
218
  files:
@@ -218,17 +220,19 @@ files:
218
220
  - ".rubocop.yml"
219
221
  - ".travis.yml"
220
222
  - Gemfile
221
- - Gemfile.lock
222
223
  - Guardfile
223
224
  - LICENSE.txt
224
225
  - README.md
225
226
  - Rakefile
227
+ - bin/console
228
+ - bin/setup
226
229
  - lib/speaky_csv.rb
227
230
  - lib/speaky_csv/active_record_import.rb
228
231
  - lib/speaky_csv/attr_import.rb
229
232
  - lib/speaky_csv/base.rb
230
233
  - lib/speaky_csv/export.rb
231
234
  - lib/speaky_csv/version.rb
235
+ - log/.gitkeep
232
236
  - speaky_csv.gemspec
233
237
  - spec/active_record_import_spec.rb
234
238
  - spec/attr_import_spec.rb
data/Gemfile.lock DELETED
@@ -1,119 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- speaky_csv (0.0.1)
5
- activemodel
6
- activerecord
7
- activesupport
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- activemodel (4.2.5)
13
- activesupport (= 4.2.5)
14
- builder (~> 3.1)
15
- activerecord (4.2.5)
16
- activemodel (= 4.2.5)
17
- activesupport (= 4.2.5)
18
- arel (~> 6.0)
19
- activesupport (4.2.5)
20
- i18n (~> 0.7)
21
- json (~> 1.7, >= 1.7.7)
22
- minitest (~> 5.1)
23
- thread_safe (~> 0.3, >= 0.3.4)
24
- tzinfo (~> 1.1)
25
- arel (6.0.3)
26
- ast (2.1.0)
27
- astrolabe (1.3.1)
28
- parser (~> 2.2)
29
- builder (3.2.2)
30
- coderay (1.1.0)
31
- database_cleaner (1.5.1)
32
- diff-lcs (1.2.5)
33
- ffi (1.9.10)
34
- formatador (0.2.5)
35
- guard (2.13.0)
36
- formatador (>= 0.2.4)
37
- listen (>= 2.7, <= 4.0)
38
- lumberjack (~> 1.0)
39
- nenv (~> 0.1)
40
- notiffany (~> 0.0)
41
- pry (>= 0.9.12)
42
- shellany (~> 0.0)
43
- thor (>= 0.18.1)
44
- guard-compat (1.2.1)
45
- guard-rspec (4.6.4)
46
- guard (~> 2.1)
47
- guard-compat (~> 1.1)
48
- rspec (>= 2.99.0, < 4.0)
49
- i18n (0.7.0)
50
- json (1.8.3)
51
- listen (3.0.4)
52
- rb-fsevent (>= 0.9.3)
53
- rb-inotify (>= 0.9)
54
- lumberjack (1.0.9)
55
- method_source (0.8.2)
56
- minitest (5.8.2)
57
- nenv (0.2.0)
58
- notiffany (0.0.8)
59
- nenv (~> 0.1)
60
- shellany (~> 0.0)
61
- parser (2.2.3.0)
62
- ast (>= 1.1, < 3.0)
63
- powerpack (0.1.1)
64
- pry (0.10.3)
65
- coderay (~> 1.1.0)
66
- method_source (~> 0.8.1)
67
- slop (~> 3.4)
68
- rainbow (2.0.0)
69
- rake (10.4.2)
70
- rb-fsevent (0.9.6)
71
- rb-inotify (0.9.5)
72
- ffi (>= 0.5.0)
73
- rspec (3.3.0)
74
- rspec-core (~> 3.3.0)
75
- rspec-expectations (~> 3.3.0)
76
- rspec-mocks (~> 3.3.0)
77
- rspec-core (3.3.2)
78
- rspec-support (~> 3.3.0)
79
- rspec-expectations (3.3.1)
80
- diff-lcs (>= 1.2.0, < 2.0)
81
- rspec-support (~> 3.3.0)
82
- rspec-mocks (3.3.2)
83
- diff-lcs (>= 1.2.0, < 2.0)
84
- rspec-support (~> 3.3.0)
85
- rspec-support (3.3.0)
86
- rubocop (0.35.0)
87
- astrolabe (~> 1.3)
88
- parser (>= 2.2.3.0, < 3.0)
89
- powerpack (~> 0.1)
90
- rainbow (>= 1.99.1, < 3.0)
91
- ruby-progressbar (~> 1.7)
92
- ruby-progressbar (1.7.5)
93
- ruby_gntp (0.3.4)
94
- shellany (0.0.1)
95
- slop (3.6.0)
96
- sqlite3 (1.3.11)
97
- thor (0.19.1)
98
- thread_safe (0.3.5)
99
- tzinfo (1.2.2)
100
- thread_safe (~> 0.1)
101
-
102
- PLATFORMS
103
- ruby
104
-
105
- DEPENDENCIES
106
- bundler (> 1.5)
107
- database_cleaner
108
- guard-rspec
109
- rake
110
- rb-fsevent
111
- rb-inotify
112
- rspec (> 2.14.0)
113
- rubocop
114
- ruby_gntp
115
- speaky_csv!
116
- sqlite3
117
-
118
- BUNDLED WITH
119
- 1.10.3