ruby_uri_template 1.0.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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.mkd +40 -0
- data/Rakefile +2 -0
- data/lib/uri_template.rb +167 -0
- data/lib/uri_template/parser.rb +78 -0
- data/lib/uri_template/transformer.rb +19 -0
- data/lib/uri_template/version.rb +3 -0
- data/spec/errors_spec.rb +36 -0
- data/spec/examples_from_draft.txt +135 -0
- data/spec/examples_from_draft_spec.rb +51 -0
- data/spec/params_spec.rb +17 -0
- data/spec/spec_helper.rb +2 -0
- data/uri_template.gemspec +22 -0
- metadata +98 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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
data/lib/uri_template.rb
ADDED
@@ -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
|
+
|
data/spec/errors_spec.rb
ADDED
@@ -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
|
+
|
data/spec/params_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|