data_package 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +53 -0
  7. data/LICENSE +20 -0
  8. data/README.md +32 -0
  9. data/Rakefile +6 -0
  10. data/data_package.gemspec +33 -0
  11. data/lib/attr_helper/base_attr.rb +36 -0
  12. data/lib/attr_helper/required_attr.rb +46 -0
  13. data/lib/attr_helper/serialization.rb +25 -0
  14. data/lib/attr_helper.rb +105 -0
  15. data/lib/data_package/base.rb +10 -0
  16. data/lib/data_package/dialect.rb +9 -0
  17. data/lib/data_package/field.rb +20 -0
  18. data/lib/data_package/license.rb +8 -0
  19. data/lib/data_package/package.rb +100 -0
  20. data/lib/data_package/person.rb +7 -0
  21. data/lib/data_package/resource.rb +75 -0
  22. data/lib/data_package/schema.rb +13 -0
  23. data/lib/data_package/source.rb +7 -0
  24. data/lib/data_package/version.rb +3 -0
  25. data/lib/data_package.rb +17 -0
  26. data/spec/attr_helper_spec.rb +60 -0
  27. data/spec/attr_helpers/base_attr_spec.rb +62 -0
  28. data/spec/attr_helpers/required_attr_spec.rb +49 -0
  29. data/spec/attr_helpers/serialization_spec.rb +9 -0
  30. data/spec/data_package/base_spec.rb +10 -0
  31. data/spec/data_package/dialect_spec.rb +35 -0
  32. data/spec/data_package/field_spec.rb +29 -0
  33. data/spec/data_package/license_spec.rb +18 -0
  34. data/spec/data_package/package_spec.rb +59 -0
  35. data/spec/data_package/person_spec.rb +21 -0
  36. data/spec/data_package/resource_spec.rb +57 -0
  37. data/spec/data_package/schema_spec.rb +25 -0
  38. data/spec/data_package/source_spec.rb +22 -0
  39. data/spec/fixtures/package/datapackage.json +94 -0
  40. data/spec/fixtures/package/standard.csv +11 -0
  41. data/spec/fixtures/standard.csv +11 -0
  42. data/spec/klass_helper.rb +41 -0
  43. data/spec/resource_helper.rb +113 -0
  44. data/spec/spec_helper.rb +19 -0
  45. metadata +233 -0
