pebbles-uid 0.0.3 → 0.0.4
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/README.md +81 -65
- data/lib/pebbles-uid.rb +2 -2
- data/lib/pebbles-uid/labels.rb +24 -3
- data/lib/pebbles-uid/query.rb +43 -6
- data/lib/pebbles-uid/version.rb +1 -1
- data/spec/labels_spec.rb +9 -0
- data/spec/query_spec.rb +28 -2
- data/spec/uid_spec.rb +1 -1
- metadata +4 -4
data/README.md
CHANGED
|
@@ -15,7 +15,7 @@ The first label uniquely identifies which pebble the resource originated from.
|
|
|
15
15
|
Any secondary labels are grouped into a `species`, which identify sub-types within a given pebble.
|
|
16
16
|
|
|
17
17
|
```
|
|
18
|
-
|
|
18
|
+
post.doc
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Here the genus is `post`, and the species is `doc`.
|
|
@@ -26,10 +26,10 @@ The path is a dot-delimited set of labels. The first label represents the realm,
|
|
|
26
26
|
|
|
27
27
|
A single resource may have multiple paths (and therefore multiple uids). For example:
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
```
|
|
30
|
+
post.card:tourism.norway.fjords$42
|
|
31
|
+
post.card:tourism.norway.west-coast$42
|
|
32
|
+
```
|
|
33
33
|
|
|
34
34
|
### Oid
|
|
35
35
|
|
|
@@ -51,9 +51,9 @@ Across the pebblestack universe, you can query for a specific resource by passin
|
|
|
51
51
|
|
|
52
52
|
In addition, the wildcard query `genus:realm.*$oid` will identify a single resource, e.g.:
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
```
|
|
55
|
+
post.card:tourism.*$42
|
|
56
|
+
```
|
|
57
57
|
|
|
58
58
|
If a specific resource is targeted (i.e. genus and oid are both unambiguous), then realm is required.
|
|
59
59
|
|
|
@@ -63,33 +63,33 @@ If a specific resource is targeted (i.e. genus and oid are both unambiguous), th
|
|
|
63
63
|
|
|
64
64
|
The most permissive query consists of any genus in any path, with any oid (implied):
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
```
|
|
67
|
+
*:*
|
|
68
|
+
```
|
|
69
69
|
|
|
70
70
|
This is the equivalent to:
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
```
|
|
73
|
+
*:*$*
|
|
74
|
+
```
|
|
75
75
|
|
|
76
76
|
Queries may not be made across multiple realms at one time. If realm is not specified in the path, then it is assumed that the application verifies realm if necessary.
|
|
77
77
|
|
|
78
78
|
In the context of a genus or a path, you may specify any number of labels and terminate with an asterisk, which means: zero or more labels follow. E.g.:
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
```
|
|
81
|
+
post.*:tourism.europe.*
|
|
82
|
+
```
|
|
83
83
|
|
|
84
84
|
NOTE: wildcard queries on species is not yet supported.
|
|
85
85
|
|
|
86
86
|
This will return things like:
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
```
|
|
89
|
+
post:tourism.europe$123
|
|
90
|
+
post:tourism.europe.france.sightseeing$234
|
|
91
|
+
post.card:tourism.europe.mountains$345
|
|
92
|
+
```
|
|
93
93
|
|
|
94
94
|
Asterisks may not occur in mid-sequence. In other words, `post:tourism.*.food` will not be accepted.
|
|
95
95
|
|
|
@@ -101,39 +101,39 @@ A pipe signifies _or_.
|
|
|
101
101
|
|
|
102
102
|
This can be used in genus at any position:
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
```
|
|
105
|
+
unit|group:*
|
|
106
|
+
```
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
```
|
|
109
|
+
post.doc|card:*
|
|
110
|
+
```
|
|
111
111
|
|
|
112
112
|
In a path, this can be used in any position except the first, as the realm must be unambiguous.
|
|
113
113
|
|
|
114
114
|
Thus:
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
```
|
|
117
|
+
post:realm.label1|label2.something
|
|
118
|
+
```
|
|
119
119
|
|
|
120
120
|
The following is not allowed:
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
```
|
|
123
|
+
post:realm1|realm2.*
|
|
124
|
+
```
|
|
125
125
|
|
|
126
126
|
If you wish to fetch a specific list of objects, you may use the pipe to delimit oids:
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
```
|
|
129
|
+
post:realm.*$a|b|c|d|e|f|g
|
|
130
|
+
```
|
|
131
131
|
|
|
132
132
|
This is equivalent to the NOW deprecated comma-delimited uid query:
|
|
133
133
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
```
|
|
135
|
+
post:realm.*$a,post:realm.*$b,post:realm.*$c,post:realm.*$d,post:realm.*$e,post:realm.*$f,post:realm.*$g,
|
|
136
|
+
```
|
|
137
137
|
|
|
138
138
|
NOTE: realm is required in this case, because each term in the list must refer to a single resource.
|
|
139
139
|
|
|
@@ -141,19 +141,18 @@ NOTE: realm is required in this case, because each term in the list must refer t
|
|
|
141
141
|
|
|
142
142
|
In both genus and paths, a caret indicates ancestry up to the specified point:
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
```
|
|
145
|
+
post:realm.europe.^norway.fjords.food
|
|
146
|
+
```
|
|
147
147
|
|
|
148
148
|
This represents everything at the following locations:
|
|
149
149
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
```
|
|
151
|
+
post:realm.europe
|
|
152
|
+
post:realm.europe.norway
|
|
153
|
+
post:realm.europe.norway.fjords
|
|
154
|
+
post:realm.europe.norway.fjords.food
|
|
155
|
+
```
|
|
157
156
|
|
|
158
157
|
## Installation
|
|
159
158
|
|
|
@@ -173,28 +172,45 @@ Or install it yourself as:
|
|
|
173
172
|
|
|
174
173
|
### Identifying an existing resource
|
|
175
174
|
|
|
176
|
-
|
|
175
|
+
```
|
|
176
|
+
uid = Pebbles::Uid.new('post.card:tourism.norway.fjords$1234')
|
|
177
|
+
|
|
178
|
+
uid.realm
|
|
179
|
+
=> "tourism"
|
|
180
|
+
|
|
181
|
+
uid.genus
|
|
182
|
+
=> "post.card"
|
|
183
|
+
|
|
184
|
+
uid.species
|
|
185
|
+
=> "card"
|
|
186
|
+
|
|
187
|
+
uid.path
|
|
188
|
+
=> "tourism.norway.fjords"
|
|
177
189
|
|
|
178
|
-
|
|
179
|
-
|
|
190
|
+
uid.oid
|
|
191
|
+
=> 1234
|
|
180
192
|
|
|
181
|
-
|
|
182
|
-
|
|
193
|
+
uid.to_s
|
|
194
|
+
=> 'post.card:tourism.norway.fjords$1234'
|
|
183
195
|
|
|
184
|
-
|
|
185
|
-
|
|
196
|
+
uid.to_hash
|
|
197
|
+
=> {'genus_0' => 'post', 'genus_1' => 'card', 'path_0' => 'tourism', 'path_1' => 'norway', 'path_2' => 'fjords', 'oid' => '1234'}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Uid Queries
|
|
186
201
|
|
|
187
|
-
|
|
188
|
-
|
|
202
|
+
```
|
|
203
|
+
query = Pebbles::Uid::Query.new('post.card:tourism.^norway.fjords|mountains.*')
|
|
189
204
|
|
|
190
|
-
|
|
191
|
-
|
|
205
|
+
query.list?
|
|
206
|
+
=> false
|
|
192
207
|
|
|
193
|
-
|
|
194
|
-
|
|
208
|
+
query.collection?
|
|
209
|
+
=> true
|
|
195
210
|
|
|
196
|
-
|
|
197
|
-
|
|
211
|
+
query.to_hash
|
|
212
|
+
=> {'genus_0' => 'post', 'genus_1' => 'card', 'path_0' => 'tourism', 'path_1' => ['norway', nil], ['fjords', 'mountains', nil]}
|
|
213
|
+
```
|
|
198
214
|
|
|
199
215
|
## TODO
|
|
200
216
|
|
data/lib/pebbles-uid.rb
CHANGED
data/lib/pebbles-uid/labels.rb
CHANGED
|
@@ -2,12 +2,16 @@ module Pebbles
|
|
|
2
2
|
class Uid
|
|
3
3
|
class Labels
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
NO_MARKER = Class.new
|
|
6
|
+
|
|
7
|
+
attr_reader :values, :name, :suffix, :stop
|
|
6
8
|
def initialize(*values)
|
|
7
9
|
options = values.pop if values.last.is_a?(Hash)
|
|
8
10
|
options ||= {}
|
|
9
11
|
@values = values.flatten.compact.map {|v| v.split('.') }.flatten
|
|
10
12
|
@name = options[:name]
|
|
13
|
+
@suffix = options[:suffix]
|
|
14
|
+
@stop = options.fetch(:stop) { NO_MARKER }
|
|
11
15
|
end
|
|
12
16
|
|
|
13
17
|
def first
|
|
@@ -47,8 +51,25 @@ module Pebbles
|
|
|
47
51
|
!!(value =~ /[\*\|\^]/)
|
|
48
52
|
end
|
|
49
53
|
|
|
50
|
-
def to_hash
|
|
51
|
-
|
|
54
|
+
def to_hash
|
|
55
|
+
conditions.to_hash
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def next_label
|
|
59
|
+
conditions.next
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def conditions
|
|
63
|
+
unless @conditions
|
|
64
|
+
options = {:name => name, :suffix => suffix}
|
|
65
|
+
options.merge!(:stop => stop) if use_stop_marker?
|
|
66
|
+
@conditions = Conditions.new(values, options)
|
|
67
|
+
end
|
|
68
|
+
@conditions
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def use_stop_marker?
|
|
72
|
+
stop != NO_MARKER
|
|
52
73
|
end
|
|
53
74
|
|
|
54
75
|
end
|
data/lib/pebbles-uid/query.rb
CHANGED
|
@@ -2,16 +2,26 @@ module Pebbles
|
|
|
2
2
|
class Uid
|
|
3
3
|
class Query
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
NO_MARKER = Class.new
|
|
6
|
+
|
|
7
|
+
attr_reader :term, :terms, :genus, :path, :oid,
|
|
8
|
+
:genus_name, :path_name, :suffix, :stop
|
|
9
|
+
def initialize(term, options = {})
|
|
7
10
|
@term = term
|
|
11
|
+
@genus_name = options.fetch(:genus) { 'genus' }
|
|
12
|
+
@path_name = options.fetch(:path) { 'path' }
|
|
13
|
+
@suffix = options[:suffix]
|
|
14
|
+
@stop = options.fetch(:stop) { NO_MARKER }
|
|
8
15
|
|
|
9
16
|
if wildcard_query?
|
|
10
17
|
@terms = [term]
|
|
11
|
-
@genus, @path, @oid = Pebbles::Uid.parse(term)
|
|
12
18
|
else
|
|
13
19
|
@terms = extract_terms
|
|
14
20
|
end
|
|
21
|
+
|
|
22
|
+
if !list?
|
|
23
|
+
@genus, @path, @oid = Pebbles::Uid.parse(term)
|
|
24
|
+
end
|
|
15
25
|
end
|
|
16
26
|
|
|
17
27
|
def for_one?
|
|
@@ -22,6 +32,13 @@ module Pebbles
|
|
|
22
32
|
terms.size != 1
|
|
23
33
|
end
|
|
24
34
|
|
|
35
|
+
def list
|
|
36
|
+
if !list?
|
|
37
|
+
raise "Cannot expand non-list query"
|
|
38
|
+
end
|
|
39
|
+
terms
|
|
40
|
+
end
|
|
41
|
+
|
|
25
42
|
def collection?
|
|
26
43
|
wildcard_query?
|
|
27
44
|
end
|
|
@@ -56,18 +73,35 @@ module Pebbles
|
|
|
56
73
|
end
|
|
57
74
|
|
|
58
75
|
hash = genus_wrapper.to_hash.merge(path_wrapper.to_hash)
|
|
59
|
-
|
|
76
|
+
if oid?
|
|
77
|
+
oid_key = ['oid', suffix].compact.join('_').to_sym
|
|
78
|
+
hash = hash.merge(oid_key => oid)
|
|
79
|
+
end
|
|
60
80
|
hash
|
|
61
81
|
end
|
|
62
82
|
|
|
83
|
+
def next_path_label
|
|
84
|
+
path_wrapper.next_label
|
|
85
|
+
end
|
|
86
|
+
|
|
63
87
|
private
|
|
64
88
|
|
|
65
89
|
def genus_wrapper
|
|
66
|
-
@genus_wrapper
|
|
90
|
+
unless @genus_wrapper
|
|
91
|
+
options = {:name => genus_name, :suffix => suffix}
|
|
92
|
+
options.merge!(:stop => stop) if use_stop_marker?
|
|
93
|
+
@genus_wrapper = Labels.new(genus, options)
|
|
94
|
+
end
|
|
95
|
+
@genus_wrapper
|
|
67
96
|
end
|
|
68
97
|
|
|
69
98
|
def path_wrapper
|
|
70
|
-
@path_wrapper
|
|
99
|
+
unless @path_wrapper
|
|
100
|
+
options = {:name => path_name, :suffix => suffix}
|
|
101
|
+
options.merge!(:stop => stop) if use_stop_marker?
|
|
102
|
+
@path_wrapper = Labels.new(path, options)
|
|
103
|
+
end
|
|
104
|
+
@path_wrapper
|
|
71
105
|
end
|
|
72
106
|
|
|
73
107
|
def wildcard_query?
|
|
@@ -102,6 +136,9 @@ module Pebbles
|
|
|
102
136
|
end.flatten
|
|
103
137
|
end
|
|
104
138
|
|
|
139
|
+
def use_stop_marker?
|
|
140
|
+
stop != NO_MARKER
|
|
141
|
+
end
|
|
105
142
|
end
|
|
106
143
|
end
|
|
107
144
|
end
|
data/lib/pebbles-uid/version.rb
CHANGED
data/spec/labels_spec.rb
CHANGED
|
@@ -13,6 +13,15 @@ describe Pebbles::Uid::Labels do
|
|
|
13
13
|
subject.size.should eq(3)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
it "knows the next label" do
|
|
17
|
+
subject.next_label.should eq(:thing_3)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "can use a suffix on the hash" do
|
|
21
|
+
uid = Pebbles::Uid::Labels.new('a.b.c', :name => 'whatevs', :suffix => 'hey')
|
|
22
|
+
uid.to_hash.should eq(:whatevs_0_hey => 'a', :whatevs_1_hey => 'b', :whatevs_2_hey => 'c')
|
|
23
|
+
end
|
|
24
|
+
|
|
16
25
|
describe "alternate constructors" do
|
|
17
26
|
it { Pebbles::Uid::Labels.new('a', 'b', 'c').to_s.should eq('a.b.c') }
|
|
18
27
|
it { Pebbles::Uid::Labels.new(['a', 'b', 'c']).to_s.should eq('a.b.c') }
|
data/spec/query_spec.rb
CHANGED
|
@@ -9,7 +9,7 @@ describe Pebbles::Uid::Query do
|
|
|
9
9
|
|
|
10
10
|
context "for a single resource" do
|
|
11
11
|
let(:term) { "post:area51$abc" }
|
|
12
|
-
subject { Pebbles::Uid::Query.new(term) }
|
|
12
|
+
subject { Pebbles::Uid::Query.new(term, :suffix => '') }
|
|
13
13
|
|
|
14
14
|
its(:term) { should == term }
|
|
15
15
|
|
|
@@ -17,6 +17,7 @@ describe Pebbles::Uid::Query do
|
|
|
17
17
|
its(:list?) { should == false }
|
|
18
18
|
its(:collection?) { should == false }
|
|
19
19
|
its(:cache_keys) { should eq(['post:area51.*$abc']) }
|
|
20
|
+
its(:to_hash) { should eq(:genus_0_ => 'post', :path_0_ => 'area51', :oid_ => 'abc') }
|
|
20
21
|
|
|
21
22
|
it "handles a wildcard path if realm is given" do
|
|
22
23
|
query = Pebbles::Uid::Query.new('post:area51.*$abc')
|
|
@@ -32,6 +33,10 @@ describe Pebbles::Uid::Query do
|
|
|
32
33
|
->{ Pebbles::Uid::Query.new('post:*$abc') }.should raise_error(ArgumentError)
|
|
33
34
|
->{ Pebbles::Uid::Query.new('post:$abc') }.should raise_error(ArgumentError)
|
|
34
35
|
end
|
|
36
|
+
|
|
37
|
+
it "doesn't have a list of uids" do
|
|
38
|
+
->{ subject.list }.should raise_error StandardError
|
|
39
|
+
end
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
context "for a list of resources" do
|
|
@@ -47,7 +52,7 @@ describe Pebbles::Uid::Query do
|
|
|
47
52
|
context "by oid" do
|
|
48
53
|
subject { Pebbles::Uid::Query.new("post:area51$abc|xyz") }
|
|
49
54
|
|
|
50
|
-
its(:
|
|
55
|
+
its(:list) { should eq(['post:area51$abc', 'post:area51$xyz']) }
|
|
51
56
|
|
|
52
57
|
it "can't do hashes under these circumstances" do
|
|
53
58
|
->{ subject.to_hash }.should raise_error(RuntimeError)
|
|
@@ -101,6 +106,10 @@ describe Pebbles::Uid::Query do
|
|
|
101
106
|
its(:oid?) { should == false }
|
|
102
107
|
|
|
103
108
|
its(:to_hash) { should == {} }
|
|
109
|
+
|
|
110
|
+
it "doesn't have a list of uids" do
|
|
111
|
+
->{ subject.list }.should raise_error StandardError
|
|
112
|
+
end
|
|
104
113
|
end
|
|
105
114
|
|
|
106
115
|
context "everything, with any oid" do
|
|
@@ -140,6 +149,23 @@ describe Pebbles::Uid::Query do
|
|
|
140
149
|
its(:to_hash) { should == {:oid => 'yak'} }
|
|
141
150
|
end
|
|
142
151
|
|
|
152
|
+
context "a typical search" do
|
|
153
|
+
subject { Pebbles::Uid::Query.new('beast:myths.*', :genus => 'klass', :path => 'label', :suffix => '') }
|
|
154
|
+
its(:to_hash) { should == {:klass_0_ => 'beast', :label_0_ => 'myths'} }
|
|
155
|
+
its(:next_path_label) { should == :label_1_ }
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context "with a wildcard path" do
|
|
159
|
+
subject { Pebbles::Uid::Query.new('beast:myths.scary') }
|
|
160
|
+
its(:for_one?) { should == false }
|
|
161
|
+
its(:collection?) { should == true }
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context "a search with stops" do
|
|
165
|
+
subject { Pebbles::Uid::Query.new('beast:myths$*', :genus => 'klass', :path => 'label', :suffix => '', :stop => nil) }
|
|
166
|
+
its(:to_hash) { should == {:klass_0_ => 'beast', :klass_1_ => nil, :label_0_ => 'myths', :label_1_ => nil} }
|
|
167
|
+
its(:next_path_label) { should == :label_1_ }
|
|
168
|
+
end
|
|
143
169
|
end
|
|
144
170
|
|
|
145
171
|
end
|
data/spec/uid_spec.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pebbles-uid
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-10-
|
|
12
|
+
date: 2012-10-15 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rspec
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70099323387380 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ! '>='
|
|
@@ -21,7 +21,7 @@ dependencies:
|
|
|
21
21
|
version: '0'
|
|
22
22
|
type: :development
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *70099323387380
|
|
25
25
|
description: Handle pebble UIDs conveniently.
|
|
26
26
|
email:
|
|
27
27
|
- katrina.owen@gmail.com
|