icss 0.1.3 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/.watchr +35 -3
  2. data/CHANGELOG.md +38 -0
  3. data/Gemfile +19 -14
  4. data/README.md +296 -0
  5. data/Rakefile +2 -6
  6. data/TODO.md +13 -0
  7. data/VERSION +1 -1
  8. data/examples/avro_examples/complicated.icss.yaml +14 -13
  9. data/examples/bnc.icss.yaml +70 -0
  10. data/examples/chronic.icss.yaml +3 -3
  11. data/examples/license.icss.yaml +7 -0
  12. data/examples/source1.icss.yaml +4 -0
  13. data/examples/source2.icss.yaml +4 -0
  14. data/examples/test_icss.yaml +67 -0
  15. data/icss.gemspec +103 -43
  16. data/lib/icss.rb +37 -15
  17. data/lib/icss/core_types.rb +19 -0
  18. data/lib/icss/error.rb +4 -0
  19. data/{init.rb → lib/icss/init.rb} +0 -0
  20. data/lib/icss/message.rb +124 -66
  21. data/lib/icss/message/message_sample.rb +144 -0
  22. data/lib/icss/protocol.rb +184 -131
  23. data/lib/icss/protocol/code_asset.rb +18 -0
  24. data/lib/icss/protocol/data_asset.rb +23 -0
  25. data/lib/icss/protocol/license.rb +41 -0
  26. data/lib/icss/protocol/source.rb +37 -0
  27. data/lib/icss/protocol/target.rb +68 -0
  28. data/lib/icss/receiver_model.rb +24 -0
  29. data/lib/icss/receiver_model/active_model_shim.rb +36 -0
  30. data/lib/icss/receiver_model/acts_as_catalog.rb +170 -0
  31. data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
  32. data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
  33. data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
  34. data/lib/icss/receiver_model/locale/en.yml +27 -0
  35. data/lib/icss/receiver_model/to_geo_json.rb +19 -0
  36. data/lib/icss/receiver_model/tree_merge.rb +34 -0
  37. data/lib/icss/receiver_model/validations.rb +31 -0
  38. data/lib/icss/serialization.rb +51 -0
  39. data/lib/icss/serialization/zaml.rb +443 -0
  40. data/lib/icss/type.rb +148 -501
  41. data/lib/icss/type/base_type.rb +0 -0
  42. data/lib/icss/type/named_type.rb +184 -0
  43. data/lib/icss/type/record_field.rb +77 -0
  44. data/lib/icss/type/record_model.rb +49 -0
  45. data/lib/icss/type/record_schema.rb +54 -0
  46. data/lib/icss/type/record_type.rb +325 -0
  47. data/lib/icss/type/simple_types.rb +72 -0
  48. data/lib/icss/type/structured_schema.rb +288 -0
  49. data/lib/icss/type/type_factory.rb +144 -0
  50. data/lib/icss/type/union_schema.rb +41 -0
  51. data/lib/icss/view_helper.rb +56 -19
  52. data/notes/named_array.md +32 -0
  53. data/notes/on_include_vs_extend_etc.rb +176 -0
  54. data/notes/technical_details.md +278 -0
  55. data/spec/core_types_spec.rb +119 -0
  56. data/spec/fixtures/zaml_complex_hash.yaml +35 -0
  57. data/spec/icss_spec.rb +86 -23
  58. data/spec/message/message_sample_spec.rb +4 -0
  59. data/spec/message_spec.rb +139 -0
  60. data/spec/protocol/license_spec.rb +67 -0
  61. data/spec/protocol/protocol_catalog_spec.rb +48 -0
  62. data/spec/protocol/protocol_validations_spec.rb +176 -0
  63. data/spec/protocol/source_spec.rb +65 -0
  64. data/spec/protocol_spec.rb +91 -37
  65. data/spec/receiver_model_spec.rb +111 -0
  66. data/spec/serialization/zaml_spec.rb +81 -0
  67. data/spec/serialization/zaml_test.rb +473 -0
  68. data/spec/serialization_spec.rb +63 -0
  69. data/spec/spec_helper.rb +24 -7
  70. data/spec/support/icss_test_helper.rb +67 -0
  71. data/spec/support/load_example_protocols.rb +17 -0
  72. data/spec/type/base_type_spec.rb +0 -0
  73. data/spec/type/named_type_spec.rb +75 -0
  74. data/spec/type/record_field_spec.rb +44 -0
  75. data/spec/type/record_model_spec.rb +206 -0
  76. data/spec/type/record_schema_spec.rb +161 -0
  77. data/spec/type/record_type_spec.rb +155 -0
  78. data/spec/type/simple_types_spec.rb +121 -0
  79. data/spec/type/structured_schema_spec.rb +300 -0
  80. data/spec/type/type_catalog_spec.rb +44 -0
  81. data/spec/type/type_factory_spec.rb +93 -0
  82. data/spec/type/union_schema_spec.rb +0 -0
  83. data/spec/type_spec.rb +63 -0
  84. metadata +205 -144
  85. data/CHANGELOG.textile +0 -9
  86. data/Gemfile.lock +0 -40
  87. data/README.textile +0 -29
  88. data/lib/icss/brevity.rb +0 -136
  89. data/lib/icss/code_asset.rb +0 -16
  90. data/lib/icss/core_ext.rb +0 -9
  91. data/lib/icss/data_asset.rb +0 -22
  92. data/lib/icss/old.rb +0 -96
  93. data/lib/icss/protocol_set.rb +0 -48
  94. data/lib/icss/sample_message_call.rb +0 -142
  95. data/lib/icss/target.rb +0 -72
  96. data/lib/icss/type/factory.rb +0 -196
  97. data/lib/icss/validations.rb +0 -16
  98. data/spec/validations_spec.rb +0 -171
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'icss'
3
+
4
+ describe Icss::Meta::Protocol do
5
+ before do
6
+ Icss::Meta::Protocol.send :flush_registry
7
+ Icss::Meta::Protocol._catalog_loaded = true #prevent automatic loading of catalog
8
+ end
9
+ let(:protocol){ Icss::Meta::Protocol.receive(:protocol => 'test', :namespace => 'name.space') }
10
+
11
+ # Calling receive adds protocol to registry with after_receiver
12
+ describe :registry do
13
+ specify { Icss::Meta::Protocol.registry.should include('name.space.test' => protocol) }
14
+ end
15
+
16
+ describe '#find' do
17
+ context 'specific protocol name parameters' do
18
+ before { protocol } # load protocol into registry
19
+ it('return protocol'){ Icss::Meta::Protocol.find('name.space.test').should == protocol }
20
+ it('should error if not found'){ lambda{ Icss::Meta::Protocol.find('name.space.not.found') }.should raise_error(Icss::NotFoundError) }
21
+ it('should error for wildcard name'){ lambda{ Icss::Meta::Protocol.find('name.*.test') }.should raise_error(Icss::NotFoundError) }
22
+ end
23
+
24
+ context 'wildcard protocol name parameters' do
25
+ before { protocol } # load protocol into registry
26
+ context ':all' do
27
+ it('accepts wilcard names'){ Icss::Meta::Protocol.find(:all, 'name.*').should == [protocol] }
28
+ it('returns empty array if not found'){ Icss::Meta::Protocol.find(:all, 'not.*.found').should == [] }
29
+ end
30
+
31
+ context ':first' do
32
+ it('accepts wilcard names'){ Icss::Meta::Protocol.find(:first, 'name.*').should == protocol }
33
+ it('returns nil if not found'){ Icss::Meta::Protocol.find(:first, 'not.*.found').should be_nil }
34
+ end
35
+
36
+ context ':last' do
37
+ it('accepts wilcard names'){ Icss::Meta::Protocol.find(:last, 'name.*').should == protocol }
38
+ it('returns nil if not found'){ Icss::Meta::Protocol.find(:last, 'not.*.found').should be_nil }
39
+ end
40
+ end
41
+ end
42
+ describe '#all, #first, #last' do
43
+ before { protocol } # load protocol into registry
44
+ it('#all returns all protocols'){ Icss::Meta::Protocol.all.should == [protocol] }
45
+ it('#first returns first of all protocols'){ Icss::Meta::Protocol.first.should == protocol }
46
+ it('#last returns last of all protocols'){ Icss::Meta::Protocol.last.should == protocol }
47
+ end
48
+ end
@@ -0,0 +1,176 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'icss'
4
+
5
+ def template_icss
6
+ return <<EOS
7
+ ---
8
+ namespace: foo.bar
9
+ protocol: baz
10
+
11
+ data_assets:
12
+ - name: test_data_asset
13
+ location: data/test_data.tsv
14
+ type: test_data_record
15
+
16
+ messages:
17
+ search:
18
+ doc: A testable template message
19
+ request:
20
+ - name: test_request
21
+ type: test_request_record
22
+ response: test_data_record
23
+ samples:
24
+ - request:
25
+ - first_param: foo
26
+ second_param: bar
27
+
28
+ targets:
29
+ catalog:
30
+ - name: test_catalog_entry
31
+ title: Test Icss
32
+ description: This is a template Icss to test the error handling of the Icss library.
33
+ tags:
34
+ - test
35
+ - icss
36
+ - template
37
+ messages:
38
+ - search
39
+ packages:
40
+ - data_assets:
41
+ - test_data_asset
42
+
43
+ types:
44
+ - name: test_request_record
45
+ doc: A template request record
46
+ type: record
47
+ fields:
48
+ - name: first_param
49
+ doc: The first test parameter
50
+ type: string
51
+ - name: second param
52
+ doc: The second test parameter
53
+ type: string
54
+
55
+ - name: test_complex_data
56
+ doc: A template complex data type
57
+ type: record
58
+ fields:
59
+ - name: field_one
60
+ doc: A simple field for a complex data type
61
+ type: string
62
+ - name: field_two
63
+ doc: Another simple field for a complex data type
64
+ type: string
65
+
66
+ - name: test_data_record
67
+ doc: A template data record
68
+ type: record
69
+ fields:
70
+ - name: simple_data
71
+ doc: A simple piece of data
72
+ type: int
73
+ - name: complex_data
74
+ doc: A complex piece of data
75
+ type: test_complex_data
76
+
77
+ EOS
78
+ end
79
+
80
+ describe "Icss::Meta::Protocol validations" do
81
+ before :each do
82
+ @template = YAML.load(template_icss)
83
+ end
84
+
85
+ after :all do
86
+ Icss::Meta::TypeFactory.send :remove_instance_variable, :"@default_namespace"
87
+ end
88
+
89
+ it "should be able to receive a correctly formatted template Icss" do
90
+ lambda { @icss =Icss::Meta::Protocol.receive @template }.should_not raise_error
91
+ @icss.errors.should be_empty
92
+ end
93
+
94
+ it "should contain keys for all fields even if not included in the Icss file" do
95
+ @icss = Icss::Meta::Protocol.receive @template
96
+ @icss.keys.map{|k| k.to_s }.sort.should == (@template.keys | %w[code_assets _doc_hints _extra_params tags categories credits doc title]).sort
97
+ end
98
+
99
+ it "should generate an error when the namespace is formatted incorrectly" do
100
+ @template['namespace'] = '$bad_namespace'
101
+ Icss::Meta::Protocol.receive(@template).errors.keys.should == [:namespace]
102
+ end
103
+
104
+ it "should generate an error when the protocol is formatted incorrectly" do
105
+ @template['protocol'] = '$bad_protocol'
106
+ Icss::Meta::Protocol.receive(@template).errors.keys.should == [:protocol]
107
+ end
108
+
109
+ # context "Catalog Target" do
110
+ #
111
+ # it "should generate an error when an undefined data_asset is specified" do
112
+ # @template['targets']['catalog'].first['packages'].first['data_assets'] = ['fake_data_asset']
113
+ # Icss::Meta::Protocol.receive(@template).errors.keys.should == [:catalog]
114
+ # end
115
+ #
116
+ # it "should generate an error when an undefined message name is specified" do
117
+ # @template['targets']['catalog'].first['messages'] = ['fake_message']
118
+ # Icss::Meta::Protocol.receive(@template).errors.keys.should == [:catalog]
119
+ # end
120
+ #
121
+ # end
122
+ #
123
+ # context "Data Assets" do
124
+ #
125
+ # it "should generate an error when an asset's type is undefined" do
126
+ # @template['data_assets'].first['type'] = 'fake_data_asset'
127
+ # Icss::Meta::Protocol.receive(@template).errors.keys.should == [:data_assets]
128
+ # end
129
+ #
130
+ # end
131
+ #
132
+ # context "Messages" do
133
+ #
134
+ # it "should generate an error when a message's request type is undefined" do
135
+ # @template['messages']['search']['request'].first['type'] = 'fake_request_type'
136
+ # Icss::Meta::Protocol.receive(@template).errors.keys.should == [:messages]
137
+ # end
138
+ #
139
+ # it "should generate an error when a message's response type is undefined" do
140
+ # @template['messages']['search']['response'] = 'fake_response_type'
141
+ # Icss::Meta::Protocol.receive(@template).errors.keys.should == [:messages]
142
+ # end
143
+ #
144
+ # it "should generate an error when a message's sample request types do not match the request record" do
145
+ # @template['messages']['search']['samples'].first['request'] = [{ 'foo' => 'bar' }]
146
+ # Icss::Meta::Protocol.receive(@template).errors.keys.should == [:messages]
147
+ # end
148
+ #
149
+ # end
150
+
151
+ context "Types" do
152
+
153
+ it "should raise an error when an bad type definition is given for a specific type" do
154
+ @template['types'].push({
155
+ 'name' => 'fake_type_record',
156
+ 'type' => 'fake'
157
+ })
158
+ lambda{ Icss::Meta::Protocol.receive(@template) }.should raise_error(Icss::NotFoundError, /Cannot find.*fake/)
159
+ end
160
+
161
+ it "should generate an error when an undefined type definition is given for a specific field" do
162
+ @template['types'].push({
163
+ 'name' => 'fake_type_record',
164
+ 'type' => 'record',
165
+ 'fields' => [{
166
+ 'name' => 'fake_field',
167
+ 'type' => 'fake_type'
168
+ }]
169
+ })
170
+ lambda{ Icss::Meta::Protocol.receive(@template) }.should raise_error(Icss::NotFoundError, /Cannot find.*fake_type/)
171
+
172
+ end
173
+
174
+ end
175
+
176
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'icss'
3
+
4
+ describe Icss::Meta::Source do
5
+ before do
6
+ Icss::Meta::Source.send :flush_registry
7
+ Icss::Meta::Source._catalog_loaded = true #prevent automatic loading of catalog
8
+ end
9
+ let(:source){ Icss::Meta::Source.receive(:source_id => 'sources.test', :title => 'Test source', :description => 'Source description', :url => 'http://test.com') }
10
+
11
+ describe '#name' do
12
+ specify { source.name.should == 'test' }
13
+ end
14
+
15
+ describe '#fullname' do
16
+ specify { source.fullname.should == 'sources.test' }
17
+ end
18
+
19
+
20
+
21
+ # Calling receive adds source to registry with after_receiver
22
+ describe :registry do
23
+ specify { Icss::Meta::Source.registry.should include('sources.test' => source) }
24
+ end
25
+
26
+ describe '#find' do
27
+ context 'specific source name parameters' do
28
+ before { source } # load source into registry
29
+ it('return source'){ Icss::Meta::Source.find('sources.test').should == source }
30
+ it('should error if not found'){ lambda{ Icss::Meta::Source.find('sources.not_found') }.should raise_error(Icss::NotFoundError) }
31
+ it('should error for wildcard name'){ lambda{ Icss::Meta::Source.find('sources.*.test') }.should raise_error(Icss::NotFoundError) }
32
+ end
33
+
34
+ context 'wildcard source name parameters' do
35
+ before { source } # load source into registry
36
+ context ':all' do
37
+ it('accepts wilcard names'){ Icss::Meta::Source.find(:all, 'sources.*').should == [source] }
38
+ it('returns empty array if not found'){ Icss::Meta::Source.find(:all, 'not.*.found').should == [] }
39
+ end
40
+
41
+ context ':first' do
42
+ it('accepts wilcard names'){ Icss::Meta::Source.find(:first, 'sources.*').should == source }
43
+ it('returns nil if not found'){ Icss::Meta::Source.find(:first, 'not.*.found').should be_nil }
44
+ end
45
+
46
+ context ':last' do
47
+ it('accepts wilcard names'){ Icss::Meta::Source.find(:last, 'sources.*').should == source }
48
+ it('returns nil if not found'){ Icss::Meta::Source.find(:last, 'not.*.found').should be_nil }
49
+ end
50
+ end
51
+ end
52
+ describe '#all, #first, #last' do
53
+ before { source } # load source into registry
54
+ it('#all returns all sources'){ Icss::Meta::Source.all.should == [source] }
55
+ it('#first returns first of all sources'){ Icss::Meta::Source.first.should == source }
56
+ it('#last returns last of all sources'){ Icss::Meta::Source.last.should == source }
57
+ end
58
+
59
+ describe '#to_hash' do
60
+ it { source.to_hash.should == {:source_id => 'sources.test',
61
+ :title => 'Test source',
62
+ :description => 'Source description',
63
+ :url => 'http://test.com'}}
64
+ end
65
+ end
@@ -1,26 +1,27 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require 'icss'
3
3
 
