uri_template 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|