table_utils 0.0.1

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.
@@ -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