4
- describe Icss::Protocol do
4
+ describe Icss::Meta::Protocol do
5
+
5
6
  let(:simple_icss) do
6
- Icss::Protocol.receive_from_file(ICSS_ROOT_DIR('examples/chronic.icss.yaml'))
7
+ Icss::Meta::Protocol.receive_from_file(ENV.root_path('examples/chronic.icss.yaml'))
7
8
  end
8
9
 
9
10
  it 'loads cleanly' do
10
- simple_icss.name.should == 'chronic'
11
- simple_icss.fullname.should == 'util.time.chronic'
11
+ simple_icss.basename.should == 'chronic'
12
+ simple_icss.fullname.should == 'st.time_utils.chronic'
12
13
  end
13
14
 
14
15
  describe '#fullname' do
15
- it 'has namespace and name' do
16
- simple_icss.fullname.should == 'util.time.chronic'
16
+ it 'has namespace and basename' do
17
+ simple_icss.fullname.should == 'st.time_utils.chronic'
17
18
  simple_icss.namespace = nil
18
19
  simple_icss.fullname.should == 'chronic'
19
20
  end
20
21
  end
21
22
  describe '#path' do
22
23
  it 'is a / separated version of the name, with no / at start' do
23
- simple_icss.path.should == 'util/time/chronic'
24
+ simple_icss.path.should == 'st/time_utils/chronic'
24
25
  end
