uri_template 0.5.3 → 0.6.0
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/CHANGELOG.md +57 -29
- data/README.md +3 -1
- data/lib/uri_template.rb +35 -17
- data/lib/uri_template/literal.rb +5 -1
- data/lib/uri_template/rfc6570.rb +45 -30
- data/lib/uri_template/rfc6570/expression.rb +23 -10
- data/lib/uri_template/token.rb +6 -1
- data/uri_template.gemspec +1 -1
- metadata +15 -16
data/CHANGELOG.md
CHANGED
@@ -1,56 +1,84 @@
|
|
1
|
+
# 0.6.0 - TBD
|
2
|
+
|
3
|
+
* [FEATURE] partial expansion
|
4
|
+
* [FEATURE] You can now pass variables as an Array to URITemplate#expand ( thanks to @bmaland )
|
5
|
+
Example:
|
6
|
+
|
7
|
+
tpl = URITemplate.new("/{var}/")
|
8
|
+
tpl.expand(["value"]) # => '/value/'
|
9
|
+
|
10
|
+
* [BUGFIX] Expanding arrays/hashes with a length limit now actually works
|
11
|
+
|
12
|
+
# 0.5.2 - 24.02.2013
|
13
|
+
|
14
|
+
* [ENHANCEMENT] The colon based uri templates now allow more characters in variable names.
|
15
|
+
|
1
16
|
# 0.5.1 - 23.09.2012
|
2
|
-
|
17
|
+
|
18
|
+
* [BUGFIX] f*** bug.
|
3
19
|
|
4
20
|
# 0.5.0 - 23.09.2012
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
21
|
+
|
22
|
+
* [ENHANCEMENT] Removed draft7
|
23
|
+
* [ENHANCEMENT] splitted absoulte? method into host? and scheme?
|
24
|
+
* [ENHANCEMENT] the URITemplate interface is now much stronger
|
25
|
+
* [ENHANCEMENT] code quality _significantly_ improved
|
26
|
+
* [ENHANCEMENT] concat method
|
10
27
|
|
11
28
|
# 0.4.0 - 06.07.2012
|
12
|
-
|
13
|
-
|
14
|
-
|
29
|
+
|
30
|
+
* [ENHANCEMENT] expand now accepts symbols as keys ( thanks to @peterhellber )
|
31
|
+
* [ENHANCEMENT] expand now accepts arrays of pairs ( thanks to @peterhellber )
|
32
|
+
* [BUGFIX] fixed some testing bugs
|
15
33
|
|
16
34
|
# 0.3.0 - 24.05.2012
|
17
|
-
|
18
|
-
|
19
|
-
|
35
|
+
|
36
|
+
* [ENHANCEMENT] Implemented the final version. Default implementation is now RFC 6570
|
37
|
+
* [BUGFIX] variables with terminal dots were allowed
|
38
|
+
* [BUGFIX] lists of commas were parsed incorrectly
|
20
39
|
|
21
40
|
# 0.2.1 - 30.12.2011
|
22
|
-
|
41
|
+
|
42
|
+
* [ENHANCEMENT] Works now with MRI 1.8.7 and REE
|
23
43
|
|
24
44
|
# 0.2.0 - 03.12.2011
|
25
|
-
|
26
|
-
|
45
|
+
|
46
|
+
* [ENHANCEMENT] Reworked the escaping mechanism
|
47
|
+
* [ENHANCEMENT] escape_utils can now be used to boost escape/unescape performance
|
27
48
|
|
28
49
|
# 0.1.4 - 19.11.2011
|
29
|
-
|
30
|
-
|
50
|
+
|
51
|
+
* [ENHANCEMENT] Compatiblity: Works now with MRI 1.9.3, Rubinius and JRuby
|
52
|
+
* [ENHANCEMENT] Various (significant!) performance improvements
|
31
53
|
|
32
54
|
# 0.1.3 - 15.11.2011
|
33
|
-
|
34
|
-
|
55
|
+
|
56
|
+
* [BUGFIX] Draft7./ now concatenates literals correctly
|
57
|
+
* [BUGFIX] Draft7.tokens is now public
|
35
58
|
|
36
59
|
# 0.1.2 - 10.11.2011
|
37
|
-
|
60
|
+
|
61
|
+
* [FEATURE] added a new template-type: Colon
|
38
62
|
this should allow (some day) to rails-like routing tables
|
39
|
-
|
63
|
+
* [ENHANCEMENT] made the tokens-method mandatory and added two interfaces for tokens.
|
40
64
|
this allows cross-type features like variable anaylisis
|
41
65
|
|
42
66
|
# 0.1.1 - 4.11.2011
|
43
|
-
|
67
|
+
|
68
|
+
* [ENHANCEMENT] added a bunch of useful helper methods
|
44
69
|
|
45
70
|
# 0.1.0 - 2.11.2011
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
71
|
+
|
72
|
+
* [ENHANCEMENT] Removed Sections. They made too many headaches.
|
73
|
+
* [ENHANCEMENT] Made draft7 template concatenateable. This should replace sections.
|
74
|
+
* [BUGFIX] multiline uris were matched
|
75
|
+
* [BUGFIX] variablenames were decoded when this was not appreciated
|
50
76
|
|
51
77
|
# 0.0.2 - 1.11.2011
|
52
|
-
|
53
|
-
|
78
|
+
|
79
|
+
* [BUGFIX] Concatenating empty sections no more leads to catch-all templates, when an emtpy template was appreciated.
|
80
|
+
* [ENHANCEMENT] The extracted variables now contains the keys :suffix and :prefix if the match didn't consume the whole uri.
|
54
81
|
|
55
82
|
# 0.0.1 - 30.10.2011
|
56
|
-
|
83
|
+
|
84
|
+
* [FEATURE] Initial version
|
data/README.md
CHANGED
data/lib/uri_template.rb
CHANGED
@@ -192,33 +192,51 @@ RUBY
|
|
192
192
|
# The keys in the variables hash are converted to
|
193
193
|
# strings in order to support the Ruby 1.9 hash syntax.
|
194
194
|
#
|
195
|
+
# If the variables are given as an array, they will be matched against the variables in the template based on their order.
|
196
|
+
#
|
195
197
|
# @raise {Unconvertable} if a variable could not be converted to a string.
|
196
198
|
# @raise {InvalidValue} if a value is not suiteable for a certain variable ( e.g. a string when a list is expected ).
|
197
199
|
#
|
198
|
-
# @param variables [#map]
|
200
|
+
# @param variables [#map, Array]
|
199
201
|
# @return String
|
200
202
|
def expand(variables = {})
|
201
|
-
|
202
|
-
|
203
|
-
if variables.kind_of? Array
|
204
|
-
warn <<WARN
|
205
|
-
Passing variables as an Array to URITemplate#expand will have a different semantic in the next version of uri_template.
|
206
|
-
Please convert your variables into a Hash or use some ducktyping.
|
207
|
-
WARN
|
208
|
-
end
|
209
|
-
|
210
|
-
# Stringify variables
|
211
|
-
arg = variables.map{ |k, v| [k.to_s, v] }
|
212
|
-
if arg.any?{|elem| !elem.kind_of?(Array) }
|
213
|
-
raise ArgumentError, "Expected the output of variables.map to return an array of arrays but got #{arg.inspect}"
|
214
|
-
end
|
215
|
-
variables = Hash[arg]
|
216
|
-
|
203
|
+
variables = normalize_variables(variables)
|
217
204
|
tokens.map{|part|
|
218
205
|
part.expand(variables)
|
219
206
|
}.join
|
220
207
|
end
|
221
208
|
|
209
|
+
# Works like #expand with two differences:
|
210
|
+
#
|
211
|
+
# - the result is a uri template instead of string
|
212
|
+
# - undefined variables are left in the template
|
213
|
+
#
|
214
|
+
# @see {#expand}
|
215
|
+
# @param variables [#map, Array]
|
216
|
+
# @return [URITemplate]
|
217
|
+
def expand_partial(variables = {})
|
218
|
+
variables = normalize_variables(variables)
|
219
|
+
self.class.new(tokens.map{|part|
|
220
|
+
part.expand_partial(variables)
|
221
|
+
}.flatten(1))
|
222
|
+
end
|
223
|
+
|
224
|
+
def normalize_variables( variables )
|
225
|
+
raise ArgumentError, "Expected something that responds to :map, but got: #{variables.inspect}" unless variables.respond_to? :map
|
226
|
+
if variables.kind_of?(Array)
|
227
|
+
return Hash[self.variables.zip(variables)]
|
228
|
+
else
|
229
|
+
# Stringify variables
|
230
|
+
arg = variables.map{ |k, v| [k.to_s, v] }
|
231
|
+
if arg.any?{|elem| !elem.kind_of?(Array) }
|
232
|
+
raise ArgumentError, "Expected the output of variables.map to return an array of arrays but got #{arg.inspect}"
|
233
|
+
end
|
234
|
+
return Hash[arg]
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
private :normalize_variables
|
239
|
+
|
222
240
|
# @abstract
|
223
241
|
# Returns the type of this template. The type is a symbol which can be used in {.resolve_class} to resolve the type of this template.
|
224
242
|
#
|
data/lib/uri_template/literal.rb
CHANGED
@@ -40,6 +40,10 @@ module URITemplate::Literal
|
|
40
40
|
return string
|
41
41
|
end
|
42
42
|
|
43
|
+
def expand_partial(_)
|
44
|
+
return [self]
|
45
|
+
end
|
46
|
+
|
43
47
|
def starts_with_slash?
|
44
48
|
string[0] == SLASH
|
45
49
|
end
|
@@ -50,4 +54,4 @@ module URITemplate::Literal
|
|
50
54
|
|
51
55
|
alias to_s string
|
52
56
|
|
53
|
-
end
|
57
|
+
end
|
data/lib/uri_template/rfc6570.rb
CHANGED
@@ -33,7 +33,41 @@ class URITemplate::RFC6570
|
|
33
33
|
extend Forwardable
|
34
34
|
|
35
35
|
# @private
|
36
|
-
|
36
|
+
module Utils
|
37
|
+
|
38
|
+
include URITemplate::Utils
|
39
|
+
|
40
|
+
# Returns true iff the value is `defined` [RFC6570 Section 2.3](http://tools.ietf.org/html/rfc6570#section-2.3)
|
41
|
+
#
|
42
|
+
# The only undefined things are:
|
43
|
+
# - nil
|
44
|
+
# - arrays containing no defined value
|
45
|
+
# - associative arrays/hashes containing no defined value
|
46
|
+
#
|
47
|
+
# Things that are always defined:
|
48
|
+
# - Strings, independent of the length
|
49
|
+
def def?( value )
|
50
|
+
case( value )
|
51
|
+
when nil then
|
52
|
+
false
|
53
|
+
when Hash then
|
54
|
+
value.any?{|_, v| !v.nil? }
|
55
|
+
when Array then
|
56
|
+
if value.none?
|
57
|
+
false
|
58
|
+
elsif value[0].kind_of?(Array)
|
59
|
+
value.any?{|_,v| !v.nil? }
|
60
|
+
else
|
61
|
+
value.any?{|v| !v.nil? }
|
62
|
+
end
|
63
|
+
else
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
extend self
|
69
|
+
|
70
|
+
end
|
37
71
|
|
38
72
|
# :nocov:
|
39
73
|
if Utils.use_unicode?
|
@@ -161,34 +195,6 @@ __REGEXP__
|
|
161
195
|
|
162
196
|
end
|
163
197
|
|
164
|
-
class InvalidValue < StandardError
|
165
|
-
|
166
|
-
include URITemplate::InvalidValue
|
167
|
-
|
168
|
-
attr_reader :variable, :value
|
169
|
-
|
170
|
-
def initialize(variable, value)
|
171
|
-
@variable = variable
|
172
|
-
@value = value
|
173
|
-
super(generate_message())
|
174
|
-
end
|
175
|
-
protected
|
176
|
-
|
177
|
-
def generate_message()
|
178
|
-
return "The template variable " + variable.inspect + " cannot expand the given value "+ value.inspect
|
179
|
-
end
|
180
|
-
|
181
|
-
end
|
182
|
-
|
183
|
-
class InvalidValue::LengthLimitInapplicable < InvalidValue
|
184
|
-
|
185
|
-
protected
|
186
|
-
def generate_message()
|
187
|
-
return "The template variable "+variable.inspect+" has a length limit and therefore cannot expand an associative value ("+value.inspect+")."
|
188
|
-
end
|
189
|
-
|
190
|
-
end
|
191
|
-
|
192
198
|
# @private
|
193
199
|
class Tokenizer
|
194
200
|
|
@@ -307,9 +313,18 @@ __REGEXP__
|
|
307
313
|
# URITemplate::RFC6570.new('{?args*}').expand('args'=>{'key'=>'value'}) #=> '?key=value'
|
308
314
|
# URITemplate::RFC6570.new('{undef}').expand() #=> ''
|
309
315
|
#
|
310
|
-
# @param variables [Hash]
|
316
|
+
# @param variables [Hash, Array]
|
311
317
|
# @return String
|
312
318
|
|
319
|
+
# @method expand_partial(variables = {})
|
320
|
+
# Works like expand but keeps missing variables in place.
|
321
|
+
# @example
|
322
|
+
# URITemplate::RFC6570.new('{foo}').expand_partial('foo'=>'bar') #=> URITemplate::RFC6570.new('bar')
|
323
|
+
# URITemplate::RFC6570.new('{undef}').expand_partial() #=> URITemplate::RFC6570.new('{undef}')
|
324
|
+
#
|
325
|
+
# @param variables [Hash,Array]
|
326
|
+
# @return URITemplate
|
327
|
+
|
313
328
|
# Compiles this template into a regular expression which can be used to test whether a given uri matches this template. This template is also used for {#===}.
|
314
329
|
#
|
315
330
|
# @example
|
@@ -61,11 +61,11 @@ class URITemplate::RFC6570
|
|
61
61
|
|
62
62
|
def expand( vars )
|
63
63
|
result = []
|
64
|
-
@variable_specs.each
|
65
|
-
|
64
|
+
@variable_specs.each do | var, expand , max_length |
|
65
|
+
if Utils.def? vars[var]
|
66
66
|
result.push(*expand_one(var, vars[var], expand, max_length))
|
67
67
|
end
|
68
|
-
|
68
|
+
end
|
69
69
|
if result.any?
|
70
70
|
return (self.class::PREFIX + result.join(self.class::SEPARATOR))
|
71
71
|
else
|
@@ -73,6 +73,24 @@ class URITemplate::RFC6570
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
def expand_partial( vars )
|
77
|
+
result = []
|
78
|
+
defined = false
|
79
|
+
@variable_specs.each do | var, expand , max_length |
|
80
|
+
defined ||= vars.key? var
|
81
|
+
if Utils.def? vars[var]
|
82
|
+
result.push(*expand_one(var, vars[var], expand, max_length))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
if result.any?
|
86
|
+
return [ Literal.new(self.class::PREFIX + result.join(self.class::SEPARATOR)) ]
|
87
|
+
elsif defined
|
88
|
+
return []
|
89
|
+
else
|
90
|
+
return [ self ]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
76
94
|
def extract(position,matched)
|
77
95
|
name, expand, max_length = @variable_specs[position]
|
78
96
|
if matched.nil?
|
@@ -101,11 +119,6 @@ class URITemplate::RFC6570
|
|
101
119
|
private
|
102
120
|
|
103
121
|
def expand_one( name, value, expand, max_length)
|
104
|
-
if length_limited?(max_length)
|
105
|
-
if value.kind_of?(Array) or value.kind_of?(Hash)
|
106
|
-
raise InvalidValue::LengthLimitInapplicable.new(name,value)
|
107
|
-
end
|
108
|
-
end
|
109
122
|
if value.kind_of?(Hash) or Utils.pair_array?(value)
|
110
123
|
return transform_hash(name, value, expand, max_length)
|
111
124
|
elsif value.kind_of? Array
|
@@ -237,7 +250,7 @@ class URITemplate::RFC6570
|
|
237
250
|
if expand
|
238
251
|
hsh.map{|key,value| pair(escape(key),value) }
|
239
252
|
else
|
240
|
-
[ self_pair(name,hsh){|key,value| escape(key)+self.class::LIST_CONNECTOR+escape(value)} ]
|
253
|
+
[ self_pair(name,hsh, max_length ){|key,value| escape(key)+self.class::LIST_CONNECTOR+escape(value)} ]
|
241
254
|
end
|
242
255
|
end
|
243
256
|
|
@@ -245,7 +258,7 @@ class URITemplate::RFC6570
|
|
245
258
|
if expand
|
246
259
|
ary.map{|value| self_pair(name,value) }
|
247
260
|
else
|
248
|
-
[ self_pair(name, ary){|value| escape(value) } ]
|
261
|
+
[ self_pair(name, ary, max_length){|value| escape(value) } ]
|
249
262
|
end
|
250
263
|
end
|
251
264
|
end
|
data/lib/uri_template/token.rb
CHANGED
@@ -56,9 +56,14 @@ module URITemplate::Token
|
|
56
56
|
raise "Please implement #expand(variables) on #{self.class.inspect}."
|
57
57
|
end
|
58
58
|
|
59
|
+
# @abstract
|
60
|
+
def expand_partial(variables)
|
61
|
+
raise "Please implement #expand_partial(variables) on #{self.class.inspect}."
|
62
|
+
end
|
63
|
+
|
59
64
|
# @abstract
|
60
65
|
def to_s
|
61
66
|
raise "Please implement #to_s on #{self.class.inspect}."
|
62
67
|
end
|
63
68
|
|
64
|
-
end
|
69
|
+
end
|
data/uri_template.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uri_template
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,14 +9,14 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- - '>='
|
19
|
+
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- - '>='
|
27
|
+
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- - '>='
|
35
|
+
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
37
|
version: '0'
|
38
38
|
type: :development
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- - '>='
|
43
|
+
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
46
|
- !ruby/object:Gem::Dependency
|
@@ -48,7 +48,7 @@ dependencies:
|
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
51
|
-
- - '>='
|
51
|
+
- - ! '>='
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '0'
|
54
54
|
type: :development
|
@@ -56,7 +56,7 @@ dependencies:
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
|
-
- - '>='
|
59
|
+
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
@@ -64,7 +64,7 @@ dependencies:
|
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
66
66
|
requirements:
|
67
|
-
- - '>='
|
67
|
+
- - ! '>='
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
70
|
type: :development
|
@@ -72,7 +72,7 @@ dependencies:
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
|
-
- - '>='
|
75
|
+
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
78
|
- !ruby/object:Gem::Dependency
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
81
81
|
none: false
|
82
82
|
requirements:
|
83
|
-
- - '>='
|
83
|
+
- - ! '>='
|
84
84
|
- !ruby/object:Gem::Version
|
85
85
|
version: '0'
|
86
86
|
type: :development
|
@@ -88,7 +88,7 @@ dependencies:
|
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
89
|
none: false
|
90
90
|
requirements:
|
91
|
-
- - '>='
|
91
|
+
- - ! '>='
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
94
|
description: A templating system for URIs, which implements RFC6570 and Colon based
|
@@ -121,20 +121,19 @@ require_paths:
|
|
121
121
|
required_ruby_version: !ruby/object:Gem::Requirement
|
122
122
|
none: false
|
123
123
|
requirements:
|
124
|
-
- - '>='
|
124
|
+
- - ! '>='
|
125
125
|
- !ruby/object:Gem::Version
|
126
126
|
version: '0'
|
127
127
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
128
|
none: false
|
129
129
|
requirements:
|
130
|
-
- - '>='
|
130
|
+
- - ! '>='
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: '0'
|
133
133
|
requirements: []
|
134
134
|
rubyforge_project:
|
135
|
-
rubygems_version: 1.8.
|
135
|
+
rubygems_version: 1.8.23
|
136
136
|
signing_key:
|
137
137
|
specification_version: 3
|
138
138
|
summary: A templating system for URIs.
|
139
139
|
test_files: []
|
140
|
-
has_rdoc:
|