table_utils 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ -rspec_helper
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
@@ -0,0 +1,88 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ table_utils (0.0.1)
5
+ activerecord
6
+ activerecord-import
7
+ ruby-progressbar
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activemodel (4.0.2)
13
+ activesupport (= 4.0.2)
14
+ builder (~> 3.1.0)
15
+ activerecord (4.0.2)
16
+ activemodel (= 4.0.2)
17
+ activerecord-deprecated_finders (~> 1.0.2)
18
+ activesupport (= 4.0.2)
19
+ arel (~> 4.0.0)
20
+ activerecord-deprecated_finders (1.0.3)
21
+ activerecord-import (0.4.1)
22
+ activerecord (>= 3.0)
23
+ activesupport (4.0.2)
24
+ i18n (~> 0.6, >= 0.6.4)
25
+ minitest (~> 4.2)
26
+ multi_json (~> 1.3)
27
+ thread_safe (~> 0.1)
28
+ tzinfo (~> 0.3.37)
29
+ arel (4.0.1)
30
+ atomic (1.1.14)
31
+ builder (3.1.4)
32
+ coderay (1.1.0)
33
+ diff-lcs (1.2.5)
34
+ ffi (1.9.3)
35
+ formatador (0.2.4)
36
+ guard (1.8.3)
37
+ formatador (>= 0.2.4)
38
+ listen (~> 1.3)
39
+ lumberjack (>= 1.0.2)
40
+ pry (>= 0.9.10)
41
+ thor (>= 0.14.6)
42
+ guard-rspec (3.1.0)
43
+ guard (>= 1.8)
44
+ rspec (~> 2.13)
45
+ i18n (0.6.9)
46
+ listen (1.3.1)
47
+ rb-fsevent (>= 0.9.3)
48
+ rb-inotify (>= 0.9)
49
+ rb-kqueue (>= 0.2)
50
+ lumberjack (1.0.4)
51
+ method_source (0.8.2)
52
+ minitest (4.7.5)
53
+ multi_json (1.8.2)
54
+ pry (0.9.12.4)
55
+ coderay (~> 1.0)
56
+ method_source (~> 0.8)
57
+ slop (~> 3.4)
58
+ rb-fsevent (0.9.3)
59
+ rb-inotify (0.9.3)
60
+ ffi (>= 0.5.0)
61
+ rb-kqueue (0.2.0)
62
+ ffi (>= 0.5.0)
63
+ rspec (2.14.1)
64
+ rspec-core (~> 2.14.0)
65
+ rspec-expectations (~> 2.14.0)
66
+ rspec-mocks (~> 2.14.0)
67
+ rspec-core (2.14.7)
68
+ rspec-expectations (2.14.4)
69
+ diff-lcs (>= 1.1.3, < 2.0)
70
+ rspec-mocks (2.14.4)
71
+ ruby-progressbar (1.3.2)
72
+ slop (3.4.7)
73
+ sqlite3 (1.3.8)
74
+ thor (0.18.1)
75
+ thread_safe (0.1.3)
76
+ atomic
77
+ tzinfo (0.3.38)
78
+
79
+ PLATFORMS
80
+ ruby
81
+
82
+ DEPENDENCIES
83
+ bundler (~> 1.3)
84
+ guard (< 2.0)
85
+ guard-rspec
86
+ rspec
87
+ sqlite3
88
+ table_utils!
@@ -0,0 +1,9 @@
1
+
2
+ guard :rspec, cmd: "bundle exec rspec", all_after_pass: true do
3
+ watch(%r{^spec/.+_spec\.rb$})
4
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
5
+ watch("spec/spec_helper.rb") { "spec" }
6
+
7
+ watch("lib/data_source.rb") { "spec/lib/rake/table_import_spec.rb" }
8
+ end
9
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Artem Baguinski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ table_utils
2
+ ===========
3
+
4
+ utilities for working with real world tabular data
@@ -0,0 +1,63 @@
1
+ require "active_record"
2
+ require "activerecord-import"
3
+ require "table_utils/progress"
4
+
5
+ class DataSource
6
+ attr_reader :table_name, :input_path
7
+
8
+ def initialize table_name, input_path, csv_opts = {}, &block
9
+ @table_name, @input_path = table_name, input_path
10
+ @csv_opts = csv_opts ? csv_opts.dup : {}
11
+ @block = block
12
+ end
13
+
14
+ def import
15
+ batch = []
16
+ TableUtils::Progress.over csv do |row, bar|
17
+ batch << common_columns.map{ |c| row[c] }
18
+ if batch.count >= 1000 || bar.finished?
19
+ model.import common_columns, batch, validate: false
20
+ batch = []
21
+ end
22
+ end
23
+ end
24
+
25
+ def table_exists?
26
+ conn.table_exists? table_name
27
+ end
28
+
29
+ def drop_table
30
+ conn.drop_table table_name
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :csv_opts, :block
36
+
37
+ def conn
38
+ @conn ||= ActiveRecord::Base.connection
39
+ end
40
+
41
+ def model
42
+ conn.create_table table_name, &block unless table_exists?
43
+ _table_name = table_name
44
+ @model ||= Class.new(ActiveRecord::Base) { self.table_name = _table_name }
45
+ end
46
+
47
+ def csv
48
+ @csv ||= begin
49
+ csv_opts[:headers] ||= model.column_names - %w(id created_at updated_at)
50
+ csv_opts[:return_headers] = true
51
+ CSV.open(input_path, csv_opts).tap do |csv|
52
+ csv.shift
53
+ @common_columns = model.column_names & csv.headers
54
+ csv.shift if Array === csv_opts[:headers]
55
+ end
56
+ end
57
+ end
58
+
59
+ def common_columns
60
+ csv
61
+ @common_columns
62
+ end
63
+ end
@@ -0,0 +1,7 @@
1
+ module Rake::DSL
2
+ attr_writer :logger
3
+
4
+ def logger
5
+ @logger ||= Logger.new STDOUT
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ require "data_source"
2
+ require "rake/logger"
3
+
4
+ module Rake::DSL
5
+ def table_import args, &block
6
+ table_name = args.keys[0]
7
+ task args.extract!(table_name) do |t|
8
+ source = DataSource.new table_name, t.prerequisites[0], args[:csv], &block
9
+ unless source.table_exists?
10
+ begin
11
+ logger.info { "Importing #{source.table_name} from #{source.input_path}" }
12
+ source.import
13
+ rescue
14
+ if source.table_exists?
15
+ logger.warn { "dropping #{table_name} due to errors during import" }
16
+ source.drop_table
17
+ end
18
+ raise
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ require "table_utils/limit_loops"
2
+ require "table_utils/progress"
3
+
@@ -0,0 +1,21 @@
1
+ module TableUtils
2
+ class LimitLoops
3
+ attr_reader :total
4
+
5
+ def initialize max_count
6
+ @total = @left_count = max_count
7
+ end
8
+
9
+ def limit
10
+ catch(self) { yield self }
11
+ end
12
+
13
+ def check!
14
+ throw self if @left_count and (@left_count -= 1) <= 0
15
+ end
16
+
17
+ def self.to max_count, &block
18
+ LimitLoops.new(max_count).limit &block
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,52 @@
1
+ require "ruby-progressbar"
2
+
3
+ module TableUtils
4
+ module Progress
5
+ DefaultOptions = {
6
+ format: "%a |%b %c/%C =>%i| %E",
7
+ throttle_rate: 0.1,
8
+ }
9
+
10
+ def self.bar options = {}
11
+ bar = ProgressBar.create DefaultOptions.merge options
12
+ bar.format("%a: |%i| %c") if bar.total == nil
13
+ if block_given?
14
+ begin
15
+ yield bar
16
+ ensure
17
+ if bar.total
18
+ bar.finish unless bar.finished?
19
+ end
20
+ end
21
+ else
22
+ bar
23
+ end
24
+ end
25
+
26
+ def self.over enum, options = {}
27
+ options = options.dup
28
+
29
+ unless options.include? :total
30
+ options[:total] = enum.count
31
+ end
32
+
33
+ Progress.bar options do |bar|
34
+ enum.each do |i|
35
+ bar.increment
36
+ yield i, bar
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+
44
+ require "csv"
45
+ class CSV
46
+ def count
47
+ oldpos = tell if respond_to?(:tell)
48
+ super
49
+ ensure
50
+ seek oldpos if respond_to?(:seek)
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module TableUtils
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,9 @@
1
+ planet,earth_masses,jupiter_masses
2
+ Mercury,0.0553,0.000174
3
+ Venus,0.815,0.00256
4
+ Earth,1,0.00315
5
+ Mars,0.107,0.000338
6
+ Jupiter,318,1
7
+ Saturn,95.2,0.299
8
+ Uranus,14.5,0.0457
9
+ Neptune,17.2,0.0540
@@ -0,0 +1,42 @@
1
+ require "data_source"
2
+
3
+ describe DataSource do
4
+ include_context "planets"
5
+ include_context "silent_progress"
6
+ include_context "in-memory db"
7
+
8
+ let(:more_args) { [] }
9
+ let(:source) {
10
+ DataSource.new :planets, fixture("table.csv"), *more_args do |t|
11
+ t.string :planet
12
+ t.float :earth_masses
13
+ t.float :jupiter_masses
14
+ end
15
+ }
16
+ before { source.import }
17
+ let(:model) { Class.new(ActiveRecord::Base) { self.table_name = :planets } }
18
+ let(:records_without_id) { model.all.map{|r| r.attributes.tap{|h| h.delete("id")}} }
19
+
20
+ shared_examples "imports a table" do
21
+ it "imports a table" do
22
+ expect( conn.table_exists? :planets ).to be_true
23
+ expect( model.column_names ).to match_array planet_headers + %w(id)
24
+ expect( records_without_id ).to match_array planets_table
25
+ end
26
+ end
27
+
28
+ context "with implicit csv headers" do
29
+ include_examples "imports a table"
30
+ end
31
+
32
+ context "with explicit csv headers" do
33
+ let(:more_args) { [headers: planet_headers] }
34
+ include_examples "imports a table"
35
+ end
36
+
37
+ context "with csv headers from the first row" do
38
+ let(:more_args) { [headers: true] }
39
+ include_examples "imports a table"
40
+ end
41
+
42
+ end
@@ -0,0 +1,68 @@
1
+ require "rake"
2
+ require "rake/table_import"
3
+ include Rake::DSL
4
+
5
+ describe "Rake::DSL.table_import" do
6
+ let(:rake) { Rake::Application.new }
7
+
8
+ before(:each) do
9
+ Rake.application = rake
10
+ logger.level = Logger::UNKNOWN
11
+ task "path"
12
+ end
13
+
14
+ it "unrolls the arguments and passes them to DataSource constructor" do
15
+ catch :done do
16
+ DataSource.should_receive(:new).with(:table_name, "path", :csv_options).and_throw :done
17
+ table_import :table_name => "path", csv: :csv_options
18
+ rake[:table_name].invoke
19
+ end
20
+ end
21
+
22
+ it "passes nil for csv_options if not supplied" do
23
+ catch :done do
24
+ DataSource.should_receive(:new).with(:table_name, "path", nil).and_throw :done
25
+ table_import :table_name => "path"
26
+ rake[:table_name].invoke
27
+ end
28
+ end
29
+
30
+ shared_context "mock source" do
31
+ let(:source) { double() }
32
+ before { DataSource.stub(:new) { source } }
33
+ end
34
+
35
+ context "table doesn't exist" do
36
+ include_context "mock source"
37
+ before { source.stub(:table_exists?) { false } }
38
+ it "import from the source" do
39
+ expect(source).to receive(:import).with()
40
+ table_import :table_name => "path"
41
+ rake[:table_name].invoke
42
+ end
43
+
44
+ context "import fails" do
45
+ before {
46
+ source.stub(:import) {
47
+ source.stub(:table_exists?) { true }
48
+ raise RuntimeError, "mock import failure"
49
+ }
50
+ }
51
+ it "should drop the table and reraise the exception" do
52
+ expect(source).to receive(:drop_table)
53
+ table_import :table_name => "path"
54
+ expect{rake[:table_name].invoke}.to raise_error("mock import failure")
55
+ end
56
+ end
57
+ end
58
+
59
+ context "table exists" do
60
+ include_context "mock source"
61
+ before { source.stub(:table_exists?) { true } }
62
+ it "doesn't import" do
63
+ expect(source).not_to receive(:import)
64
+ table_import :table_name => "path"
65
+ rake[:table_name].invoke
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,35 @@
1
+ require "table_utils/limit_loops"
2
+ include TableUtils
3
+
4
+ describe LimitLoops do
5
+ let(:limit_value) { 5 }
6
+ let(:default_count) { 10 }
7
+
8
+ describe "#total" do
9
+ subject { LimitLoops.new limit_value }
10
+ its(:total) { should == limit_value }
11
+ end
12
+
13
+ describe "::limit_loops + #check!" do
14
+ it "limits number of iterations to limit value" do
15
+ counter = 0
16
+ LimitLoops.to limit_value do |limit|
17
+ default_count.times do
18
+ counter += 1
19
+ limit.check!
20
+ end
21
+ end
22
+ expect(counter).to eq limit_value
23
+ end
24
+ it "doesn't limit number of iterations when given nil" do
25
+ counter = 0
26
+ LimitLoops.to nil do |limit|
27
+ default_count.times do
28
+ counter += 1
29
+ limit.check!
30
+ end
31
+ end
32
+ expect(counter).to eq default_count
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ require "table_utils/progress"
2
+
3
+ include TableUtils
4
+
5
+ describe Progress do
6
+ include_context "silent_progress"
7
+
8
+ describe "::bar" do
9
+ context "without block" do
10
+ subject { Progress.bar }
11
+ it { should be_a ProgressBar::Base }
12
+ end
13
+
14
+ context "with block" do
15
+ it "should yield a ProgressBar::Base instance" do
16
+ yielded = nil
17
+ Progress.bar do |bar|
18
+ yielded = bar
19
+ end
20
+ expect( yielded ).to be_a ProgressBar::Base
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "::over" do
26
+ let(:enum) { [:foo,:bar] }
27
+ let(:yielded) { [] }
28
+ it "iterates over supplied enum" do
29
+ Progress.over enum, output: dummy_io do |item,bar|
30
+ expect(bar).to be_a ProgressBar::Base
31
+ expect(bar.total).to eq enum.count
32
+ yielded << item
33
+ end
34
+ expect(yielded).to eq enum
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ require "active_record"
2
+ require "csv"
3
+ require "ruby-progressbar"
4
+
5
+ def fixture basename
6
+ File.expand_path("../fixtures/#{basename}", __FILE__)
7
+ end
8
+
9
+ shared_context "planets" do
10
+ let(:planets_table) {
11
+ CSV.read( fixture("table.csv"),
12
+ headers: true,
13
+ converters: :numeric )
14
+ .map &:to_hash
15
+ }
16
+ let(:planets) { planets_table.map{|row| row["planet"]} }
17
+ let(:planet_headers) { planets_table[0].keys }
18
+ end
19
+
20
+ shared_context "silent_progress" do
21
+ let(:dummy_io) { StringIO.new }
22
+ before(:each) { ProgressBar::Base.any_instance.stub(:output) { dummy_io } }
23
+ end
24
+
25
+ shared_context "in-memory db" do
26
+ around(:each) do |example|
27
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
28
+ ActiveRecord::Base.transaction {
29
+ example.run
30
+ raise ActiveRecord::Rollback, "clear the database"
31
+ }
32
+ end
33
+ let(:conn) { ActiveRecord::Base.connection }
34
+ end
35
+
@@ -0,0 +1,30 @@
1
+ $LOAD_PATH << File.expand_path("../lib", __FILE__)
2
+
3
+ require "table_utils/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "table_utils"
7
+ s.version = TableUtils::VERSION
8
+ s.summary = "utilities for working with real world tabular data"
9
+ s.description = "make dealing with real life tables simpler"
10
+ s.author = "Artem Baguinski"
11
+ s.email = "femistofel@gmail.com"
12
+ s.homepage = "https://github.com/artm/table_utils"
13
+ s.license = "MIT"
14
+
15
+ s.files = `git ls-files`.split($/)
16
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency "activerecord"
21
+ s.add_runtime_dependency "activerecord-import"
22
+ s.add_runtime_dependency "ruby-progressbar"
23
+
24
+ s.add_development_dependency "bundler", "~> 1.3"
25
+ s.add_development_dependency "rspec"
26
+ s.add_development_dependency "guard", "< 2.0"
27
+ s.add_development_dependency "guard-rspec"
28
+ s.add_development_dependency "sqlite3"
29
+ end
30
+
metadata ADDED
@@ -0,0 +1,200 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: table_utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Artem Baguinski
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: activerecord-import
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: ruby-progressbar
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.3'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.3'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: guard
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - <
100
+ - !ruby/object:Gem::Version
101
+ version: '2.0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - <
108
+ - !ruby/object:Gem::Version
109
+ version: '2.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: guard-rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: sqlite3
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ description: make dealing with real life tables simpler
143
+ email: femistofel@gmail.com
144
+ executables: []
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - .gitignore
149
+ - .rspec
150
+ - Gemfile
151
+ - Gemfile.lock
152
+ - Guardfile
153
+ - LICENSE
154
+ - README.md
155
+ - lib/data_source.rb
156
+ - lib/rake/logger.rb
157
+ - lib/rake/table_import.rb
158
+ - lib/table_utils.rb
159
+ - lib/table_utils/limit_loops.rb
160
+ - lib/table_utils/progress.rb
161
+ - lib/table_utils/version.rb
162
+ - spec/fixtures/table.csv
163
+ - spec/lib/data_source_spec.rb
164
+ - spec/lib/rake/table_import_spec.rb
165
+ - spec/lib/table_utils/limit_loops_spec.rb
166
+ - spec/lib/table_utils/progress_spec.rb
167
+ - spec/spec_helper.rb
168
+ - table_utils.gemspec
169
+ homepage: https://github.com/artm/table_utils
170
+ licenses:
171
+ - MIT
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ none: false
184
+ requirements:
185
+ - - ! '>='
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ requirements: []
189
+ rubyforge_project:
190
+ rubygems_version: 1.8.23
191
+ signing_key:
192
+ specification_version: 3
193
+ summary: utilities for working with real world tabular data
194
+ test_files:
195
+ - spec/fixtures/table.csv
196
+ - spec/lib/data_source_spec.rb
197
+ - spec/lib/rake/table_import_spec.rb
198
+ - spec/lib/table_utils/limit_loops_spec.rb
199
+ - spec/lib/table_utils/progress_spec.rb
200
+ - spec/spec_helper.rb