25
26
  end
26
27
  describe '#doc' do
@@ -31,7 +32,7 @@ describe Icss::Protocol do
31
32
 
32
33
  describe 'types' do
33
34
  it 'has an array of types' do
34
- simple_icss.types.map(&:name).should == ['chronic_parse_params', 'chronic_parse_response']
35
+ simple_icss.types.map(&:basename).should == ['chronic_parse_params', 'chronic_parse_response']
35
36
  end
36
37
  end
37
38
 
@@ -41,73 +42,126 @@ describe Icss::Protocol do
41
42
  end
42
43
 
43
44
  it 'named each message for its key' do
44
- simple_icss.messages['parse'].name.should == 'parse'
45
+ simple_icss.messages['parse'].basename.should == 'parse'
45
46
  simple_icss.receive!({ :messages => { 'foo' => { :request => [] } }})
46
- simple_icss.messages['foo'].name.should == 'foo'
47
+ simple_icss.messages['foo'].basename.should == 'foo'
47
48
  end
48
49
 
49
50
  it '#find_message' do
50
51
  msg = simple_icss.find_message(:parse)
51
- msg.should be_a(Icss::Message) ; msg.name.should == 'parse'
52
- msg = simple_icss.find_message('util.time.parse')
53
- msg.should be_a(Icss::Message) ; msg.name.should == 'parse'
54
- msg = simple_icss.find_message('util/time/parse')
55
- msg.should be_a(Icss::Message) ; msg.name.should == 'parse'
52
+ msg.should be_a(Icss::Meta::Message) ; msg.basename.should == 'parse'
53
+ msg = simple_icss.find_message('st.time_utils.parse')
54
+ msg.should be_a(Icss::Meta::Message) ; msg.basename.should == 'parse'
55
+ msg = simple_icss.find_message('st/time_utils/parse')
56
+ msg.should be_a(Icss::Meta::Message) ; msg.basename.should == 'parse'
56
57
  end