@@ -0,0 +1,17 @@
1
+ require 'active_support/core_ext/hash'
2
+
3
+ require "data_package/version"
4
+
5
+ # Attribute Helpers
6
+ require 'attr_helper'
7
+
8
+ # Core Specification
9
+ require 'data_package/base'
10
+ require 'data_package/package'
11
+ require 'data_package/field'
12
+ require 'data_package/schema'
13
+ require 'data_package/resource'
14
+ require 'data_package/dialect'
15
+ require 'data_package/person'
16
+ require 'data_package/source'
17
+ require 'data_package/license'
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+ require 'klass_helper'
3
+
4
+ describe AttrHelper do
5
+ it "should initialize" do
6
+ obj = KlassHelper::BaseKlass.new(:name => 'myvalue')
7
+
8
+ obj.name.should == 'myvalue'
9
+
10
+ obj.attr_required?(:name).should == true
11
+ obj.attr_required?(:title).should == false
12
+ obj.attr_required?(:format).should == false
13
+
14
+ obj.missing_attributes.collect(&:name).should == [:data, :path, :url, :email, :web]
15
+ obj.required_attributes.collect(&:name).should == [:name, :data, :path, :url, :email, :web]
16
+
17
+ obj.attr_present?(:name).should == true
18
+ obj.attr_missing?(:name).should == false
19
+
20
+ obj.attr_present?(:data).should == false
21
+ obj.attr_missing?(:data).should == true
22
+ end
23
+
24
+ it "should inherit" do
25
+ obj = KlassHelper::ChildKlass.new(:name => 'myvalue')
26
+
27
+ obj.name.should == 'myvalue'
28
+
29
+ obj.attr_required?(:name).should == true
30
+ obj.attr_required?(:title).should == false
31
+ obj.attr_required?(:format).should == false
32
+
33
+ obj.missing_attributes.collect(&:name).should == [:data, :path, :url, :email, :web]
34
+ obj.required_attributes.collect(&:name).should == [:name, :data, :path, :url, :email, :web]
35
+
36
+ obj.attr_present?(:name).should == true
37
+ obj.attr_missing?(:name).should == false
38
+
39
+ obj.attr_present?(:data).should == false
40
+ obj.attr_missing?(:data).should == true
41
+ end
42
+
43
+ it "should allow mutual exclusion" do
44
+ obj = KlassHelper::ChildKlass.new(:name => 'myvalue')
45
+
46
+ obj.missing_attributes.collect(&:name).should == [:data, :path, :url, :email, :web]
47
+ obj.required_attributes.collect(&:name).should == [:name, :data, :path, :url, :email, :web]
48
+
49
+ obj.path = 'data.csv'
50
+ obj.missing_attributes.collect(&:name).should == [:email, :web]
51
+ obj.required_attributes.collect(&:name).should == [:name, :path, :email, :web]
52
+ end
53
+
54
+ it "should write attributes through the setters" do
55
+ obj = KlassHelper::ChildKlass.new(:name => 'myvalue', :title => 'mytitle')
56
+
57
+ obj.name.should == 'myvalue'
58
+ obj.title.should == 'mytitlechild'
59
+ end
60
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ class ValueObj
4
+ attr_accessor :name
5
+
6
+ def initialize(attrs = {})
7
+ @name = attrs[:name]
8
+ end
9
+
10
+ def is_name_required?
11
+ true
12
+ end
13
+
14
+ def serialized_name(name)
15
+ name + 'method'
16
+ end
17
+ end
18
+
19
+ describe AttrHelper::BaseAttr do
20
+ it "should initialize" do
21
+ valueObj = ValueObj.new(:name => 'value')
22
+ attribute = AttrHelper::BaseAttr.new(:name)
23
+
24
+ attribute.name.should == :name
25
+ attribute.key.should == 'name'
26
+ attribute.serialize.should == true
27
+ end
28
+
29
+ describe "Serialization" do
30
+ it "should serialize by default" do
31
+ valueObj = ValueObj.new(:name => 'value')
32
+ attribute = AttrHelper::BaseAttr.new(:name)
33
+
34
+ attribute.serializable?.should == true
35
+ attribute.serialized(valueObj).should == 'value'
36
+ end
37
+
38
+ it "should serialize with a proc" do
39
+ valueObj = ValueObj.new(:name => 'value')
40
+ attribute = AttrHelper::BaseAttr.new(:name, :serialize => Proc.new{|name| name + 'proc'})
41
+
42
+ attribute.serializable?.should == true
43
+ attribute.serialized(valueObj).should == 'valueproc'
44
+ end
45
+
46
+ it "should serialize with a symbol" do
47
+ valueObj = ValueObj.new(:name => 'value')
48
+ attribute = AttrHelper::BaseAttr.new(:name, :serialize => :serialized_name)
49
+
50
+ attribute.serializable?.should == true
51
+ attribute.serialized(valueObj).should == 'valuemethod'
52
+ end
53
+
54
+ it "should disable serialization" do
55
+ valueObj = ValueObj.new(:name => 'value')
56
+ attribute = AttrHelper::BaseAttr.new(:name, :serialize => false)
57
+
58
+ attribute.serializable?.should == false
59
+ attribute.serialized(valueObj).should == nil
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ class ValueObj
4
+ attr_accessor :name
5
+
6
+ def initialize(attrs = {})
7
+ @name = attrs[:name]
8
+ end
9
+
10
+ def is_name_required?
11
+ true
12
+ end
13
+ end
14
+
15
+ describe AttrHelper::RequiredAttr do
16
+ it "should initialize" do
17
+ valueObj = ValueObj.new(:name => 'value')
18
+ attribute = AttrHelper::RequiredAttr.new(:name)
19
+
20
+ attribute.name.should == :name
21
+ attribute.key.should == 'name'
22
+ attribute.serialize.should == true
23
+ attribute.required?(valueObj).should == true
24
+ end
25
+
26
+ it "should check for if requirement with a proc" do
27
+ valueObj = ValueObj.new(:name => 'value')
28
+ attribute = AttrHelper::RequiredAttr.new(:name, :if => Proc.new{|parent| true})
29
+ attribute.required?(valueObj).should == true
30
+ end
31
+
32
+ it "should check for if requirement with a symbol" do
33
+ valueObj = ValueObj.new(:name => 'value')
34
+ attribute = AttrHelper::RequiredAttr.new(:name, :if => :is_name_required?)
35
+ attribute.required?(valueObj).should == true
36
+ end
37
+
38
+ it "should check for unless requirement with a proc" do
39
+ valueObj = ValueObj.new(:name => 'value')
40
+ attribute = AttrHelper::RequiredAttr.new(:name, :unless => Proc.new{|parent| true})
41
+ attribute.required?(valueObj).should == false
42
+ end
43
+
44
+ it "should check for unless requirement with a symbol" do
45
+ valueObj = ValueObj.new(:name => 'value')
46
+ attribute = AttrHelper::RequiredAttr.new(:name, :unless => :is_name_required?)
47
+ attribute.required?(valueObj).should == false
48
+ end
49
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ require 'klass_helper'
3
+
4
+ describe AttrHelper do
5
+ it "should serialize" do
6
+ obj = KlassHelper::BaseKlass.new(:name => 'myvalue')
7
+ obj.to_json.should == Yajl::Encoder.encode({:name => 'myvalue'}, :pretty => true)
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataPackage::Base do
4
+ it "should list required and optional attributes" do
5
+ base = DataPackage::Base.new
6
+
7
+ base.required_attributes.should == []
8
+ base.optional_attributes.should == []
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataPackage::Dialect do
4
+ let(:json) {
5
+ {
6
+ "delimiter" => "\t",
7
+ "doublequote" => false,
8
+ "lineterminator" => "\n",
9
+ "quotechar" => "\"",
10
+ "skipinitialspace" => true
11
+ }
12
+ }
13
+
14
+ it "should initialize with defaults" do
15
+ dialect = DataPackage::Dialect.new
16
+
17
+ dialect.delimiter.should == ','
18
+ dialect.double_quote.should == false
19
+ dialect.line_terminator.should == "\n"
20
+ dialect.quote_char.should == "\""
21
+ dialect.skip_initial_space.should == false
22
+ end
23
+
24
+ it "should initialize and serialize" do
25
+ dialect = DataPackage::Dialect.new(json)
26
+
27
+ dialect.delimiter.should == "\t"
28
+ dialect.double_quote.should == false
29
+ dialect.line_terminator.should == "\n"
30
+ dialect.quote_char.should == "\""
31
+ dialect.skip_initial_space.should == true
32
+
33
+ dialect.to_json.should == Yajl::Encoder.encode(json, :pretty => true)
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataPackage::Field do
4
+ let(:json) {
5
+ {
6
+ 'name' => 'income',
7
+ 'type' => 'number',
8
+ 'title' => 'Personal Income',
9
+ 'description' => 'My Desc'
10
+ }
11
+ }
12
+
13
+ it "should initialize and serialize" do
14
+ field = DataPackage::Field.new(json)
15
+
16
+ field.type.should == :number
17
+ field.name.should == json['name']
18
+ field.title.should == json['title']
19
+ field.description.should == json['description']
20
+
21
+ field.to_hash.should == json
22
+ field.to_json.should == Yajl::Encoder.encode(field.to_hash, :pretty => true)
23
+ end
24
+
25
+ it "should require a name" do
26
+ field = DataPackage::Field.new
27
+ field.missing_attributes.collect(&:name).should == [:name]
28
+ end
29
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataPackage::License do
4
+ let(:json) {
5
+ {
6
+ 'id' => 'PDDL',
7
+ 'url' => 'http://opendatacommons.org/licenses/pddl/'
8
+ }
9
+ }
10
+
11
+ it "should initialize and serialize" do
12
+ license = DataPackage::License.new(json)
13
+
14
+ license.id.should == 'PDDL'
15
+ license.url.should == 'http://opendatacommons.org/licenses/pddl/'
16
+ license.to_json.should == Yajl::Encoder.encode(json, :pretty => true)
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataPackage::Package do
4
+ let(:tmpdir) {
5
+ Dir.mktmpdir
6
+ }
7
+
8
+ let(:package_path) {
9
+ File.join(base_path, 'package')
10
+ }
11
+
12
+ it "should init" do
13
+ package = DataPackage::Package.init(tmpdir, 'mypackage')
14
+
15
+ package.name.should == 'mypackage'
16
+ package.version.should == '0.0.1'
17
+ package.resources.should == nil
18
+ package.base_path.should == tmpdir
19
+ end
20
+
21
+ it "should raise on open if the package file doesn't exist" do
22
+ expect { package = DataPackage::Package.open(tmpdir) }.to raise_error
23
+ end
24
+
25
+ it "should check if a package exists" do
26
+ DataPackage::Package.exist?(package_path).should == true
27
+ end
28
+
29
+ it "should initialize and serialize" do
30
+ package = DataPackage::Package.open(package_path)
31
+
32
+ package.name.should == 'standard'
33
+ package.title.should == 'Standard Data Package'
34
+ package.version.should == '0.0.1'
35
+
36
+ package.resources.length.should == 1
37
+
38
+ package.resources.first.schema.fields.length.should == 10
39
+ package.resources.first.schema.primary_key.should == ['id']
40
+
41
+ package.sources.length.should == 1
42
+ package.licenses.length.should == 1
43
+ package.maintainers.length.should == 1
44
+ package.contributors.length.should == 1
45
+ end
46
+
47
+ it "should save the package" do
48
+ package = DataPackage::Package.open(package_path)
49
+
50
+ package.base_path = tmpdir
51
+ package.name = "tested_package"
52
+
53
+ package.save
54
+
55
+ reopened = DataPackage::Package.open(tmpdir)
56
+
57
+ reopened.name.should == "tested_package"
58
+ end
59
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataPackage::Person do
4
+ let(:json) {
5
+ {
6
+ 'name' => 'Josh F',
7
+ 'email' => 'josh@modeanalytics.com',
8
+ 'web' => 'http://www.modeanalytics.com/josh'
9
+ }
10
+ }
11
+
12
+ it "should initialize and serialize" do
13
+ person = DataPackage::Person.new(json)
14
+
15
+ person.name.should == 'Josh F'
16
+ person.email.should == 'josh@modeanalytics.com'
17
+ person.web.should == 'http://www.modeanalytics.com/josh'
18
+
19
+ person.to_json.should == Yajl::Encoder.encode(json, :pretty => true)
20
+ end
21
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ require 'resource_helper'
3
+
4
+ describe DataPackage::Resource do
5
+ it "should initialize and serialize" do
6
+ resource = DataPackage::Resource.new(base_path, standard_resource)
7
+
8
+ resource.format.should == 'csv'
9
+ resource.name.should == 'standard'
10
+ resource.path.should == 'standard.csv'
11
+
12
+ resource.schema.fields.length.should == 10
13
+ resource.schema.primary_key.should == ['id']
14
+
15
+ resource.to_hash.should == standard_resource.merge('format' => 'csv', 'dialect' => DataPackage::Dialect.new.to_hash)
16
+ end
17
+
18
+ describe "#each_row" do
19
+ it "should enumerate over inline data" do
20
+ resource = DataPackage::Resource.new(base_path, inline_resource)
21
+
22
+ row_count = 0
23
+ resource.each_row do |row|
24
+ row_count += 1
25
+ end
26
+ row_count.should == 3
27
+ end
28
+
29
+ it "should enumerate over local file data" do
30
+ resource = DataPackage::Resource.new(base_path, standard_resource)
31
+
32
+ row_count = 0
33
+ resource.each_row do |row|
34
+ row_count += 1
35
+ end
36
+ row_count.should == 10
37
+ end
38
+
39
+ it "should not enumerate URL data" do
40
+ resource = DataPackage::Resource.new(base_path, http_resource)
41
+ expect{ resource.each_row{|row| nil} }.to raise_error
42
+ end
43
+
44
+ it "should raise if the data format is unexpected" do
45
+ resource = DataPackage::Resource.new(base_path, standard_resource.merge('format' => 'unknown'))
46
+ expect{ resource.each_row{|row| nil} }.to raise_error
47
+ end
48
+
49
+ it "should raise if data, path or url aren't present" do
50
+ invalid = standard_resource.dup
51
+ invalid.delete('path')
52
+
53
+ resource = DataPackage::Resource.new(base_path, invalid)
54
+ expect{ resource.each_row{|row| nil} }.to raise_error
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataPackage::Schema do
4
+ let(:json) {
5
+ {
6
+ 'fields' => [
7
+ {
8
+ 'name' => 'income',
9
+ 'type' => 'number'
10
+ }
11
+ ],
12
+
13
+ 'primaryKey' => ['income']
14
+ }
15
+ }
16
+
17
+ it "should initialize" do
18
+ schema = DataPackage::Schema.new(json)
19
+
20
+ schema.fields.length.should == 1
21
+ schema.fields.first.name.should == 'income'
22
+ schema.primary_key.should == ['income']
23
+ schema.to_json.should == Yajl::Encoder.encode(json, :pretty => true)
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataPackage::Source do
4
+ let(:json) {
5
+ {
6
+ 'name' => 'Josh F',
7
+ 'email' => 'josh@modeanalytics.com',
8
+ 'web' => 'http://www.modeanalytics.com/josh'
9
+ }
10
+ }
11
+
12
+ it "should initialize and serialize" do
13
+ person = DataPackage::Source.new(json)
14
+
15
+ person.name.should == 'Josh F'
16
+ person.email.should == 'josh@modeanalytics.com'
17
+ person.web.should == 'http://www.modeanalytics.com/josh'
18
+
19
+ person.to_hash.should == json
20
+ person.to_json.should == Yajl::Encoder.encode(person.to_hash, :pretty => true)
21
+ end
22
+ end
@@ -0,0 +1,94 @@
1
+ {
2
+ "name": "standard",
3
+ "version": "0.0.1",
4
+ "title": "Standard Data Package",
5
+
6
+ "sources": [
7
+ {
8
+ "name": "Josh F",
9
+ "email": "josh@modeanalytics.com",
10
+ "web": "http://www.modeanalytics.com/josh"
11
+ }
12
+ ],
13
+
14
+ "licenses": [
15
+ {
16
+ "id": "PDDL",
17
+ "url": "http://opendatacommons.org/licenses/pddl/"
18
+ }
19
+ ],
20
+
21
+ "maintainers": [
22
+ {
23
+ "name": "Josh F",
24
+ "email": "josh@modeanalytics.com",
25
+ "web": "http://www.modeanalytics.com/josh"
26
+ }
27
+ ],
28
+
29
+ "contributors": [
30
+ {
31
+ "name": "Josh F",
32
+ "email": "josh@modeanalytics.com",
33
+ "web": "http://www.modeanalytics.com/josh"
34
+ }
35
+ ],
36
+
37
+ "resources": [
38
+ {
39
+ "name": "standard",
40
+ "path": "standard.csv",
41
+
42
+ "dialect": {
43
+ "delimiter": ","
44
+ },
45
+
46
+ "schema": {
47
+ "fields": [
48
+ {
49
+ "name": "id",
50
+ "type": "integer"
51
+ },
52
+ {
53
+ "name": "first_name",
54
+ "type": "string"
55
+ },
56
+ {
57
+ "name": "last_name",
58
+ "type": "string"
59
+ },
60
+ {
61
+ "name": "email",
62
+ "type": "string"
63
+ },
64
+ {
65
+ "name": "country",
66
+ "type": "string"
67
+ },
68
+ {
69
+ "name": "ip_address",
70
+ "type": "string"
71
+ },
72
+ {
73
+ "name": "amount",
74
+ "type": "number"
75
+ },
76
+ {
77
+ "name": "active",
78
+ "type": "boolean"
79
+ },
80
+ {
81
+ "name": "activated_at",
82
+ "type": "datetime"
83
+ },
84
+ {
85
+ "name": "address",
86
+ "type": "string"
87
+ }
88
+ ],
89
+
90
+ "primaryKey": ["id"]
91
+ }
92
+ }
93
+ ]
94
+ }
@@ -0,0 +1,11 @@
1
+ id,first_name,last_name,email,country,ip_address,amount,active,activated_at,address
2
+ 1,Todd,Hamilton,thamilton@plambee.edu,Norfolk Island,66.157.128.241,$7.72,true,10/3/1955,0582 Dwight Street
3
+ 2,Melissa,Kelly,mkelly@twinte.name,Singapore,204.221.167.233,$4.33,false,7/9/2013,06 Cardinal Crossing
4
+ 3,Donald,Wheeler,dwheeler@edgeify.mil,Madagascar,34.201.104.193,$2.92,true,12/12/1993,4 Del Sol Hill
5
+ 4,Ruby,Hall,rhall@cogilith.com,USSR,237.243.109.67,$8.27,false,12/15/1975,7 Ramsey Avenue
6
+ 5,Jessica,Cole,jcole@shuffletag.info,Cyprus,25.40.138.137,$8.16,false,6/2/1939,8142 Novick Hill
7
+ 6,Doris,Nelson,dnelson@zoombox.biz,Svalbard and Jan Mayen Islands,233.43.155.229,$6.26,false,5/23/1948,596 Veith Road
8
+ 7,Robert,Hansen,rhansen@miboo.edu,Ghana,41.194.33.211,$4.90,true,9/28/1999,529 Oak Pass
9
+ 8,Matthew,Freeman,mfreeman@midel.name,Sudan,53.186.162.65,$6.63,false,5/24/1996,70682 Declaration Center
10
+ 9,Julia,Nelson,jnelson@skajo.net,Vatican City State (Holy See),249.49.124.178,$9.80,true,1/26/1940,96 Hermina Lane
11
+ 10,Wanda,Palmer,wpalmer@ntags.biz,Indonesia,0.200.163.200,$5.89,false,1/1/1959,26837 Donald Trail
@@ -0,0 +1,11 @@
1
+ id,first_name,last_name,email,country,ip_address,amount,active,activated_at,address
2
+ 1,Todd,Hamilton,thamilton@plambee.edu,Norfolk Island,66.157.128.241,$7.72,true,10/3/1955,0582 Dwight Street
3
+ 2,Melissa,Kelly,mkelly@twinte.name,Singapore,204.221.167.233,$4.33,false,7/9/2013,06 Cardinal Crossing
4
+ 3,Donald,Wheeler,dwheeler@edgeify.mil,Madagascar,34.201.104.193,$2.92,true,12/12/1993,4 Del Sol Hill
5
+ 4,Ruby,Hall,rhall@cogilith.com,USSR,237.243.109.67,$8.27,false,12/15/1975,7 Ramsey Avenue
6
+ 5,Jessica,Cole,jcole@shuffletag.info,Cyprus,25.40.138.137,$8.16,false,6/2/1939,8142 Novick Hill
7
+ 6,Doris,Nelson,dnelson@zoombox.biz,Svalbard and Jan Mayen Islands,233.43.155.229,$6.26,false,5/23/1948,596 Veith Road
8
+ 7,Robert,Hansen,rhansen@miboo.edu,Ghana,41.194.33.211,$4.90,true,9/28/1999,529 Oak Pass
9
+ 8,Matthew,Freeman,mfreeman@midel.name,Sudan,53.186.162.65,$6.63,false,5/24/1996,70682 Declaration Center
10
+ 9,Julia,Nelson,jnelson@skajo.net,Vatican City State (Holy See),249.49.124.178,$9.80,true,1/26/1940,96 Hermina Lane
11
+ 10,Wanda,Palmer,wpalmer@ntags.biz,Indonesia,0.200.163.200,$5.89,false,1/1/1959,26837 Donald Trail
@@ -0,0 +1,41 @@
1
+ module KlassHelper
2
+ class BaseKlass
3
+ include AttrHelper
4
+ include AttrHelper::Serialization
5
+
6
+ attr_required :name
7
+ attr_optional :title
8
+ attr_optional :format
9
+
10
+ attr_required :data, :if => Proc.new{ |o| o.path.nil? && o.url.nil? }
11
+ attr_required :path, :if => Proc.new{ |o| o.data.nil? && o.url.nil? }
12
+ attr_required :url, :if => Proc.new{ |o| o.data.nil? && o.path.nil? }
13
+
14
+ attr_required :dialect, :if => :format_requires_dialect?
15
+
16
+ attr_required :email, :unless => :empty_name?
17
+ attr_required :web, :unless => Proc.new{ |o| o.name.nil? }
18
+
19
+ def initialize(attrs = {})
20
+ write_attributes(attrs)
21
+ end
22
+
23
+ def title=(value)
24
+ write_attribute(:title, value + 'test')
25
+ end
26
+
27
+ def format_requires_dialect?
28
+ format == 'csv'
29
+ end
30
+
31
+ def empty_name?
32
+ name.nil?
33
+ end
34
+ end
35
+
36
+ class ChildKlass < BaseKlass
37
+ def title=(value)
38
+ write_attribute(:title, value + 'child')
39
+ end
40
+ end
41
+ end