conformist 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.2.0 / 2012-08-18
4
+
5
+ * `Conformist::Schema#confrom` takes option to skip first row.
6
+ * Removed deprecated classes and warnings.
7
+
3
8
  ## 0.1.3 / 2012-02-09
4
9
 
5
10
  * Column indexes are implicitly incremented when the index argument is omitted. Implicit indexing is all or nothing.
@@ -29,7 +34,7 @@
29
34
  ## 0.0.2 / 2011-04-28
30
35
 
31
36
  * Column#values_in will be nil if the index is out of range rather than an empty string. This is consistent with CSV
32
- * Fixed 1.8.7 and JRuby dependancies. Gemspec will not let you specify dependancies based on the version of Ruby. Everyone gets it
37
+ * Fixed 1.8.7 and JRuby dependencies. Gemspec will not let you specify dependencies based on the version of Ruby. Everyone gets it
33
38
 
34
39
  ## 0.0.1 / 2011-04-27
35
40
 
data/README.md CHANGED
@@ -8,7 +8,7 @@ Bend CSVs to your will with declarative schemas. Map one or many columns, prepro
8
8
 
9
9
  ## Quick and Dirty Examples
10
10
 
11
- Open a CSV file and declare a schema. A schema compromises of columns. A column takes an arbitary name followed by its position in the input. A column may be derived from multiple positions.
11
+ Open a CSV file and declare a schema. A schema compromises of columns. A column takes an arbitrary name followed by its position in the input. A column may be derived from multiple positions.
12
12
 
13
13
  ``` ruby
14
14
  require 'conformist'
@@ -177,6 +177,15 @@ CSV.open('~/file.csv').responds_to? :each # => true
177
177
  [[], [], []].responds_to? :each # => true
178
178
  ```
179
179
 
180
+ #### Header Row
181
+
182
+ `#conform` takes an option to skip the first row of input. Given a typical CSV document,
183
+ the first row is the header row and irrelevant for enumeration.
184
+
185
+ ``` ruby
186
+ schema.conform CSV.open('~/file_with_headers.csv'), :skip_first => true
187
+ ```
188
+
180
189
  #### Enumerator
181
190
 
182
191
  `#conform` is lazy, returning an [Enumerator](http://www.ruby-doc.org/core-1.9.3/Enumerator.html). Input is not parsed until you call `#each`, `#map` or any method defined in [Enumerable](http://www.ruby-doc.org/core-1.9.3/Enumerable.html). That means schemas can be assigned now and evaluated later. `#each` has the lowest memory footprint because it does not build a collection.
@@ -326,7 +335,7 @@ See CHANGELOG.md for a full list of changes.
326
335
  * MRI 1.8.7
327
336
  * JRuby 1.6.5
328
337
 
329
- ## Dependancies
338
+ ## Dependencies
330
339
 
331
340
  No explicit dependencies, although `CSV` and `Spreadsheet` are commonly used.
332
341
 
data/conformist.gemspec CHANGED
@@ -11,20 +11,11 @@ Gem::Specification.new do |s|
11
11
  s.homepage = "https://github.com/tatey/conformist"
12
12
  s.summary = %q{Bend CSVs to your will with declarative schemas.}
13
13
  s.description = %q{Bend CSVs to your will with declarative schemas.}
14
- s.post_install_message = <<-EOS
15
- ********************************************************************************
16
-
17
- Upgrading from <= 0.0.3? You should be aware of breaking changes. See
18
- https://github.com/tatey/conformist and skip to "Upgrading from 0.0.3 to
19
- 0.1.1" to learn more. Conformist will raise helpful messages where necessary.
20
-
21
- ********************************************************************************
22
- EOS
23
14
 
24
15
  s.rubyforge_project = "conformist"
25
16
 
26
17
  s.required_ruby_version = '>= 1.8.7'
27
-
18
+
28
19
  s.add_development_dependency 'minitest'
29
20
  s.add_development_dependency 'rake'
30
21
  s.add_development_dependency 'spreadsheet'
data/lib/conformist.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'forwardable'
2
2
 
3
- require 'conformist/base'
4
3
  require 'conformist/builder'
5
4
  require 'conformist/column'
6
5
  require 'conformist/hash_struct'
@@ -11,15 +10,11 @@ module Conformist
11
10
  require 'generator'
12
11
  Enumerator = Generator
13
12
  end
14
-
13
+
15
14
  def self.extended base
16
15
  base.extend Schema
17
16
  end
18
-
19
- def self.foreach *args, &block
20
- raise "`Conformist.foreach` has been removed, use something like `[MySchema1.conform(file1), MySchema2.conform(file2)].each(&block)` instead (#{caller.first})"
21
- end
22
-
17
+
23
18
  def self.new *args, &block
24
19
  Class.new { include Schema }.new *args, &block
25
20
  end
@@ -1,13 +1,13 @@
1
1
  module Conformist
2
2
  class Column
3
3
  attr_accessor :name, :indexes, :preprocessor
4
-
4
+
5
5
  def initialize name, *indexes, &preprocessor
6
6
  self.name = name
7
7
  self.indexes = indexes
8
8
  self.preprocessor = preprocessor
9
9
  end
10
-
10
+
11
11
  def values_in enumerable
12
12
  values = Array(enumerable).values_at(*indexes).map do |value|
13
13
  if value.respond_to? :strip
@@ -15,8 +15,8 @@ module Conformist
15
15
  else
16
16
  value
17
17
  end
18
- end
19
- values = values.first if values.size == 1
18
+ end
19
+ values = values.first if values.size == 1
20
20
  if preprocessor
21
21
  preprocessor.call values
22
22
  else
@@ -1,31 +1,31 @@
1
1
  module Conformist
2
2
  class HashStruct
3
3
  extend Forwardable
4
-
4
+
5
5
  attr_accessor :attributes
6
-
6
+
7
7
  def_delegators :attributes, :[], :[]=, :fetch, :key?
8
-
8
+
9
9
  def initialize attributes = {}
10
10
  self.attributes = attributes
11
11
  end
12
-
12
+
13
13
  def merge other
14
14
  self.class.new.tap do |instance|
15
15
  instance.attributes = attributes.merge other
16
16
  end
17
17
  end
18
-
18
+
19
19
  def == other
20
20
  other.class == self.class && attributes == other.attributes
21
21
  end
22
-
22
+
23
23
  protected
24
-
24
+
25
25
  def respond_to_missing? method, include_private
26
26
  key?(method) || super
27
27
  end
28
-
28
+
29
29
  def method_missing method, *args, &block
30
30
  fetch(method) { super }
31
31
  end
@@ -4,23 +4,19 @@ module Conformist
4
4
  base.send :include, InstanceExtensions
5
5
  base.send :include, Methods
6
6
  end
7
-
7
+
8
8
  def self.extended base
9
9
  base.extend ClassExtensions
10
10
  base.extend Methods
11
11
  end
12
-
12
+
13
13
  module ClassExtensions
14
14
  def inherited base
15
15
  base.builder = builder.dup
16
16
  base.columns = columns.dup
17
17
  end
18
-
19
- def load *args
20
- raise "``#{self.class}.load` has been removed, use something like `#{self.class}.conform(file).each(&block)` instead (#{caller.first})"
21
- end
22
18
  end
23
-
19
+
24
20
  module InstanceExtensions
25
21
  def initialize super_schema = nil, &block
26
22
  if super_schema
@@ -32,7 +28,7 @@ module Conformist
32
28
  end
33
29
  end
34
30
  end
35
-
31
+
36
32
  module Methods
37
33
  def builder
38
34
  @builder ||= Builder
@@ -55,13 +51,15 @@ module Conformist
55
51
  @columns = value
56
52
  end
57
53
 
58
- def conform enumerables
54
+ def conform enumerables, options = {}
55
+ options = options.dup
59
56
  Enumerator.new do |yielder|
60
57
  enumerables.each do |enumerable|
58
+ next if options.delete :skip_first
61
59
  yielder.yield builder.call(self, enumerable)
62
60
  end
63
61
  end
64
- end
62
+ end
65
63
  end
66
64
  end
67
65
  end
@@ -1,3 +1,3 @@
1
1
  module Conformist
2
- VERSION = '0.1.3'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -0,0 +1,5 @@
1
+ Name,Age,Gender
2
+ Aaron,21,Male
3
+ Bec,30,Female
4
+ Charlie,50,Male
5
+ Debbie,26,Female
@@ -0,0 +1,7 @@
1
+ class Citizens
2
+ extend Conformist
3
+
4
+ column :name, 0
5
+ column :age, 1
6
+ column :gender, 2
7
+ end
data/test/schemas/fcc.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  class FCC
2
2
  extend Conformist
3
-
3
+
4
4
  column :name, 10, 11 do |values|
5
5
  "#{values[0].upcase}, #{values[-1]}"
6
6
  end
@@ -4,42 +4,42 @@ class Conformist::ColumnTest < MiniTest::Unit::TestCase
4
4
  def stub_row
5
5
  ('a'..'d').to_a
6
6
  end
7
-
7
+
8
8
  def test_name
9
9
  column = Column.new :foo
10
10
  assert_equal :foo, column.name
11
11
  end
12
-
12
+
13
13
  def test_one_index
14
14
  column = Column.new :foo, 0
15
15
  assert_equal 'a', column.values_in(stub_row)
16
16
  end
17
-
17
+
18
18
  def test_preprocess_with_one_index
19
19
  column = Column.new(:foo, 0) { |value| value.upcase }
20
20
  assert_equal 'A', column.values_in(stub_row)
21
21
  end
22
-
22
+
23
23
  def test_many_indexes
24
24
  column = Column.new :foo, 1, 2, 3
25
25
  assert_equal ['b', 'c', 'd'], column.values_in(stub_row)
26
26
  end
27
-
27
+
28
28
  def test_preprocess_with_many_indexes
29
29
  column = Column.new(:foo, 1, 2, 3) { |values| values.reverse }
30
30
  assert_equal ['d', 'c', 'b'], column.values_in(stub_row)
31
31
  end
32
-
32
+
33
33
  def test_virtual
34
34
  column = Column.new(:foo) { 'a' }
35
35
  assert_equal 'a', column.values_in(stub_row)
36
36
  end
37
-
37
+
38
38
  def test_strip_whitespace
39
39
  column = Column.new :foo, 0
40
40
  assert_equal 'a', column.values_in([' a '])
41
41
  end
42
-
42
+
43
43
  def test_array
44
44
  mock = MiniTest::Mock.new
45
45
  mock.expect :to_a, ['a']
@@ -48,7 +48,7 @@ class Conformist::ColumnTest < MiniTest::Unit::TestCase
48
48
  assert_equal 'a', column.values_in('a')
49
49
  assert_equal 'a', column.values_in(mock)
50
50
  end
51
-
51
+
52
52
  def test_nil
53
53
  column = Column.new :foo, 0
54
54
  assert_nil column.values_in([])
@@ -5,7 +5,7 @@ class Conformist::HashStructTest < MiniTest::Unit::TestCase
5
5
  assert_equal({:a => 1}, HashStruct.new({:a => 1}).attributes)
6
6
  assert_empty HashStruct.new.attributes
7
7
  end
8
-
8
+
9
9
  def test_delegates
10
10
  hash = HashStruct.new
11
11
  assert hash.respond_to?(:[])
@@ -13,7 +13,7 @@ class Conformist::HashStructTest < MiniTest::Unit::TestCase
13
13
  assert hash.respond_to?(:fetch)
14
14
  assert hash.respond_to?(:key?)
15
15
  end
16
-
16
+
17
17
  def test_equality
18
18
  hash1 = HashStruct.new :a => 1
19
19
  hash2 = HashStruct.new :a => 1
@@ -23,7 +23,7 @@ class Conformist::HashStructTest < MiniTest::Unit::TestCase
23
23
  assert_equal hash1, hash2
24
24
  refute_equal hash1, hash3
25
25
  end
26
-
26
+
27
27
  def test_merge
28
28
  hash1 = HashStruct.new
29
29
  hash2 = hash1.merge :a => 1
@@ -31,13 +31,13 @@ class Conformist::HashStructTest < MiniTest::Unit::TestCase
31
31
  refute_equal 1, hash1[:a]
32
32
  assert_equal 1, hash2[:a]
33
33
  end
34
-
34
+
35
35
  def test_readers_with_method_missing
36
36
  hash = HashStruct.new :a => 1, :c_d => 1
37
37
  assert_equal 1, hash.a
38
38
  assert_equal 1, hash.c_d
39
39
  end
40
-
40
+
41
41
  if respond_to? :respond_to_missing? # Compatible with 1.9
42
42
  def test_readers_with_respond_to_missing
43
43
  hash = HashStruct.new :a => 1, :c_d => 1
@@ -17,7 +17,7 @@ class Conformist::SchemaTest < MiniTest::Unit::TestCase
17
17
  end
18
18
  assert_equal 2, anonymous.columns.size
19
19
  end
20
-
20
+
21
21
  def test_builder_reader
22
22
  assert_equal Builder, Class.new { extend Schema }.builder
23
23
  end
@@ -58,6 +58,12 @@ class Conformist::SchemaTest < MiniTest::Unit::TestCase
58
58
  assert definition.conform([]).respond_to?(:map)
59
59
  end
60
60
 
61
+ def test_conform_skip_first
62
+ definition = Class.new { extend Schema }
63
+ definition.column :a, 0
64
+ assert_equal HashStruct.new({:a => 'value'}), definition.conform(['header', 'value'], :skip_first => true).first
65
+ end
66
+
61
67
  def test_conform_calls_builders_call_method
62
68
  definition = Class.new { extend Schema }
63
69
  definition.builder = lambda { |definition, value| value }
@@ -72,10 +78,4 @@ class Conformist::SchemaTest < MiniTest::Unit::TestCase
72
78
  assert_equal [0, 1], child1.columns
73
79
  assert_equal [0, 2], child2.columns
74
80
  end
75
-
76
- def test_load
77
- assert_raises RuntimeError do
78
- Class.new { extend Schema }.load
79
- end
80
- end
81
81
  end
@@ -7,13 +7,7 @@ class ConformistTest < MiniTest::Unit::TestCase
7
7
  assert definition.respond_to?(:columns)
8
8
  assert definition.respond_to?(:conform)
9
9
  end
10
-
11
- def test_foreach
12
- assert_raises RuntimeError do
13
- Conformist.foreach
14
- end
15
- end
16
-
10
+
17
11
  def test_new
18
12
  assert Conformist.new.class.include?(Schema)
19
13
  end
@@ -1,6 +1,7 @@
1
1
  require 'csv'
2
2
  require 'helper'
3
3
  require 'schemas/acma'
4
+ require 'schemas/citizens'
4
5
  require 'schemas/fcc'
5
6
  require 'spreadsheet'
6
7
 
@@ -22,19 +23,25 @@ class IntegrationTest < MiniTest::Unit::TestCase
22
23
  last = enumerable.to_a.last
23
24
  assert_equal HashStruct.new(:name=>'CRAFERS', :callsign=>'ADS10', :latitude=>'34 58 57S'), last
24
25
  end
25
-
26
+
27
+ def test_class_with_csv_including_headers
28
+ enumerable = Citizens.conform open_csv('citizens.csv'), :skip_first => true
29
+ first = enumerable.to_a.first
30
+ assert_equal HashStruct.new(:name => 'Aaron', :age => '21', :gender => 'Male'), first
31
+ end
32
+
26
33
  def test_inherited_class_with_csv
27
34
  enumerable = ACMA::Digital.conform open_csv('acma.csv')
28
35
  last = enumerable.to_a.last
29
36
  assert_equal HashStruct.new(:name=>'CRAFERS', :callsign=>'ADS10', :latitude=>'34 58 57S', :signal_type => 'digital'), last
30
37
  end
31
-
38
+
32
39
  def test_class_with_psv
33
40
  enumerable = FCC.conform open_csv('fcc.txt', :col_sep => '|')
34
41
  last = enumerable.to_a.last
35
42
  assert_equal HashStruct.new(:name => 'LOS ANGELES, CA', :callsign => 'KVTU-LP', :latitude => '34 13 38.00 N', :signtal_type => 'digital'), last
36
43
  end
37
-
44
+
38
45
  def test_instance_with_spreadsheet
39
46
  book = Spreadsheet.open fixture('states.xls')
40
47
  sheet = book.worksheet 0
@@ -43,7 +50,7 @@ class IntegrationTest < MiniTest::Unit::TestCase
43
50
  last = enumerable.to_a.last
44
51
  assert_equal HashStruct.new(:state => 'QLD'), last
45
52
  end
46
-
53
+
47
54
  def test_instance_with_array_of_arrays
48
55
  data = Array.new.tap do |d|
49
56
  d << ['NSW', 'New South Wales', 'Sydney']
@@ -60,7 +67,7 @@ class IntegrationTest < MiniTest::Unit::TestCase
60
67
  last = enumerable.to_a.last
61
68
  assert_equal HashStruct.new(:state => 'QLD, Queensland', :capital => 'Brisbane'), last
62
69
  end
63
-
70
+
64
71
  def test_inherited_instance_with_array_of_arrays
65
72
  data = Array.new.tap do |d|
66
73
  d << ['NSW', 'New South Wales', 'Sydney']
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conformist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-09 00:00:00.000000000 Z
12
+ date: 2012-08-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
16
- requirement: &70317078761180 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70317078761180
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rake
27
- requirement: &70317078759240 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70317078759240
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: spreadsheet
38
- requirement: &70317078758780 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,7 +53,12 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70317078758780
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  description: Bend CSVs to your will with declarative schemas.
48
63
  email:
49
64
  - tate@tatey.com
@@ -60,19 +75,19 @@ files:
60
75
  - Rakefile
61
76
  - conformist.gemspec
62
77
  - lib/conformist.rb
63
- - lib/conformist/base.rb
64
78
  - lib/conformist/builder.rb
65
79
  - lib/conformist/column.rb
66
80
  - lib/conformist/hash_struct.rb
67
81
  - lib/conformist/schema.rb
68
82
  - lib/conformist/version.rb
69
83
  - test/fixtures/acma.csv
84
+ - test/fixtures/citizens.csv
70
85
  - test/fixtures/fcc.txt
71
86
  - test/fixtures/states.xls
72
87
  - test/helper.rb
73
88
  - test/schemas/acma.rb
89
+ - test/schemas/citizens.rb
74
90
  - test/schemas/fcc.rb
75
- - test/unit/conformist/base_test.rb
76
91
  - test/unit/conformist/builder_test.rb
77
92
  - test/unit/conformist/column_test.rb
78
93
  - test/unit/conformist/hash_struct_test.rb
@@ -81,11 +96,7 @@ files:
81
96
  - test/unit/integration_test.rb
82
97
  homepage: https://github.com/tatey/conformist
83
98
  licenses: []
84
- post_install_message: ! "********************************************************************************\n\n
85
- \ Upgrading from <= 0.0.3? You should be aware of breaking changes. See\n https://github.com/tatey/conformist
86
- and skip to \"Upgrading from 0.0.3 to \n 0.1.1\" to learn more. Conformist will
87
- raise helpful messages where necessary.\n\n********************************************************************************
88
- \ \n"
99
+ post_install_message:
89
100
  rdoc_options: []
90
101
  require_paths:
91
102
  - lib
@@ -103,21 +114,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
114
  version: '0'
104
115
  segments:
105
116
  - 0
106
- hash: -2607692248856246044
117
+ hash: -2869076359774702419
107
118
  requirements: []
108
119
  rubyforge_project: conformist
109
- rubygems_version: 1.8.11
120
+ rubygems_version: 1.8.23
110
121
  signing_key:
111
122
  specification_version: 3
112
123
  summary: Bend CSVs to your will with declarative schemas.
113
124
  test_files:
114
125
  - test/fixtures/acma.csv
126
+ - test/fixtures/citizens.csv
115
127
  - test/fixtures/fcc.txt
116
128
  - test/fixtures/states.xls
117
129
  - test/helper.rb
118
130
  - test/schemas/acma.rb
131
+ - test/schemas/citizens.rb
119
132
  - test/schemas/fcc.rb
120
- - test/unit/conformist/base_test.rb
121
133
  - test/unit/conformist/builder_test.rb
122
134
  - test/unit/conformist/column_test.rb
123
135
  - test/unit/conformist/hash_struct_test.rb
@@ -1,7 +0,0 @@
1
- module Conformist
2
- module Base
3
- def self.included base
4
- raise "`include Conformist::Base` has been removed, `extend Conformist` instead (#{caller.first})"
5
- end
6
- end
7
- end
@@ -1,9 +0,0 @@
1
- require 'helper'
2
-
3
- class Conformist::BuilderTest < MiniTest::Unit::TestCase
4
- def test_included
5
- assert_raises RuntimeError do
6
- Class.new { include Base }
7
- end
8
- end
9
- end