57
58
  end
58
59
 
59
60
  describe 'targets' do
60
61
  it 'has a hash of targets' do
61
- simple_icss.targets.keys.should == ['catalog']
62
- simple_icss.targets['catalog'].first.should be_a(Icss::CatalogTarget)
63
- simple_icss.targets['catalog'].first.name.should == 'util_time_chronic_parse'
62
+ simple_icss.targets.keys.should == [:catalog]
63
+ simple_icss.targets[:catalog].first.should be_a(Icss::CatalogTarget)
64
+ simple_icss.targets[:catalog].first.basename.should == 'st_time_utils_chronic_parse'
65
+ end
66
+ end
67
+
68
+ describe 'license' do
69
+ it 'returns nil if no license_id specified' do
70
+ simple_icss.license.should be_nil
71
+ end
72
+ it 'raises Icss::NotFoundError if license_id specified and not found' do
73
+ simple_icss.license_id = 'not_found_license'
74
+ lambda{ simple_icss.license }.should raise_error(Icss::NotFoundError, /Cannot find .*/)
75
+ end
76
+ it 'returns the Icss::Meta::License object' do
77
+ license = Icss::Meta::License.receive_from_file(ENV.root_path('examples/license.icss.yaml'))
78
+ simple_icss.license_id = 'licenses.example'
79
+ simple_icss.license.should == license
80
+ end
81
+ end
82
+
83
+
84
+
85
+ describe 'sources' do
86
+ it 'returns empty array if no source_ids specified' do
87
+ simple_icss.sources.should == {}
88
+ end
89
+ it 'raises Icss::NotFoundError if license_id specified and not found' do
90
+ simple_icss.credits = { :role => 'not_found_license' }
91
+ lambda{ simple_icss.sources }.should raise_error(Icss::NotFoundError, /Cannot find .*/)
92
+ end
93
+ it 'returns array of Icss::Meta::Source objects' do
94
+ source2 = Icss::Meta::Source.receive_from_file(ENV.root_path('examples/source2.icss.yaml'))
95
+ source1 = Icss::Meta::Source.receive_from_file(ENV.root_path('examples/source1.icss.yaml'))
96
+ simple_icss.credits = {:main => 'sources.source1', :uploaded => 'sources.source2'}
97
+ simple_icss.sources.should == { :main => source1, :uploaded => source2 }
64
98
  end
