ruby_uri_template 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in uri_template.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2011 Paul Sadauskas
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.mkd ADDED
@@ -0,0 +1,40 @@
1
+ # UriTemplate
2
+
3
+ Implements the URI Template draft spec, v7 http://tools.ietf.org/html/draft-gregorio-uritemplate-07
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'uri_template'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install uri_template
18
+
19
+ ## Usage
20
+
21
+ 1. `UriTemplate.new` with a UriTemplate.
22
+ 1. `#expand` the template with a hash of params to be used. Both Strings and Symbols are valid as keys.
23
+
24
+ ### Example:
25
+
26
+ tmpl = UriTemplate.new("http://example.com/search{?q,lang}")
27
+ tmpl.expand(:q => ["dogs", "cats"], "lang" => "en_US")
28
+ # => "http://example.com/search?q=dogs,cats&lang=en_US"
29
+
30
+ See the spec for other examples.
31
+
32
+ **Note:** Sometimes the spec fails on 1.8 because of hash-ordering. Use 1.9 or an ordered hash library if the order is important to you.
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,167 @@
1
+ require 'addressable/uri'
2
+
3
+ __dir__ = File.dirname(__FILE__)
4
+ require __dir__ + "/uri_template/version"
5
+ require __dir__ + "/uri_template/parser"
6
+ require __dir__ + "/uri_template/transformer"
7
+
8
+ class UriTemplate
9
+ class ParseError < StandardError; end
10
+
11
+ def initialize(uri_template)
12
+ @uri_template = uri_template
13
+ tree = Parser.new.parse(@uri_template)
14
+ @template = Transformer.new.apply(tree)
15
+ rescue Parslet::ParseFailed => ex
16
+ raise ParseError, "invalid template: #{uri_template}"
17
+ end
18
+
19
+ def expand(params)
20
+ output = ""
21
+ @template.each do |part|
22
+ case part
23
+ when String then output << part
24
+ when Hash then output << Expression.new(part).expand(params)
25
+ end
26
+ end
27
+
28
+ output
29
+ end
30
+
31
+ class Expression
32
+
33
+ def initialize(tree)
34
+ @tree = tree
35
+ end
36
+
37
+ def expand(params = {})
38
+ out = var_list.map do |var|
39
+ Var.new(self, var[:var]).value(params)
40
+ end.compact
41
+
42
+ return "" if out.empty?
43
+ first_char + out.join(separator)
44
+ end
45
+
46
+ def var_list
47
+ @tree[:var_list]
48
+ end
49
+
50
+ def operator
51
+ @tree[:operator]
52
+ end
53
+
54
+ def separator
55
+ case operator
56
+ when nil, "+", "#" then ","
57
+ when "." then "."
58
+ when "/" then "/"
59
+ when ";" then ";"
60
+ when "?", "&" then "&"
61
+ end
62
+ end
63
+
64
+ def first_char
65
+ case operator
66
+ when nil, "+" then ""
67
+ else operator
68
+ end
69
+ end
70
+
71
+ def named?
72
+ [";", "?", "&"].include? operator
73
+ end
74
+
75
+ def str_if_empty
76
+ case operator
77
+ when "?", "&" then "="
78
+ else ""
79
+ end
80
+ end
81
+
82
+ def encode_set
83
+ set = Addressable::URI::CharacterClasses::UNRESERVED
84
+ set += Addressable::URI::CharacterClasses::RESERVED if ["+", "#"].include? operator
85
+ set
86
+ end
87
+
88
+ end
89
+
90
+ class Var
91
+ attr_reader :exp
92
+
93
+ def initialize(exp, tree)
94
+ @exp, @tree = exp, tree
95
+ end
96
+
97
+ # Algorithm taken directly from the spec.
98
+ # TODO: refactor to be Ruby-like
99
+ def value(params)
100
+ value = params[name] || params[name.to_sym]
101
+
102
+ out = ""
103
+ case value
104
+ when nil
105
+ return nil
106
+ when String
107
+ if exp.named?
108
+ out << "#{encode(name)}#{value.empty? ? exp.str_if_empty : "="}"
109
+ end
110
+ out << encode(trim(value))
111
+
112
+ when Array
113
+ if !explode?
114
+ if exp.named?
115
+ out << "#{encode(name)}#{value.empty? ? exp.str_if_empty : "="}"
116
+ end
117
+ return if value.empty?
118
+ out << value.map{|v| encode(v)}.join(",")
119
+ else
120
+ return if value.empty?
121
+ out << value.map{|v| encode(v)}.join(exp.separator)
122
+ end
123
+
124
+ when Hash
125
+ if !explode?
126
+ if exp.named?
127
+ out << "#{encode(name)}#{value.empty? ? exp.str_if_empty : "="}"
128
+ end
129
+ return if value.empty?
130
+ out << value.map{|k,v| [encode(k), encode(v)]}.flatten.join(",")
131
+ else
132
+ return if value.empty?
133
+ out << value.map{|k,v| "#{encode(k)}=#{encode(v)}"}.join(exp.separator)
134
+ end
135
+
136
+ end
137
+
138
+ out
139
+ end
140
+
141
+ protected
142
+
143
+ def name
144
+ @tree[:name]
145
+ end
146
+
147
+ def explode?
148
+ @tree.has_key?(:explode)
149
+ end
150
+
151
+ def max_length
152
+ @tree[:max_length]
153
+ end
154
+
155
+ def trim(str)
156
+ max_length ? str[0..(max_length-1)] : str
157
+ end
158
+
159
+ def encode(str)
160
+ Addressable::URI.encode_component(str, exp.encode_set)
161
+ end
162
+
163
+
164
+ end
165
+
166
+ end
167
+
@@ -0,0 +1,78 @@
1
+ require 'parslet'
2
+
3
+ class UriTemplate
4
+ class Parser < Parslet::Parser
5
+
6
+ rule(:uri_template) do
7
+ (literals | expression).repeat
8
+ end
9
+
10
+ rule(:expression) do
11
+ str('{') >> operator.maybe.as(:operator) >> var_list.as(:var_list) >> str('}')
12
+ end
13
+
14
+ rule(:operator) do
15
+ str("+") | str("#") | str(".") | str("/") | str(";") | str("?") | str("&")
16
+ end
17
+
18
+ rule(:var_list) do
19
+ (varspec >> ( str(",") >> varspec ).repeat).maybe.as(:array)
20
+ end
21
+
22
+ rule(:varspec) do
23
+ (varname >> modifier.maybe).as(:var)
24
+ end
25
+
26
+ rule(:varname) do
27
+ ((varchar >> (varchar | str(".")).repeat).as(:string)).as(:name)
28
+ end
29
+
30
+ rule(:varchar) do
31
+ (alphanumeric | str("_") | pct_encoded)
32
+ end
33
+
34
+ rule(:modifier) do
35
+ prefix | explode
36
+ end
37
+
38
+ rule(:prefix) do
39
+ str(':') >> number.as(:max_length)
40
+ end
41
+
42
+ rule(:explode) do
43
+ str('*').as(:explode)
44
+ end
45
+
46
+ rule(:literals) do
47
+ (unreserved | reserved | pct_encoded).repeat(1).as(:literals)
48
+ end
49
+
50
+ rule(:unreserved) do
51
+ alphanumeric | match("[-._~]")
52
+ end
53
+
54
+ rule(:reserved) do
55
+ match("[:/?#\\[\\]@!$&'()*+,;=]")
56
+ end
57
+
58
+ rule(:pct_encoded) do
59
+ str('%') >> hex >> hex
60
+ end
61
+
62
+ rule(:alphanumeric) do
63
+ match('[A-Za-z0-9]')
64
+ end
65
+
66
+ rule(:number) do
67
+ match('[0-9]').repeat(1).as(:number)
68
+ end
69
+
70
+ rule(:hex) do
71
+ match('[a-fA-F0-9]')
72
+ end
73
+
74
+ root(:uri_template)
75
+
76
+ end
77
+ end
78
+
@@ -0,0 +1,19 @@
1
+ require 'parslet'
2
+
3
+ class UriTemplate
4
+ class Transformer < Parslet::Transform
5
+
6
+ rule(:literals => simple(:l)) { l.to_s }
7
+ rule(:string => simple(:s)) { s.to_s }
8
+
9
+ rule(:array => subtree(:ar)) { ar.is_a?(Array) ? ar : [ar] }
10
+
11
+ rule(:explode) { true }
12
+
13
+ #rule(:name => simple(:name)) { name.to_s }
14
+
15
+ rule(:number => simple(:x)) { Integer(x) }
16
+
17
+ end
18
+ end
19
+
@@ -0,0 +1,3 @@
1
+ class UriTemplate
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe UriTemplate do
4
+
5
+ describe "with good uris" do
6
+
7
+ good = [
8
+ "{var}",
9
+ "http://example.com/",
10
+ "http://example.com/{foo}",
11
+ "http://example.com/search{?q}",
12
+ "http://example.com/search{?q,list}"
13
+ ]
14
+
15
+ good.each do |tmpl|
16
+ it "should parse #{tmpl.inspect}" do
17
+ lambda { UriTemplate.new(tmpl) }.should_not raise_error(UriTemplate::ParseError)
18
+ end
19
+ end
20
+ end
21
+
22
+ describe "with invaldi uris" do
23
+
24
+ bad = [
25
+ "http://example.com/{",
26
+ "http://example.com/{^foo}"
27
+ ]
28
+
29
+ bad.each do |tmpl|
30
+ it "should not parse #{tmpl.inspect}" do
31
+ lambda { UriTemplate.new(tmpl) }.should raise_error(UriTemplate::ParseError)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,135 @@
1
+ ## 3.2.2. Simple String Expansion: {var}
2
+
3
+ {var} value
4
+ {hello} Hello%20World%21
5
+ {half} 50%25
6
+ O{empty}X OX
7
+ O{undef}X OX
8
+ {x,y} 1024,768
9
+ {x,hello,y} 1024,Hello%20World%21,768
10
+ ?{x,empty} ?1024,
11
+ ?{x,undef} ?1024
12
+ ?{undef,y} ?768
13
+ {var:3} val
14
+ {var:30} value
15
+ {list} red,green,blue
16
+ {list*} red,green,blue
17
+ {keys} semi,%3B,dot,.,comma,%2C
18
+ {keys*} semi=%3B,dot=.,comma=%2C
19
+
20
+ ## 3.2.3. Reserved expansion: {+var}
21
+
22
+ {+var} value
23
+ {+hello} Hello%20World!
24
+ {+half} 50%25
25
+
26
+ {base}index http%3A%2F%2Fexample.com%2Fhome%2Findex
27
+ {+base}index http://example.com/home/index
28
+ O{+empty}X OX
29
+ O{+undef}X OX
30
+
31
+ {+path}/here /foo/bar/here
32
+ here?ref={+path} here?ref=/foo/bar
33
+ up{+path}{var}/here up/foo/barvalue/here
34
+ {+x,hello,y} 1024,Hello%20World!,768
35
+ {+path,x}/here /foo/bar,1024/here
36
+
37
+ {+path:6}/here /foo/b/here
38
+ {+list} red,green,blue
39
+ {+list*} red,green,blue
40
+ {+keys} semi,;,dot,.,comma,,
41
+ {+keys*} semi=;,dot=.,comma=,
42
+
43
+ ## 3.2.4. Fragment expansion: {#var}
44
+
45
+ {#var} #value
46
+ {#hello} #Hello%20World!
47
+ {#half} #50%25
48
+ foo{#empty} foo#
49
+ foo{#undef} foo
50
+ {#x,hello,y} #1024,Hello%20World!,768
51
+ {#path,x}/here #/foo/bar,1024/here
52
+ {#path:6}/here #/foo/b/here
53
+ {#list} #red,green,blue
54
+ {#list*} #red,green,blue
55
+ {#keys} #semi,;,dot,.,comma,,
56
+ {#keys*} #semi=;,dot=.,comma=,
57
+
58
+ ## 3.2.5. Label expansion with dot-prefix: {.var}
59
+
60
+ {.who} .fred
61
+ {.who,who} .fred.fred
62
+ {.half,who} .50%25.fred
63
+ www{.dom} www.example.com
64
+ X{.var} X.value
65
+ X{.empty} X.
66
+ X{.undef} X
67
+ X{.var:3} X.val
68
+ X{.list} X.red,green,blue
69
+ X{.list*} X.red.green.blue
70
+ X{.keys} X.semi,%3B,dot,.,comma,%2C
71
+ X{.keys*} X.semi=%3B.dot=..comma=%2C
72
+ X{.empty_keys} X
73
+ X{.empty_keys*} X
74
+
75
+ ## 3.2.6. Path segment expansion: {/var}
76
+
77
+ {/who} /fred
78
+ {/who,who} /fred/fred
79
+ {/half,who} /50%25/fred
80
+ {/who,dub} /fred/me%2Ftoo
81
+ {/var} /value
82
+ {/var,empty} /value/
83
+ {/var,undef} /value
84
+ {/var,x}/here /value/1024/here
85
+ {/var:1,var} /v/value
86
+ {/list} /red,green,blue
87
+ {/list*} /red/green/blue
88
+ {/list*,path:4} /red/green/blue/%2Ffoo
89
+ {/keys} /semi,%3B,dot,.,comma,%2C
90
+ {/keys*} /semi=%3B/dot=./comma=%2C
91
+
92
+ ## 3.2.7. Path-style parameter expansion: {;var}
93
+
94
+ {;who} ;who=fred
95
+ {;half} ;half=50%25
96
+ {;empty} ;empty
97
+ {;v,empty,who} ;v=6;empty;who=fred
98
+ {;v,bar,who} ;v=6;who=fred
99
+ {;x,y} ;x=1024;y=768
100
+ {;x,y,empty} ;x=1024;y=768;empty
101
+ {;x,y,undef} ;x=1024;y=768
102
+ {;hello:5} ;hello=Hello
103
+ {;list} ;list=red,green,blue
104
+ {;list*} ;red;green;blue
105
+ {;keys} ;keys=semi,%3B,dot,.,comma,%2C
106
+ {;keys*} ;semi=%3B;dot=.;comma=%2C
107
+
108
+ ## 3.2.8. Form-style query expansion: {?var}
109
+
110
+ {?who} ?who=fred
111
+ {?half} ?half=50%25
112
+ {?x,y} ?x=1024&y=768
113
+ {?x,y,empty} ?x=1024&y=768&empty=
114
+ {?x,y,undef} ?x=1024&y=768
115
+ {?var:3} ?var=val
116
+ {?list} ?list=red,green,blue
117
+ {?list*} ?red&green&blue
118
+ {?keys} ?keys=semi,%3B,dot,.,comma,%2C
119
+ {?keys*} ?semi=%3B&dot=.&comma=%2C
120
+
121
+ ## 3.2.9. Form-style query continuation: {&var}
122
+
123
+ {&who} &who=fred
124
+ {&half} &half=50%25
125
+ ?fixed=yes{&x} ?fixed=yes&x=1024
126
+ {&x,y,empty} &x=1024&y=768&empty=
127
+ {&x,y,undef} &x=1024&y=768
128
+
129
+ {&var:3} &var=val
130
+ {&list} &list=red,green,blue
131
+ {&list*} &red&green&blue
132
+ {&keys} &keys=semi,%3B,dot,.,comma,%2C
133
+ {&keys*} &semi=%3B&dot=.&comma=%2C
134
+
135
+
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ # These examples are take directly from the draft spec
4
+ # http://tools.ietf.org/html/draft-gregorio-uritemplate-07
5
+ describe "Examples given in the Draft" do
6
+ let(:params) do
7
+ {
8
+ "dom" => "example.com",
9
+ "dub" => "me/too",
10
+ "hello" => "Hello World!",
11
+ "half" => "50%",
12
+ "var" => "value",
13
+ "who" => "fred",
14
+ "base" => "http://example.com/home/",
15
+ "path" => "/foo/bar",
16
+ "list" => [ "red", "green", "blue" ],
17
+ "keys" => {"semi"=>";", "dot"=>".", "comma" =>","},
18
+ "v" => "6",
19
+ "x" => "1024",
20
+ "y" => "768",
21
+ "empty" => "",
22
+ "empty_keys" => [],
23
+ "undef" => nil
24
+ }
25
+ end
26
+
27
+ examples = {}
28
+ section = ""
29
+ File.read(File.dirname(__FILE__) + "/examples_from_draft.txt").each_line do |line|
30
+ next if line.strip.empty?
31
+ if line =~ /^##/
32
+ section = line.gsub('## ', '').to_s
33
+ examples[section] = []
34
+ else
35
+ template, expected = line.strip.split(/\s+/,2)
36
+ examples[section] << [template, expected]
37
+ end
38
+ end
39
+
40
+ examples.each do |section, data|
41
+ describe section do
42
+ data.each do |template, expected|
43
+ it "should render #{template.inspect} as #{expected.inspect}" do
44
+ UriTemplate.new(template).expand(params).should == expected
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe UriTemplate do
4
+
5
+ describe "params" do
6
+ let(:template) { UriTemplate.new("{foo}") }
7
+
8
+ it "should handle string keys" do
9
+ template.expand("foo" => "bar").should == "bar"
10
+ end
11
+
12
+ it "should handle symbol keys" do
13
+ template.expand(:foo => "bar").should == "bar"
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,2 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/uri_template")
2
+
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/uri_template/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Paul Sadauskas"]
6
+ gem.email = ["psadauskas@gmail.com"]
7
+ gem.description = %q{Expands URI Templates}
8
+ gem.summary = %q{Implements the URI Template draft specification v7}
9
+ gem.homepage = ""
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "ruby_uri_template"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = UriTemplate::VERSION
17
+
18
+ gem.add_dependency "parslet"
19
+ gem.add_dependency "addressable"
20
+
21
+ gem.add_development_dependency "rspec"
22
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_uri_template
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Paul Sadauskas
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: parslet
16
+ requirement: &70344458699960 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70344458699960
25
+ - !ruby/object:Gem::Dependency
26
+ name: addressable
27
+ requirement: &70344458699540 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70344458699540
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70344458699120 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70344458699120
47
+ description: Expands URI Templates
48
+ email:
49
+ - psadauskas@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - LICENSE
57
+ - README.mkd
58
+ - Rakefile
59
+ - lib/uri_template.rb
60
+ - lib/uri_template/parser.rb
61
+ - lib/uri_template/transformer.rb
62
+ - lib/uri_template/version.rb
63
+ - spec/errors_spec.rb
64
+ - spec/examples_from_draft.txt
65
+ - spec/examples_from_draft_spec.rb
66
+ - spec/params_spec.rb
67
+ - spec/spec_helper.rb
68
+ - uri_template.gemspec
69
+ homepage: ''
70
+ licenses: []
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.10
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: Implements the URI Template draft specification v7
93
+ test_files:
94
+ - spec/errors_spec.rb
95
+ - spec/examples_from_draft.txt
96
+ - spec/examples_from_draft_spec.rb
97
+ - spec/params_spec.rb
98
+ - spec/spec_helper.rb