icss 0.1.2 → 0.1.3
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/.watchr +1 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +8 -0
- data/TODO.md +31 -0
- data/VERSION +1 -1
- data/examples/chronic.icss.yaml +3 -0
- data/icss.gemspec +10 -4
- data/lib/icss.rb +2 -3
- data/lib/icss/protocol.rb +19 -15
- data/spec/protocol_spec.rb +109 -3
- data/spec/validations_spec.rb +171 -0
- metadata +32 -13
data/.watchr
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
activemodel (3.0.9)
|
5
|
+
activesupport (= 3.0.9)
|
6
|
+
builder (~> 2.1.2)
|
7
|
+
i18n (~> 0.5.0)
|
8
|
+
activesupport (3.0.9)
|
9
|
+
builder (2.1.2)
|
4
10
|
diff-lcs (1.1.2)
|
5
11
|
git (1.2.5)
|
6
12
|
gorillib (0.1.1)
|
13
|
+
i18n (0.5.0)
|
7
14
|
jeweler (1.5.2)
|
8
15
|
bundler (~> 1.0.0)
|
9
16
|
git (>= 1.2.5)
|
@@ -24,6 +31,7 @@ PLATFORMS
|
|
24
31
|
ruby
|
25
32
|
|
26
33
|
DEPENDENCIES
|
34
|
+
activemodel (~> 3.0.9)
|
27
35
|
bundler (~> 1.0.0)
|
28
36
|
gorillib (~> 0.1.1)
|
29
37
|
jeweler (~> 1.5.2)
|
data/TODO.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Proposed ICSS refactoring:
|
2
|
+
|
3
|
+
* one ICSS <=> one Dataset <=> one Catalog Entry
|
4
|
+
|
5
|
+
|
6
|
+
### catalog_entry
|
7
|
+
|
8
|
+
Most of it moves to top-level:
|
9
|
+
* tags: move to top-level attribute
|
10
|
+
* title: disappears -- take from `protocol`
|
11
|
+
* description: disappears -- take from `doc`
|
12
|
+
* owner: stays in catalog_entry
|
13
|
+
* price: attach to bulk data target
|
14
|
+
|
15
|
+
* messages: only necessary to select among messages
|
16
|
+
* packages: only necessary to select among packages
|
17
|
+
|
18
|
+
move to a new top-level section, `provenance`:
|
19
|
+
|
20
|
+
* license
|
21
|
+
* link -> becomes sources
|
22
|
+
|
23
|
+
moves *to* catalog_entry:
|
24
|
+
|
25
|
+
* `under_consideration`
|
26
|
+
* `update_frequency` (?? def. doesn't feel like a top-level thing, but this feels weird too)
|
27
|
+
|
28
|
+
|
29
|
+
___________________________________________________________________________
|
30
|
+
|
31
|
+
Make the get_data part of culture/books/comics/grand_comics_db a three-liner
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/examples/chronic.icss.yaml
CHANGED
data/icss.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{icss}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Philip (flip) Kromer for Infochimps"]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-15}
|
13
13
|
s.description = %q{Infochimps Stupid Schema library: an avro-compatible data description standard. ICSS completely describes a collection of data (and associated assets) in a way that is expressive, scalable and sufficient to drive remarkably complex downstream processes.}
|
14
14
|
s.email = %q{coders@infochimps.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
"LICENSE.textile",
|
27
27
|
"README.textile",
|
28
28
|
"Rakefile",
|
29
|
+
"TODO.md",
|
29
30
|
"VERSION",
|
30
31
|
"examples/avro_examples/BulkData.avpr",
|
31
32
|
"examples/avro_examples/complicated.icss.yaml",
|
@@ -61,7 +62,8 @@ Gem::Specification.new do |s|
|
|
61
62
|
"lib/icss/view_helper.rb",
|
62
63
|
"spec/icss_spec.rb",
|
63
64
|
"spec/protocol_spec.rb",
|
64
|
-
"spec/spec_helper.rb"
|
65
|
+
"spec/spec_helper.rb",
|
66
|
+
"spec/validations_spec.rb"
|
65
67
|
]
|
66
68
|
s.homepage = %q{http://github.com/mrflip/icss}
|
67
69
|
s.licenses = ["MIT"]
|
@@ -71,7 +73,8 @@ Gem::Specification.new do |s|
|
|
71
73
|
s.test_files = [
|
72
74
|
"spec/icss_spec.rb",
|
73
75
|
"spec/protocol_spec.rb",
|
74
|
-
"spec/spec_helper.rb"
|
76
|
+
"spec/spec_helper.rb",
|
77
|
+
"spec/validations_spec.rb"
|
75
78
|
]
|
76
79
|
|
77
80
|
if s.respond_to? :specification_version then
|
@@ -80,6 +83,7 @@ Gem::Specification.new do |s|
|
|
80
83
|
|
81
84
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
82
85
|
s.add_runtime_dependency(%q<gorillib>, ["~> 0.1.1"])
|
86
|
+
s.add_runtime_dependency(%q<activemodel>, ["~> 3.0.9"])
|
83
87
|
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
84
88
|
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
85
89
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
@@ -87,6 +91,7 @@ Gem::Specification.new do |s|
|
|
87
91
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
88
92
|
else
|
89
93
|
s.add_dependency(%q<gorillib>, ["~> 0.1.1"])
|
94
|
+
s.add_dependency(%q<activemodel>, ["~> 3.0.9"])
|
90
95
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
91
96
|
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
92
97
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
@@ -95,6 +100,7 @@ Gem::Specification.new do |s|
|
|
95
100
|
end
|
96
101
|
else
|
97
102
|
s.add_dependency(%q<gorillib>, ["~> 0.1.1"])
|
103
|
+
s.add_dependency(%q<activemodel>, ["~> 3.0.9"])
|
98
104
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
99
105
|
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
100
106
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
data/lib/icss.rb
CHANGED
@@ -10,9 +10,8 @@ require 'gorillib/metaprogramming/class_attribute'
|
|
10
10
|
|
11
11
|
require 'gorillib/hashlike'
|
12
12
|
require 'gorillib/receiver'
|
13
|
-
require 'gorillib/
|
14
|
-
|
15
|
-
require 'gorillib/receiver/validations'
|
13
|
+
require 'gorillib/receiver_model'
|
14
|
+
|
16
15
|
require 'time' # ain't that always the way
|
17
16
|
|
18
17
|
$: << File.dirname(__FILE__)
|
data/lib/icss/protocol.rb
CHANGED
@@ -55,11 +55,12 @@ module Icss
|
|
55
55
|
include Receiver
|
56
56
|
include Receiver::ActsAsHash
|
57
57
|
include Receiver::ActsAsLoadable
|
58
|
-
include
|
58
|
+
include Gorillib::Hashlike::TreeMerge
|
59
|
+
include Receiver::ActiveModelShim
|
59
60
|
|
60
61
|
rcvr_accessor :protocol, String, :required => true
|
61
62
|
alias_method :name, :protocol
|
62
|
-
rcvr_accessor :namespace, String
|
63
|
+
rcvr_accessor :namespace, String
|
63
64
|
rcvr_accessor :doc, String
|
64
65
|
#
|
65
66
|
rcvr_accessor :types, Array, :of => Icss::TypeFactory, :default => []
|
@@ -69,17 +70,21 @@ module Icss
|
|
69
70
|
rcvr_accessor :code_assets, Array, :of => Icss::CodeAsset, :default => []
|
70
71
|
rcvr_accessor :targets, Hash, :of => Icss::TargetListFactory, :default => {}, :merge_as => :hash_of_arrays
|
71
72
|
rcvr_accessor :under_consideration, Boolean
|
72
|
-
rcvr_accessor :update_frequency, String
|
73
|
+
rcvr_accessor :update_frequency, String
|
74
|
+
|
75
|
+
validates_presence_of :protocol, :namespace
|
76
|
+
validates_format_of :protocol, :with => /\A[A-Za-z_]\w*\z/, :message => "must start with [A-Za-z_] and contain only [A-Za-z0-9_].", :allow_blank => true
|
77
|
+
validates_format_of :namespace, :with => /\A([A-Za-z_]\w*\.?)+\z/, :message => "must be a dot-separated sequence of avro names (start with [A-Za-z_] and contain only [A-Za-z0-9_])", :allow_blank => true
|
78
|
+
validates_format_of :update_frequency, :with => /daily|weekly|monthly|quarterly|never/, :message => "must be one of daily, weekly, monthly, quarterly, never", :allow_blank => true
|
73
79
|
|
74
|
-
# attr_accessor :body
|
75
80
|
after_receive do |hsh|
|
76
81
|
# Set each message's protocol to self, and if the name wasn't given, set
|
77
82
|
# it using the message's hash key.
|
78
83
|
self.messages.each{|msg_name, msg| msg.protocol = self; msg.name ||= msg_name }
|
79
|
-
# Set
|
84
|
+
# Set each type's parent to self (for namespace resolution)
|
80
85
|
self.types.each{|type| type.parent = self }
|
81
|
-
|
82
|
-
|
86
|
+
# warn if invalid
|
87
|
+
warn errors.inspect unless valid?
|
83
88
|
end
|
84
89
|
|
85
90
|
# String: namespace.name
|
@@ -87,14 +92,11 @@ module Icss
|
|
87
92
|
[namespace, name].compact.join(".")
|
88
93
|
end
|
89
94
|
|
95
|
+
# a / separated version of the name, with no / at start
|
90
96
|
def path
|
91
97
|
fullname.gsub('.', '/')
|
92
98
|
end
|
93
99
|
|
94
|
-
def tree_merge! arg
|
95
|
-
to_hash.tree_merge!(arg)
|
96
|
-
end
|
97
|
-
|
98
100
|
def find_message nm
|
99
101
|
return if messages.blank?
|
100
102
|
nm = nm.to_s.gsub("/", ".").split(".").last
|
@@ -107,11 +109,13 @@ module Icss
|
|
107
109
|
self.namespace = namespace_and_name.join('.')
|
108
110
|
end
|
109
111
|
|
110
|
-
def receive_targets
|
111
|
-
|
112
|
-
|
113
|
-
|
112
|
+
def receive_targets tgts
|
113
|
+
return unless tgts.present?
|
114
|
+
self.targets ||= {}
|
115
|
+
tgts.each do |target_name, target_info_list|
|
116
|
+
targets[target_name] = TargetListFactory.receive(target_info_list, target_name) # array of targets
|
114
117
|
end
|
118
|
+
targets
|
115
119
|
end
|
116
120
|
|
117
121
|
def to_hash()
|
data/spec/protocol_spec.rb
CHANGED
@@ -1,10 +1,116 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
require 'icss'
|
3
3
|
|
4
|
-
|
5
4
|
describe Icss::Protocol do
|
6
|
-
|
7
|
-
|
5
|
+
let(:simple_icss) do
|
6
|
+
Icss::Protocol.receive_from_file(ICSS_ROOT_DIR('examples/chronic.icss.yaml'))
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'loads cleanly' do
|
10
|
+
simple_icss.name.should == 'chronic'
|
11
|
+
simple_icss.fullname.should == 'util.time.chronic'
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#fullname' do
|
15
|
+
it 'has namespace and name' do
|
16
|
+
simple_icss.fullname.should == 'util.time.chronic'
|
17
|
+
simple_icss.namespace = nil
|
18
|
+
simple_icss.fullname.should == 'chronic'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
describe '#path' do
|
22
|
+
it 'is a / separated version of the name, with no / at start' do
|
23
|
+
simple_icss.path.should == 'util/time/chronic'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
describe '#doc' do
|
27
|
+
it 'takes a doc string' do
|
28
|
+
simple_icss.doc.should == 'A series of calls hooking into the Chronic ruby gem'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'types' do
|
33
|
+
it 'has an array of types' do
|
34
|
+
simple_icss.types.map(&:name).should == ['chronic_parse_params', 'chronic_parse_response']
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'messages' do
|
39
|
+
it 'has a hash of messages' do
|
40
|
+
simple_icss.messages.keys.should == ['parse']
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'named each message for its key' do
|
44
|
+
simple_icss.messages['parse'].name.should == 'parse'
|
45
|
+
simple_icss.receive!({ :messages => { 'foo' => { :request => [] } }})
|
46
|
+
simple_icss.messages['foo'].name.should == 'foo'
|
47
|
+
end
|
48
|
+
|
49
|
+
it '#find_message' do
|
50
|
+
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'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'targets' do
|
60
|
+
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'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# describe 'tree_merge!' do
|
68
|
+
# it 'merges recursively'
|
69
|
+
# end
|
70
|
+
|
71
|
+
describe 'validations' do
|
72
|
+
it 'validates protocol name' do
|
73
|
+
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_]."]
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'validates namespace' do
|
79
|
+
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/
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#to_hash' do
|
86
|
+
it 'roundtrips' do
|
87
|
+
hsh = simple_icss.to_hash
|
88
|
+
hsh.should == {
|
89
|
+
:namespace=>"util.time", :protocol=>"chronic",
|
90
|
+
:doc=>"A series of calls hooking into the Chronic ruby gem",
|
91
|
+
:types => [
|
92
|
+
{:name=>"chronic_parse_params", :doc=>"Query API parameters for the /util/time/chronic/parse call", :type=>:record,
|
93
|
+
: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."}
|
98
|
+
]},
|
99
|
+
{:name=>"chronic_parse_response", :doc=>"Query API response for the /util/time/chronic/parse call", :type=>:record,
|
100
|
+
: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."}
|
103
|
+
]}
|
104
|
+
],
|
105
|
+
: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"}]},
|
107
|
+
},
|
108
|
+
:data_assets=>[],
|
109
|
+
: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"]}]},
|
111
|
+
}
|
112
|
+
end
|
8
113
|
end
|
9
114
|
|
10
115
|
end
|
116
|
+
|
@@ -0,0 +1,171 @@
|
|
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::Protocol validations" do
|
81
|
+
before :each do
|
82
|
+
@template = YAML.load(template_icss)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should be able to receive a correctly formatted template Icss" do
|
86
|
+
lambda { @icss =Icss::Protocol.receive @template }.should_not raise_error
|
87
|
+
@icss.errors.should be_empty
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should contain only the keys that were included in the Icss file" do
|
91
|
+
@icss = Icss::Protocol.receive @template
|
92
|
+
@icss.keys.map { |k| k.to_s }.should == @template.keys
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should generate an error when the namespace if formatted incorrectly" do
|
96
|
+
@template['namespace'] = '$bad_namespace'
|
97
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:namespace]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should generate an error when the protocol if formatted incorrectly" do
|
101
|
+
@template['protocol'] = '$bad_protocol'
|
102
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:protocol]
|
103
|
+
end
|
104
|
+
|
105
|
+
context "Catalog Target" do
|
106
|
+
|
107
|
+
it "should generate an error when an undefined data_asset is specified" do
|
108
|
+
@template['targets']['catalog'].first['packages'].first['data_assets'] = ['fake_data_asset']
|
109
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:catalog]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should generate an error when an undefined message name is specified" do
|
113
|
+
@template['targets']['catalog'].first['messages'] = ['fake_message']
|
114
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:catalog]
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
context "Data Assets" do
|
120
|
+
|
121
|
+
it "should generate an error when an asset's type is undefined" do
|
122
|
+
@template['data_assets'].first['type'] = 'fake_data_asset'
|
123
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:data_assets]
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
context "Messages" do
|
129
|
+
|
130
|
+
it "should generate an error when a message's request type is undefined" do
|
131
|
+
@template['messages']['search']['request'].first['type'] = 'fake_request_type'
|
132
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:messages]
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should generate an error when a message's response type is undefined" do
|
136
|
+
@template['messages']['search']['response'] = 'fake_response_type'
|
137
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:messages]
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should generate an error when a message's sample request types do not match the request record" do
|
141
|
+
@template['messages']['search']['samples'].first['request'] = [{ 'foo' => 'bar' }]
|
142
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:messages]
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
context "Types" do
|
148
|
+
|
149
|
+
it "should generate an error when an bad type definition is given for a specific type" do
|
150
|
+
@template['types'].push({
|
151
|
+
'name' => 'fake_type_record',
|
152
|
+
'type' => 'fake'
|
153
|
+
})
|
154
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:types]
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should generate an error when an undefined type definition is given for a specific field" do
|
158
|
+
@template['types'].push({
|
159
|
+
'name' => 'fake_type_record',
|
160
|
+
'type' => 'record',
|
161
|
+
'fields' => [{
|
162
|
+
'name' => 'fake_field',
|
163
|
+
'type' => 'fake_type'
|
164
|
+
}]
|
165
|
+
})
|
166
|
+
Icss::Protocol.receive(@template).errors.keys.should == [:types]
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Philip (flip) Kromer for Infochimps
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-15 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -36,6 +36,22 @@ dependencies:
|
|
36
36
|
version_requirements: *id001
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 21
|
44
|
+
segments:
|
45
|
+
- 3
|
46
|
+
- 0
|
47
|
+
- 9
|
48
|
+
version: 3.0.9
|
49
|
+
type: :runtime
|
50
|
+
name: activemodel
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
55
|
none: false
|
40
56
|
requirements:
|
41
57
|
- - ~>
|
@@ -49,9 +65,9 @@ dependencies:
|
|
49
65
|
type: :development
|
50
66
|
name: rspec
|
51
67
|
prerelease: false
|
52
|
-
version_requirements: *
|
68
|
+
version_requirements: *id003
|
53
69
|
- !ruby/object:Gem::Dependency
|
54
|
-
requirement: &
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
55
71
|
none: false
|
56
72
|
requirements:
|
57
73
|
- - ~>
|
@@ -65,9 +81,9 @@ dependencies:
|
|
65
81
|
type: :development
|
66
82
|
name: yard
|
67
83
|
prerelease: false
|
68
|
-
version_requirements: *
|
84
|
+
version_requirements: *id004
|
69
85
|
- !ruby/object:Gem::Dependency
|
70
|
-
requirement: &
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
71
87
|
none: false
|
72
88
|
requirements:
|
73
89
|
- - ~>
|
@@ -81,9 +97,9 @@ dependencies:
|
|
81
97
|
type: :development
|
82
98
|
name: bundler
|
83
99
|
prerelease: false
|
84
|
-
version_requirements: *
|
100
|
+
version_requirements: *id005
|
85
101
|
- !ruby/object:Gem::Dependency
|
86
|
-
requirement: &
|
102
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
87
103
|
none: false
|
88
104
|
requirements:
|
89
105
|
- - ~>
|
@@ -97,9 +113,9 @@ dependencies:
|
|
97
113
|
type: :development
|
98
114
|
name: jeweler
|
99
115
|
prerelease: false
|
100
|
-
version_requirements: *
|
116
|
+
version_requirements: *id006
|
101
117
|
- !ruby/object:Gem::Dependency
|
102
|
-
requirement: &
|
118
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
103
119
|
none: false
|
104
120
|
requirements:
|
105
121
|
- - ">="
|
@@ -111,7 +127,7 @@ dependencies:
|
|
111
127
|
type: :development
|
112
128
|
name: rcov
|
113
129
|
prerelease: false
|
114
|
-
version_requirements: *
|
130
|
+
version_requirements: *id007
|
115
131
|
description: "Infochimps Stupid Schema library: an avro-compatible data description standard. ICSS completely describes a collection of data (and associated assets) in a way that is expressive, scalable and sufficient to drive remarkably complex downstream processes."
|
116
132
|
email: coders@infochimps.com
|
117
133
|
executables: []
|
@@ -131,6 +147,7 @@ files:
|
|
131
147
|
- LICENSE.textile
|
132
148
|
- README.textile
|
133
149
|
- Rakefile
|
150
|
+
- TODO.md
|
134
151
|
- VERSION
|
135
152
|
- examples/avro_examples/BulkData.avpr
|
136
153
|
- examples/avro_examples/complicated.icss.yaml
|
@@ -167,6 +184,7 @@ files:
|
|
167
184
|
- spec/icss_spec.rb
|
168
185
|
- spec/protocol_spec.rb
|
169
186
|
- spec/spec_helper.rb
|
187
|
+
- spec/validations_spec.rb
|
170
188
|
has_rdoc: true
|
171
189
|
homepage: http://github.com/mrflip/icss
|
172
190
|
licenses:
|
@@ -205,3 +223,4 @@ test_files:
|
|
205
223
|
- spec/icss_spec.rb
|
206
224
|
- spec/protocol_spec.rb
|
207
225
|
- spec/spec_helper.rb
|
226
|
+
- spec/validations_spec.rb
|