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