65
99
  end
66
-
67
- # describe 'tree_merge!' do
68
- # it 'merges recursively'
69
- # end
70
100
 
71
101
  describe 'validations' do
72
102
  it 'validates protocol name' do
73
103
  simple_icss.should be_valid
74
- simple_icss.protocol = '' ; simple_icss.should_not be_valid ; simple_icss.errors[:protocol].should == ["can't be blank"]
75
- simple_icss.protocol = '1bz' ; simple_icss.should_not be_valid ; simple_icss.errors[:protocol].should == ["must start with [A-Za-z_] and contain only [A-Za-z0-9_]."]
104
+ simple_icss.protocol = '' ; simple_icss.should_not be_valid ; simple_icss.errors[:protocol].should include("can't be blank")
105
+ simple_icss.protocol = '1bz' ; simple_icss.should_not be_valid ; simple_icss.errors[:protocol].should include("must start with [A-Za-z_] and contain only [A-Za-z0-9_].")
76
106
  end
77
107
 
78
108
  it 'validates namespace' do
79
109
  simple_icss.should be_valid
80
- simple_icss.namespace = '' ; simple_icss.should_not be_valid ; simple_icss.errors[:namespace].should == ["can't be blank"]
81
- simple_icss.namespace = '1bz' ; simple_icss.should_not be_valid ; simple_icss.errors[:namespace].first.should =~ /must be a dot-s/
110
+ simple_icss.namespace = '' ; simple_icss.should_not be_valid ; simple_icss.errors[:namespace].should include("can't be blank")
111
+ simple_icss.namespace = '1bz' ; simple_icss.should_not be_valid ; simple_icss.errors[:namespace].first.should =~ /Segments that start with.*joined by.*dots/
82
112
  end
