goodsheet 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aef27ae57a44343de4b43b8118c3a4dba7940021
4
- data.tar.gz: ccd478aad49271a61e1e4278cbfd95ea9a226b17
3
+ metadata.gz: b602fb68bc8d91fbc2004a2fc5dc021e26ef25cc
4
+ data.tar.gz: 7ccf288b4183c2d84ecdc5f22afbdfd572824dd5
5
5
  SHA512:
6
- metadata.gz: cf0b9d857e4eb5a66cbf72a6c205e1ab4f517fd93dbd40e42382e1b1f34d0b0e74813bdf8bb5e3e48c554933297ccc31160d39e83e2d4b311825ddf73c32d897
7
- data.tar.gz: f866ccb2f33ffa9618f12c597a1ab4c9d88282eaf6ffd0485d0e262f78cc506c424a58cc97f2de569e385aa88e2f517b3ee85fd443a955c35e9fe4c808bd7e6e
6
+ metadata.gz: 81da028ed30bdd2e27616fcff01fe313e8eb38884e098121518eff2be24cad1ec538f5641442ec18d08f896bf756f640baec21352a898716555d236e0e6821b1
7
+ data.tar.gz: 0b85bba8e877f4907ec5a601ecb3fd482358d0cdb32d174467495a4334e0d8a138dbc8865abb3f901410f371b3a36bacca77bb4bad9f5320472774ba49fda363
data/README.md CHANGED
@@ -30,7 +30,8 @@ Given a spreadsheet:
30
30
  ```ruby
31
31
  ss = Goodsheet::Spreadsheet.new("example.xls")
32
32
  res = ss.read do
33
- column_names :filename => 0, :size => 1, :created_at => 3, :updated_at => 4 # ignore 'description' column
33
+ column_names :filename => 0, :size => 1, :created_at => 3, :updated_at => 4 # i want to ignore 'description' column
34
+ column_defaults :filename => "UNKNOWN"
34
35
  validates :filename, :presence => true
35
36
  validates :size, :presence => true, :numericality => { :greater_than_or_equal_to => 0.0 }
36
37
  validate :order_of_dates
@@ -126,14 +127,21 @@ ss.rows_wo_skipped # => except the skipped ones, aliased by `rows` method
126
127
 
127
128
  #### Reading and validate
128
129
 
129
- Use the `validate` and `read` methods to perform validation and reading. Note that the reading function include a validation call.
130
+ Use the `validate` and `read` methods to perform validation and reading. Note that the reading function include the validation step.
130
131
  Pass the previously seen `options` hash and a block to `validate`/`read` method.
131
- Inside the block you define columns names and indexes you want to validate/read using the `column_names` method. You can use one of these 4 forms (and their effect is the same):
132
+ Inside the block you define columns names and indexes you want to validate/read using the `column_names` method. You can use one of these 4 forms (and their effect is identical):
132
133
  - `column_names :a => 0, :b => 1, :c => 3`
133
134
  - `column_names 0 => :a, 1 => :b, 3 => :c`
134
135
  - `column_names [:a, :b, nil, :c]`
135
136
  - `column_names :a, :b, nil, :c`
136
137
 
138
+ Use the `column_defaults` method to specify the value to set when the corresponding cell hold a nil value (is empty). Like the previous method, the following forms are identical:
139
+ - `column_defaults :a => 0.0, :b => 0.0, :c => "UNKNOWN"`
140
+ - `column_defaults 0 => 0.0, 1 => 0.0, 3 => "UNKNOWN"`
141
+ - `column_defaults [0.0, 0.0, "UNKNOWN"]`
142
+ - `column_defaults 0.0, 0.0, "UNKNOWN"`
143
+ The `column_defaults` macro overwrite the read/validate `:force_nil` option.
144
+
137
145
  Aside from define the columns settings, into block you define the validation rules.
138
146
  Refer to the [official guide](http://guides.rubyonrails.org/active_record_validations.html) and [ROR Api](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html)
139
147
 
@@ -2,6 +2,7 @@
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'goodsheet/version'
5
+ require 'date'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
8
  spec.name = "goodsheet"
@@ -12,7 +13,7 @@ Gem::Specification.new do |spec|
12
13
  spec.summary = "Extract and validate data from a spreadsheet"
13
14
  spec.homepage = "https://github.com/iwan/goodsheet"
14
15
  spec.license = "MIT"
15
- spec.date = '2013-07-19'
16
+ spec.date = Date.today.to_s
16
17
  spec.files = `git ls-files`.split($/)
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
@@ -23,6 +24,6 @@ Gem::Specification.new do |spec|
23
24
  spec.add_development_dependency "rake"
24
25
 
25
26
  spec.add_dependency('roo', '>= 1.12.1') # https://github.com/Empact/roo
26
- spec.add_dependency('activemodel', '>= 3.2.14')
27
+ spec.add_dependency('activemodel', '~> 3.2')
27
28
  spec.add_dependency('google_drive')
28
29
  end
@@ -0,0 +1,10 @@
1
+ class Object
2
+ def chrono(msg, &block)
3
+ puts "--------- starting #{msg} -------->"
4
+ t = Time.now
5
+ yield
6
+ delta_t = Time.now-t
7
+ puts "<-------- #{msg} takes #{delta_t}s"
8
+ return delta_t
9
+ end
10
+ end
@@ -6,7 +6,7 @@ module Goodsheet
6
6
  include ActiveModel::Validations
7
7
 
8
8
  class << self
9
- attr_accessor :keys, :defaults
9
+ attr_accessor :keys, :defaults, :defaults_attributes
10
10
  end
11
11
  # @keys = {} # idx => key: {0=>:name, 1=>:quantity, 2=>:price, 3=>:total, 6=>:password}
12
12
  # @defaults = {} # name => default_value
@@ -28,6 +28,7 @@ module Goodsheet
28
28
  c = Class.new(self) do
29
29
  @keys = {} # idx => key: {0=>:name, 1=>:quantity, 2=>:price, 3=>:total, 6=>:password}
30
30
  @defaults = {} # name => default_value
31
+ @defaults_attributes = nil # name => default_value
31
32
  end
32
33
  c.class_eval(&block)
33
34
  c
@@ -35,16 +36,29 @@ module Goodsheet
35
36
 
36
37
  # using indexes: defaults 1 => 0.0, 2 => ""
37
38
  # using names: defaults :qty => 0.0, :name => ""
38
-
39
39
  def self.column_defaults(*attr)
40
40
  raise ArgumentError, 'You have to pass at least one attribute' if attr.empty?
41
- if attr[0].is_a? Array
41
+ if self.keys.empty?
42
+ self.defaults_attributes = attr
43
+ else
44
+ self.defaults_attributes = nil
45
+ self.set_defaults(attr)
46
+ end
47
+ end
48
+
49
+ def self.set_defaults(attr)
50
+ if attr[0].is_a? Array # column_defaults [0.0, nil, "Unknown"]
51
+ # @defaults = Hash[attr[0].map.with_index{|v, i| [self.keys[i], v]}]
42
52
  @defaults = Hash[attr[0].map.with_index{|v, i| [self.keys[i], v]}]
43
53
 
44
- elsif attr[0].is_a? Hash
54
+ elsif attr[0].is_a? Hash # column_defaults 0 => 0.0, 1 => nil, 2 => "Unknown"
55
+ # --or-- column_defaults :size => 0.0, :weight => nil, :name => "Unknown"
56
+
57
+ # @defaults = Hash[attr[0].to_a.collect{|a| [(a[0].is_a?(Fixnum)) ? (self.keys[a[0]]) : a[0], a[1]]}]
45
58
  @defaults = Hash[attr[0].to_a.collect{|a| [(a[0].is_a?(Fixnum)) ? (self.keys[a[0]]) : a[0], a[1]]}]
46
59
 
47
- else
60
+ else # column_defaults 0.0, nil, "Unknown"
61
+ # @defaults = Hash[attr.map.with_index{|v, i| [self.keys[i], v]}]
48
62
  @defaults = Hash[attr.map.with_index{|v, i| [self.keys[i], v]}]
49
63
  end
50
64
  end
@@ -58,30 +72,21 @@ module Goodsheet
58
72
  # at the position, or simply put the list of names.
59
73
  # The positions are 0-based.
60
74
  def self.column_names(*attr)
61
- # def self.column_names(param)
62
75
  @keys = {}
63
76
  raise ArgumentError, 'You have to pass at least one attribute' if attr.empty?
64
77
  if attr[0].is_a? Array
65
78
  attr[0].each_with_index do |name, idx|
66
79
  self.set_key_pair(idx, name) if name
67
- # if name
68
- # self.keys[idx] = name
69
- # attr_accessor name
70
- # end
71
80
  end
72
81
 
73
82
  elsif attr[0].is_a? Hash
74
83
  if attr[0].first[0].is_a? Integer
75
84
  attr[0].each do |idx, name|
76
85
  self.set_key_pair(idx, name)
77
- # self.keys[idx] = name
78
- # attr_accessor name
79
86
  end
80
87
  else
81
88
  attr[0].each do |name, idx|
82
89
  self.set_key_pair(idx, name)
83
- # self.keys[idx] = name
84
- # attr_accessor name
85
90
  end
86
91
  end
87
92
 
@@ -90,12 +95,13 @@ module Goodsheet
90
95
  if name
91
96
  name = name.to_s.gsub(" ", "_").to_sym unless name.is_a? Symbol
92
97
  self.set_key_pair(idx, name)
93
- # self.keys[idx] = name
94
- # attr_accessor name
95
98
  end
96
99
  end
97
100
  end
98
101
 
102
+ if !self.defaults_attributes.nil?
103
+ self.set_defaults(self.defaults_attributes)
104
+ end
99
105
  end
100
106
 
101
107
 
@@ -1,3 +1,3 @@
1
1
  module Goodsheet
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -0,0 +1,147 @@
1
+ require 'test/unit'
2
+ require 'goodsheet'
3
+
4
+ class TestDefaults < Test::Unit::TestCase
5
+
6
+ def setup
7
+ filepath = File.dirname(__FILE__) + "/fixtures/for_defaults.xls"
8
+ @ss = Goodsheet::Spreadsheet.new(filepath, :skip => 1)
9
+ end
10
+
11
+
12
+
13
+ def test_invalid
14
+ res = @ss.read do
15
+ column_names 0 => :name, 1 => :number
16
+ validates :name, :presence => true
17
+ validates :number, :numericality => true
18
+ end
19
+ assert(res.invalid?)
20
+
21
+ res = @ss.read do
22
+ column_names 0 => :name, 1 => :number
23
+ column_defaults 0 => "UNKNOWN"
24
+ validates :name, :presence => true
25
+ validates :number, :numericality => true
26
+ end
27
+ assert(res.invalid?)
28
+
29
+ res = @ss.read do
30
+ column_names 0 => :name, 1 => :number
31
+ column_defaults 1 => 0.0
32
+ validates :name, :presence => true
33
+ validates :number, :numericality => true
34
+ end
35
+ assert(res.invalid?)
36
+ end
37
+
38
+
39
+
40
+ def test_force_nil_vs_defaults
41
+ res = @ss.read(:force_nil => 0.0) do
42
+ column_names 0 => :name, 1 => :number
43
+ validates :name, :presence => true
44
+ validates :number, :numericality => true
45
+ end
46
+ assert(res.valid?)
47
+ assert_equal(["Joshua Baney", "Libby Meiers", "Dean Murdoch", 0.0, "Esmeralda Erben"], res.values[:name])
48
+ assert_equal([3.0, 2.0, 0.0, 8.0, 1.0], res.values[:number])
49
+
50
+ res = @ss.read(:force_nil => "foo") do
51
+ column_names 0 => :name, 1 => :number
52
+ validates :name, :presence => true
53
+ validates :number, :numericality => true
54
+ end
55
+ assert(res.invalid?)
56
+ assert_equal(["Joshua Baney", "Libby Meiers", "Dean Murdoch", "foo", "Esmeralda Erben"], res.values[:name])
57
+ assert_equal([3.0, 2.0, "foo", 8.0, 1.0], res.values[:number])
58
+
59
+
60
+ res = @ss.read(:force_nil => 1.0) do
61
+ column_names 0 => :name, 1 => :number
62
+ column_defaults 0 => "UNKNOWN", 1 => 10.0
63
+ validates :name, :presence => true
64
+ validates :number, :numericality => true
65
+ end
66
+ assert(res.valid?)
67
+ assert_equal(["Joshua Baney", "Libby Meiers", "Dean Murdoch", "UNKNOWN", "Esmeralda Erben"], res.values[:name])
68
+ assert_equal([3.0, 2.0, 10.0, 8.0, 1.0], res.values[:number])
69
+ end
70
+
71
+
72
+
73
+ def test_values_correctness
74
+ res = @ss.read do
75
+ column_names 0 => :name, 1 => :number
76
+ column_defaults 0 => "UNKNOWN", 1 => 0.0
77
+ validates :name, :presence => true
78
+ validates :number, :numericality => true
79
+ end
80
+ assert(res.valid?)
81
+ assert_equal(["Joshua Baney", "Libby Meiers", "Dean Murdoch", "UNKNOWN", "Esmeralda Erben"], res.values[:name])
82
+ assert_equal([3.0, 2.0, 0.0, 8.0, 1.0], res.values[:number])
83
+ end
84
+
85
+
86
+
87
+ def test_not_existing_column
88
+ res = @ss.read do
89
+ column_names 0 => :name, 1 => :number, 2 => :fake
90
+ column_defaults 0 => "UNKNOWN", 1 => 0.0
91
+ validates :name, :presence => true
92
+ validates :number, :numericality => true
93
+ end
94
+ assert(res.valid?)
95
+ assert_equal([nil, nil, nil, nil, nil], res.values[:fake])
96
+
97
+ res = @ss.read do
98
+ column_names 0 => :name, 1 => :number, 2 => :fake
99
+ column_defaults 0 => "UNKNOWN", 1 => 0.0
100
+ validates :name, :presence => true
101
+ validates :number, :numericality => true
102
+ validates :fake, :presence => true
103
+ end
104
+ assert(res.invalid?)
105
+
106
+ res1 = @ss.read do
107
+ column_names 0 => :name, 1 => :number, 2 => :fake
108
+ column_defaults 0 => "UNKNOWN", 1 => 0.0, 2 => "EMPTY"
109
+ validates :name, :presence => true
110
+ validates :number, :numericality => true
111
+ validates :fake, :presence => true
112
+ end
113
+ assert(res1.valid?)
114
+ end
115
+
116
+
117
+
118
+ def test_column_defaults_formats
119
+ res_1 = @ss.read do
120
+ column_names :name, :number
121
+ column_defaults ["UNKNOWN", 0.0]
122
+ validates :name, :presence => true
123
+ validates :number, :numericality => true
124
+ end
125
+ assert(res_1.valid?)
126
+
127
+ res_2 = @ss.read do
128
+ column_names :name, :number
129
+ column_defaults "UNKNOWN", 0.0
130
+ validates :name, :presence => true
131
+ validates :number, :numericality => true
132
+ end
133
+ assert(res_2.valid?)
134
+ assert_equal(res_1.values, res_2.values)
135
+
136
+ res_3 = @ss.read do
137
+ column_names 0 => :name, 1 => :number
138
+ column_defaults 1 => 0.0, 0 => "UNKNOWN"
139
+ validates :name, :presence => true
140
+ validates :number, :numericality => true
141
+ end
142
+ assert(res_3.valid?)
143
+ assert_equal(res_1.values, res_3.values)
144
+ end
145
+
146
+
147
+ end
@@ -0,0 +1,130 @@
1
+ require 'test/unit'
2
+ require 'goodsheet'
3
+
4
+ # test the functionality of column_defaults macro, when used before column_names macro
5
+ class TestDefaults < Test::Unit::TestCase
6
+
7
+ def setup
8
+ filepath = File.dirname(__FILE__) + "/fixtures/for_defaults.xls"
9
+ @ss = Goodsheet::Spreadsheet.new(filepath, :skip => 1)
10
+ end
11
+
12
+
13
+ def test_values_correctness
14
+ res = @ss.read do
15
+ column_defaults 0 => "UNKNOWN", 1 => 0.0
16
+ column_names 0 => :name, 1 => :number
17
+ validates :name, :presence => true
18
+ validates :number, :numericality => true
19
+ end
20
+ assert(res.valid?)
21
+ assert_equal(["Joshua Baney", "Libby Meiers", "Dean Murdoch", "UNKNOWN", "Esmeralda Erben"], res.values[:name])
22
+ assert_equal([3.0, 2.0, 0.0, 8.0, 1.0], res.values[:number])
23
+ end
24
+
25
+
26
+ def test_invalid
27
+ res = @ss.read do
28
+ column_names 0 => :name, 1 => :number
29
+ validates :name, :presence => true
30
+ validates :number, :numericality => true
31
+ end
32
+ assert(res.invalid?)
33
+
34
+ res = @ss.read do
35
+ column_defaults 0 => "UNKNOWN"
36
+ column_names 0 => :name, 1 => :number
37
+ validates :name, :presence => true
38
+ validates :number, :numericality => true
39
+ end
40
+ assert(res.invalid?)
41
+
42
+ res = @ss.read do
43
+ column_defaults 1 => 0.0
44
+ column_names 0 => :name, 1 => :number
45
+ validates :name, :presence => true
46
+ validates :number, :numericality => true
47
+ end
48
+ assert(res.invalid?)
49
+ end
50
+
51
+
52
+
53
+ def test_force_nil_vs_defaults
54
+ res = @ss.read(:force_nil => 1.0) do
55
+ column_defaults 0 => "UNKNOWN", 1 => 10.0
56
+ column_names 0 => :name, 1 => :number
57
+ validates :name, :presence => true
58
+ validates :number, :numericality => true
59
+ end
60
+ assert(res.valid?)
61
+ assert_equal(["Joshua Baney", "Libby Meiers", "Dean Murdoch", "UNKNOWN", "Esmeralda Erben"], res.values[:name])
62
+ assert_equal([3.0, 2.0, 10.0, 8.0, 1.0], res.values[:number])
63
+ end
64
+
65
+
66
+
67
+
68
+
69
+
70
+ def test_not_existing_column
71
+ res = @ss.read do
72
+ column_defaults 0 => "UNKNOWN", 1 => 0.0
73
+ column_names 0 => :name, 1 => :number, 2 => :fake
74
+ validates :name, :presence => true
75
+ validates :number, :numericality => true
76
+ end
77
+ assert(res.valid?)
78
+ assert_equal([nil, nil, nil, nil, nil], res.values[:fake])
79
+
80
+ res = @ss.read do
81
+ column_defaults 0 => "UNKNOWN", 1 => 0.0
82
+ column_names 0 => :name, 1 => :number, 2 => :fake
83
+ validates :name, :presence => true
84
+ validates :number, :numericality => true
85
+ validates :fake, :presence => true
86
+ end
87
+ assert(res.invalid?)
88
+
89
+ res1 = @ss.read do
90
+ column_defaults 0 => "UNKNOWN", 1 => 0.0, 2 => "EMPTY"
91
+ column_names 0 => :name, 1 => :number, 2 => :fake
92
+ validates :name, :presence => true
93
+ validates :number, :numericality => true
94
+ validates :fake, :presence => true
95
+ end
96
+ assert(res1.valid?)
97
+ end
98
+
99
+
100
+
101
+ def test_column_defaults_formats
102
+ res_1 = @ss.read do
103
+ column_defaults ["UNKNOWN", 0.0]
104
+ column_names :name, :number
105
+ validates :name, :presence => true
106
+ validates :number, :numericality => true
107
+ end
108
+ assert(res_1.valid?)
109
+
110
+ res_2 = @ss.read do
111
+ column_defaults "UNKNOWN", 0.0
112
+ column_names :name, :number
113
+ validates :name, :presence => true
114
+ validates :number, :numericality => true
115
+ end
116
+ assert(res_2.valid?)
117
+ assert_equal(res_1.values, res_2.values)
118
+
119
+ res_3 = @ss.read do
120
+ column_defaults 1 => 0.0, 0 => "UNKNOWN"
121
+ column_names 0 => :name, 1 => :number
122
+ validates :name, :presence => true
123
+ validates :number, :numericality => true
124
+ end
125
+ assert(res_3.valid?)
126
+ assert_equal(res_1.values, res_3.values)
127
+ end
128
+
129
+
130
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goodsheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iwan Buetti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-19 00:00:00.000000000 Z
11
+ date: 2013-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: activemodel
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 3.2.14
61
+ version: '3.2'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: 3.2.14
68
+ version: '3.2'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: google_drive
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -96,6 +96,7 @@ files:
96
96
  - goodsheet.gemspec
97
97
  - img/img_01.png
98
98
  - lib/goodsheet.rb
99
+ - lib/goodsheet/aux.rb
99
100
  - lib/goodsheet/exceptions.rb
100
101
  - lib/goodsheet/read_result.rb
101
102
  - lib/goodsheet/row.rb
@@ -106,12 +107,15 @@ files:
106
107
  - notes.txt
107
108
  - test/fixtures/example.xls
108
109
  - test/fixtures/fixtures_template.xlsx
110
+ - test/fixtures/for_defaults.xls
109
111
  - test/fixtures/ss_01.xls
110
112
  - test/fixtures/ss_02.csv
111
113
  - test/fixtures/ss_02.ods
112
114
  - test/fixtures/ss_02.xls
113
115
  - test/fixtures/ss_02.xlsx
114
116
  - test/fixtures/ss_04.xlsx
117
+ - test/test_defaults.rb
118
+ - test/test_defaults_2.rb
115
119
  - test/test_row.rb
116
120
  - test/test_spreadsheet_01.rb
117
121
  - test/test_spreadsheet_02.rb
@@ -143,12 +147,15 @@ summary: Extract and validate data from a spreadsheet
143
147
  test_files:
144
148
  - test/fixtures/example.xls
145
149
  - test/fixtures/fixtures_template.xlsx
150
+ - test/fixtures/for_defaults.xls
146
151
  - test/fixtures/ss_01.xls
147
152
  - test/fixtures/ss_02.csv
148
153
  - test/fixtures/ss_02.ods
149
154
  - test/fixtures/ss_02.xls
150
155
  - test/fixtures/ss_02.xlsx
151
156
  - test/fixtures/ss_04.xlsx
157
+ - test/test_defaults.rb
158
+ - test/test_defaults_2.rb
152
159
  - test/test_row.rb
153
160
  - test/test_spreadsheet_01.rb
154
161
  - test/test_spreadsheet_02.rb