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.
@@ -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: