conformist 0.1.3 → 0.2.0

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