83
113
  end
84
114
 
85
115
  describe '#to_hash' do
86
116
  it 'roundtrips' do
117
+ simple_icss.license_id = 'licenses.example'
118
+ simple_icss.credits = { :original => 'sources.source1' }
119
+ simple_icss.tags = ['tag1', 'tag2', 'tag3']
120
+ simple_icss.categories = ['category1', 'category2', 'category3']
87
121
  hsh = simple_icss.to_hash
88
122
  hsh.should == {
89
- :namespace=>"util.time", :protocol=>"chronic",
123
+ :namespace=>"st.time_utils", :protocol=>"chronic",
90
124
  :doc=>"A series of calls hooking into the Chronic ruby gem",
125
+ :license_id=>"licenses.example",
126
+ :credits=>{:original=>"sources.source1"},
127
+ :tags=>['tag1', 'tag2', 'tag3'],
128
+ :categories=>['category1', 'category2', 'category3'],
91
129
  :types => [
92
- {:name=>"chronic_parse_params", :doc=>"Query API parameters for the /util/time/chronic/parse call", :type=>:record,
130
+ {:name=>"st.time_utils.chronic_parse_params",
131
+ :namespace=>"st.time_utils",
132
+ :type=>:record,
133
+ :doc=>"Query API parameters for the /st/time_utils/chronic/parse call",
93
134
  :fields=>[
94
- {:name=>"time_str", :type=>:string, :doc=>"The string to parse."},
95
- {:name=>"context", :type=>:symbol, :doc=>"<tt>past</tt> or <tt>future</tt> (defaults to <tt>future</tt>)\nIf your string represents a birthday, you can set <tt>context</tt> to <tt>past</tt> and if an ambiguous string is given, it will assume it is in the past. Specify <tt>future</tt> or omit to set a future context."},
96
- {:name=>"now", :type=>:time, :doc=>"Time (defaults to Time.now)\nBy setting <tt>:now</tt> to a Time, all computations will be based off of that time instead of Time.now. If set to nil, Chronic will use the current time in UTC. You must supply a date that unambiguously parses with the much-less-generous ruby Time.parse()"},
97
- {:name=>"ambiguous_time_range", :type=>:int, :doc=>"Integer or <tt>:none</tt> (defaults to <tt>6</tt> (6am-6pm))\nIf an Integer is given, ambiguous times (like 5:00) will be assumed to be within the range of that time in the AM to that time in the PM. For example, if you set it to <tt>7</tt>, then the parser will look for the time between 7am and 7pm. In the case of 5:00, it would assume that means 5:00pm. If <tt>:none</tt> is given, no assumption will be made, and the first matching instance of that time will be used."}
135
+ {:name=>:time_str, :type=>:string, :doc=>"The string to parse."},
136
+ {:name=>:context, :type=>:symbol, :doc=>"<tt>past</tt> or <tt>future</tt> (defaults to <tt>future</tt>)\nIf your string represents a birthday, you can set <tt>context</tt> to <tt>past</tt> and if an ambiguous string is given, it will assume it is in the past. Specify <tt>future</tt> or omit to set a future context."},
137
+ {:name=>:now, :type=>:time, :doc=>"Time (defaults to Time.now)\nBy setting <tt>:now</tt> to a Time, all computations will be based off of that time instead of Time.now. If set to nil, Chronic will use the current time in UTC. You must supply a date that unambiguously parses with the much-less-generous ruby Time.parse()"},
138
+ {:name=>:ambiguous_time_range, :type=>:int, :doc=>"Integer or <tt>:none</tt> (defaults to <tt>6</tt> (6am-6pm))\nIf an Integer is given, ambiguous times (like 5:00) will be assumed to be within the range of that time in the AM to that time in the PM. For example, if you set it to <tt>7</tt>, then the parser will look for the time between 7am and 7pm. In the case of 5:00, it would assume that means 5:00pm. If <tt>:none</tt> is given, no assumption will be made, and the first matching instance of that time will be used."}
98
139
  ]},
99
- {:name=>"chronic_parse_response", :doc=>"Query API response for the /util/time/chronic/parse call", :type=>:record,
140
+ {:name=>"st.time_utils.chronic_parse_response",
141
+ :namespace=>"st.time_utils",
142
+ :type=>:record,
143
+ :doc=>"Query API response for the /util/time/chronic/parse call",
100
144
  :fields=>[
101
- {:name=>"time", :type=>:string, :doc=>"The UTC parsed time, as a \"ISO 8601 combined date time\":http://en.wikipedia.org/wiki/ISO_8601 string."},
102
- {:name=>"epoch_seconds", :type=>:int, :doc=>"The UTC parsed time, as \"epoch seconds\":http://en.wikipedia.org/wiki/Epoch_seconds integer."}
145
+ {:name=>:time, :type=>:string, :doc=>"The UTC parsed time, as a \"ISO 8601 combined date time\":http://en.wikipedia.org/wiki/ISO_8601 string."},
146
+ {:name=>:epoch_seconds, :type=>:int, :doc=>"The UTC parsed time, as \"epoch seconds\":http://en.wikipedia.org/wiki/Epoch_seconds integer."}
103
147
  ]}
104
148
  ],
105
149
  :messages => {
106
- 'parse' => {:doc=>"\nChronic is a natural language date/time parser written in pure Ruby. See below\nfor the wide variety of formats Chronic will parse.", :request=>[{:name=>"chronic_parse_params", :type=>"chronic_parse_params"}], :response=>"chronic_parse_response", :samples=>[{:request=>[{"time_str"=>"one hour ago", "now"=>"2007-03-16T12:09:08Z"}], :response=>{"epoch_seconds"=>1174043348, "time"=>"2007-03-16T11:09:08Z"}, :url=>"?now=2007-03-16T12%3A09%3A08Z&time_str=one%20hour%20ago"}, {:request=>[{"time_str"=>"Yesterday", "now"=>"5:06:07T2010-08-08Z"}], :response=>{"epoch_seconds"=>1281182400, "time"=>"2010-08-07T12:00:00Z"}, :url=>"?now=5%3A06%3A07%202010-08-08&time_str=Yesterday"}, {:url=>"?time_str=5pm+on+November+4th&context=past"}]},
150
+ :parse => {
151
+ :request =>[{:name=>:chronic_parse_params, :type=>"st.time_utils.chronic_parse_params"}],
152
+ :response =>"st.time_utils.chronic_parse_response",
153
+ :doc=>"\nChronic is a natural language date/time parser written in pure Ruby. See below\nfor the wide variety of formats Chronic will parse.",
154
+ :samples =>[{
155
+ :request=>[{"time_str"=>"one hour ago", "now"=>"2007-03-16T12:09:08Z"}],
156
+ :response=>{"epoch_seconds"=>1174043348, "time"=>"2007-03-16T11:09:08Z"}, :url=>"?now=2007-03-16T12%3A09%3A08Z&time_str=one%20hour%20ago"},
157
+ {:request=>[{"time_str"=>"Yesterday", "now"=>"5:06:07T2010-08-08Z"}],
158
+ :response=>{"epoch_seconds"=>1281182400, "time"=>"2010-08-07T12:00:00Z"}, :url=>"?now=5%3A06%3A07%202010-08-08&time_str=Yesterday"},
159
+ {:url=>"?time_str=5pm+on+November+4th&context=past"}]
160
+ },
107
161
  },
108
162
  :data_assets=>[],
109
163
  :code_assets=>[{:location=>"code/chronic_endpoint.rb"}],
110
- :targets => {"catalog"=>[{:name=>"util_time_chronic_parse", :title=>"Utils - Parse Times", :description=>"An API call to parse human-readable date / time strings", :tags=>["apiawesome", "ruby", "gems", "chronic", "time", "date", "util", "parse"], :messages=>["parse"]}]},
164
+ :targets => {:catalog=>[{:name=>"st_time_utils_chronic_parse", :title=>"Utils - Parse Times", :description=>"An API call to parse human-readable date / time strings", :tags=>["apiawesome", "ruby", "gems", "chronic", "time", "date", "util", "parse"], :messages=>["parse"]}]},
111
165
  }
112
166
  end
113
167
  end