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.
@@ -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
- - * f*** bug.
17
+
18
+ * [BUGFIX] f*** bug.
3
19
 
4
20
  # 0.5.0 - 23.09.2012
5
- - - Removed draft7
6
- - - splitted absoulte? method into host? and scheme?
7
- - + the URITemplate interface is now much stronger
8
- - * code quality _significantly_ improved
9
- - + concat method
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
- - + expand now accepts symbols as keys ( thanks to @peterhellber )
13
- - + expand now accepts arrays of pairs ( thanks to @peterhellber )
14
- - * fixed some testing bugs
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
- - + Implemented the final version. Default implementation is now RFC 6570
18
- - * BUGFIX: variables with terminal dots were allowed
19
- - * BUGFIX: lists of commas were parsed incorrectly
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
- - * Compatibility: Works now with MRI 1.8.7 and REE
41
+
42
+ * [ENHANCEMENT] Works now with MRI 1.8.7 and REE
23
43
 
24
44
  # 0.2.0 - 03.12.2011
25
- - * Reworked the escaping mechanism
26
- - + escape_utils can now be used to boost escape/unescape performance
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
- - * Compatiblity: Works now with MRI 1.9.3, Rubinius and JRuby
30
- - * Various (significant!) performance improvements
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
- - * BUGFIX: Draft7./ now concatenates literals correctly
34
- - * BUGFIX: Draft7.tokens is now public
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
- - + added a new template-type: Colon
60
+
61
+ * [FEATURE] added a new template-type: Colon
38
62
  this should allow (some day) to rails-like routing tables
39
- - + made the tokens-method mandatory and added two interfaces for tokens.
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
- - + added a bunch of useful helper methods
67
+
68
+ * [ENHANCEMENT] added a bunch of useful helper methods
44
69
 
45
70
  # 0.1.0 - 2.11.2011
46
- - - Removed Sections. They made too many headaches.
47
- - + Made draft7 template concatenateable. This should replace sections.
48
- - * BUGFIX: multiline uris were matched
49
- - * BUGFIX: variablenames were decoded when this was not appreciated
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
- - * BUGFIX: Concatenating empty sections no more leads to catch-all templates, when an emtpy template was appreciated.
53
- - + The extracted variables now contains the keys :suffix and :prefix if the match didn't consume the whole uri.
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
- - Initial version
83
+
84
+ * [FEATURE] Initial version
data/README.md CHANGED
@@ -38,7 +38,9 @@ Examples
38
38
 
39
39
  # This will give: {'x' => 'z'}
40
40
  tpl2.extract('/z/y')
41
-
41
+
42
+ # This will give a new uri template with just the host expanded:
43
+ tpl.expand_partial(host: "www.host.com")
42
44
 
43
45
  RFC 6570 Syntax
44
46
  --------------------
@@ -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
- raise ArgumentError, "Expected something that responds to :map, but got: #{variables.inspect}" unless variables.respond_to? :map
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
  #
@@ -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
@@ -33,7 +33,41 @@ class URITemplate::RFC6570
33
33
  extend Forwardable
34
34
 
35
35
  # @private
36
- Utils = URITemplate::Utils
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{| var, expand , max_length |
65
- unless vars[var].nil?
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
@@ -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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'uri_template'
3
- s.version = '0.5.3'
3
+ s.version = '0.6.0'
4
4
  s.date = Time.now.strftime('%Y-%m-%d')
5
5
  s.authors = ["HannesG"]
6
6
  s.email = %q{hannes.georg@googlemail.com}
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.5.3
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-04-04 00:00:00.000000000 Z
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.25
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: