iuri 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/README.md +138 -22
- data/Rakefile +1 -0
- data/iuri.gemspec +3 -2
- data/lib/iuri.rb +56 -27
- data/lib/iuri/version.rb +2 -2
- data/test/iuri_test.rb +25 -3
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80c50f10a15c87f8aedd47924a82bd4069c1a9e3
|
4
|
+
data.tar.gz: a78f253736108f72b6b27bdae2ace3563859e6d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c904845ebc55971e9f3d968e49b5b1b28a088d97db83ed20477f144e19e608d0057e51bbbdcebea703ce0eb1e9b05509942cac4cd7ad57494be1b92e3742500
|
7
|
+
data.tar.gz: 015553c5aa28b0aa769f498b33ccadb870792272a0acbcb229719aa55928dd1c48bf92fab889a6a9640cd5fa3afe437f2270dce6502e8ace1d5fdb9bc131ad04
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,42 +1,158 @@
|
|
1
1
|
# IURI
|
2
2
|
|
3
|
-
Build
|
4
|
-
|
3
|
+
[![Build Status](https://travis-ci.org/tatey/iuri.svg?branch=master)](https://travis-ci.org/tatey/iuri)
|
4
|
+
|
5
|
+
Build complex URIs with chainability and immutability. No string
|
6
|
+
concatenation required. If you're familiar with `URI` then you already know
|
7
|
+
how to use it.
|
8
|
+
|
9
|
+
First it starts like this.
|
10
|
+
|
11
|
+
``` ruby
|
12
|
+
"https://lifx.co/api/v1/devices".
|
13
|
+
```
|
14
|
+
|
15
|
+
Then you need to target different hosts in development, staging and
|
16
|
+
production.
|
17
|
+
|
18
|
+
``` ruby
|
19
|
+
"#{ENV['API_SCHEME']}://#{ENV['API_HOST']}/api/v1/devices"
|
20
|
+
```
|
21
|
+
|
22
|
+
Then staging becomes protected by basic authentication.
|
23
|
+
|
24
|
+
``` ruby
|
25
|
+
if ENV['API_CREDENTIALS']
|
26
|
+
"#{ENV['API_SCHEME']}://#{ENV['API_CREDENTIALS']}@#{ENV['API_HOST']}/api/v1/devices"
|
27
|
+
else
|
28
|
+
"#{ENV['API_SCHEME']}://#{ENV['API_HOST']}/api/v1/devices"
|
29
|
+
end
|
30
|
+
```
|
31
|
+
|
32
|
+
Then you need to target different paths.
|
33
|
+
|
34
|
+
``` ruby
|
35
|
+
def devices_url
|
36
|
+
base_url + '/api/v1/devices'
|
37
|
+
end
|
38
|
+
|
39
|
+
def accounts_url
|
40
|
+
base_url + '/api/v1/accounts'
|
41
|
+
end
|
42
|
+
|
43
|
+
def base_url
|
44
|
+
if ENV['API_CREDENTIALS']
|
45
|
+
"#{ENV['API_SCHEME']}://#{ENV['API_CREDENTIALS']}@#{ENV['API_HOST']}"
|
46
|
+
else
|
47
|
+
"#{ENV['API_SCHEME']}://#{ENV['API_HOST']}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Now you've added three environment variables and you're vulnerable to
|
53
|
+
developers mistyping URLs. With `IURI` there's a better way.
|
54
|
+
|
55
|
+
``` ruby
|
56
|
+
# Development
|
57
|
+
# ENV['API_BASE_URL'] = 'http://lifx.dev'
|
58
|
+
#
|
59
|
+
# Staging
|
60
|
+
# ENV['API_BASE_URL'] = 'https://user:pass@staging.lifx.co'
|
61
|
+
#
|
62
|
+
# Production
|
63
|
+
# ENV['API_BASE_URL'] = 'https://lifx.co'
|
64
|
+
|
65
|
+
def devices_url
|
66
|
+
API_BASE_URL.merge(path: "/api/v1/devices")
|
67
|
+
end
|
68
|
+
|
69
|
+
def accounts_url
|
70
|
+
API_BASE_URL.merge(path: "/api/v1/accounts")
|
71
|
+
end
|
72
|
+
|
73
|
+
def API_BASE_URL
|
74
|
+
IURI.parse(ENV['API_BASE_URL'])
|
75
|
+
end
|
76
|
+
```
|
5
77
|
|
6
|
-
##
|
7
|
-
|
8
|
-
Add this line to your application's Gemfile:
|
9
|
-
|
10
|
-
gem 'iuri'
|
11
|
-
|
12
|
-
And then execute:
|
13
|
-
|
14
|
-
$ bundle
|
78
|
+
## Usage
|
15
79
|
|
16
|
-
|
80
|
+
Parse URL and append a path.
|
81
|
+
|
82
|
+
``` ruby
|
83
|
+
uri = IURI.parse("https://user:secret@lifx.co").merge(path: "/api/v1/devices")
|
84
|
+
uri.to_s # => "https://user:secret@lifx.co/api/v1/devices"
|
85
|
+
```
|
86
|
+
|
87
|
+
Preferring components to strings gives you greater flexibility over the
|
88
|
+
base URL. Here we include a query string at the end of the URL and change
|
89
|
+
the path as required.
|
90
|
+
|
91
|
+
``` ruby
|
92
|
+
uri = IURI.parse("https://lifx.co?api_key=secret").merge(path: "/api/v1/devices")
|
93
|
+
uri.to_s # => "https://lifx.co/api/v1/devices?api_key=secret"
|
94
|
+
```
|
95
|
+
|
96
|
+
Queries can also be built with a hash avoiding worrying about formatting
|
97
|
+
and escaping. Deep hashes are OK.
|
98
|
+
|
99
|
+
``` ruby
|
100
|
+
uri = IURI.parse("https://lifx.co").merge(params: {api_key: 'secret'})
|
101
|
+
uri.to_s # => "https://lifx.co/?api_key=secret"
|
102
|
+
```
|
103
|
+
|
104
|
+
Supports the same components as `URI`. Here's a sample of commonly used
|
105
|
+
components.
|
106
|
+
|
107
|
+
``` ruby
|
108
|
+
iuri = IURI.parse("https://lifx.co").merge({
|
109
|
+
path: "/api/v1/devices"
|
110
|
+
query: "api_key=secret"
|
111
|
+
user: "user"
|
112
|
+
password: "secret"
|
113
|
+
})
|
114
|
+
|
115
|
+
iuri.path # => "/api/v1/devices"
|
116
|
+
iuri.query # => "api_key=secret"
|
117
|
+
iuri.user # => "user"
|
118
|
+
iuri.password # => "secret"
|
119
|
+
```
|
120
|
+
|
121
|
+
Each `merge` returns a copy guaranteeing that constants and variables
|
122
|
+
remain unchanged.
|
123
|
+
|
124
|
+
``` ruby
|
125
|
+
uri1 = IURI.parse("https://lifx.co")
|
126
|
+
uri2 = uri1.merge(path: "/api/v1/devices")
|
127
|
+
uri1.to_s # => "https://lifx.co"
|
128
|
+
uri2.to_s # => "https://lifx.co/api/v1/devices"
|
129
|
+
```
|
17
130
|
|
18
|
-
|
131
|
+
## Installation
|
19
132
|
|
20
|
-
|
133
|
+
First, add this line to your application's Gemfile.
|
21
134
|
|
22
|
-
|
23
|
-
|
135
|
+
``` ruby
|
136
|
+
gem 'iuri'
|
137
|
+
```
|
24
138
|
|
25
|
-
|
139
|
+
Then, then execute.
|
26
140
|
|
27
|
-
|
28
|
-
|
29
|
-
|
141
|
+
```
|
142
|
+
$ bundle
|
143
|
+
```
|
30
144
|
|
31
145
|
## Tests
|
32
146
|
|
33
147
|
Run the entire test suite.
|
34
148
|
|
35
|
-
|
149
|
+
```
|
150
|
+
$ rake
|
151
|
+
```
|
36
152
|
|
37
153
|
## Contributing
|
38
154
|
|
39
|
-
1. Fork it (
|
155
|
+
1. Fork it (https://github.com/tatey/iuri/fork)
|
40
156
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
41
157
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
42
158
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/Rakefile
CHANGED
data/iuri.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ['Tate Johnson']
|
10
10
|
spec.email = ['tate@lifx.co']
|
11
11
|
spec.summary = %q{Build complex URIs with chainability and immutability.}
|
12
|
-
spec.description = %q{Build complex URIs with chainability and immutability.}
|
13
|
-
spec.homepage = ''
|
12
|
+
spec.description = %q{Build complex URIs with chainability and immutability. No string concatenation required.}
|
13
|
+
spec.homepage = 'https://github.com/tatey/iuri'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -19,5 +19,6 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
22
|
+
spec.add_development_dependency 'minitest', '~> 5.4.2'
|
22
23
|
spec.add_development_dependency 'rake'
|
23
24
|
end
|
data/lib/iuri.rb
CHANGED
@@ -1,40 +1,69 @@
|
|
1
|
+
require 'delegate'
|
1
2
|
require 'uri'
|
2
3
|
require 'iuri/version'
|
3
4
|
|
4
|
-
|
5
|
-
def initialize(uri)
|
6
|
-
@uri = uri
|
7
|
-
end
|
8
|
-
|
5
|
+
module IURI
|
9
6
|
def self.parse(string)
|
10
7
|
uri = URI.parse(string)
|
11
|
-
new(uri)
|
8
|
+
Generic.new(uri)
|
12
9
|
end
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
copy.
|
11
|
+
class Generic < SimpleDelegator
|
12
|
+
# Change components of a URI using a hash. Changes are chainable and
|
13
|
+
# each one returns a new instance.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
# uri1 = IURI.parse("https://lifx.co")
|
17
|
+
# uri2 = uri1.merge(path: "/foo/bar")
|
18
|
+
# uri2.to_s # => "https://lifx.co/foo/bar"
|
19
|
+
#
|
20
|
+
# @param options [Hash] Components
|
21
|
+
# @return [URI] A new instance
|
22
|
+
def merge(components)
|
23
|
+
copy = clone
|
24
|
+
components.each do |key, value|
|
25
|
+
writer = :"#{key}="
|
26
|
+
if copy.respond_to?(writer)
|
27
|
+
copy.send(writer, value)
|
28
|
+
else
|
29
|
+
raise KeyError, "key not found: \"#{key}\""
|
30
|
+
end
|
31
|
+
end
|
32
|
+
copy
|
33
|
+
end
|
34
|
+
|
35
|
+
def params=(new_params)
|
36
|
+
self.query = build_nested_query(new_params)
|
37
|
+
end
|
38
|
+
|
39
|
+
def inspect
|
40
|
+
super.sub('#<URI', '#<IURI')
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# A special thanks to rack for this one.
|
46
|
+
# See https://github.com/rack/rack/blob/e98a9f7ef0ddd9589145ea953948c73a8ce3caa9/lib/rack/utils.rb
|
47
|
+
def build_nested_query(value, prefix = nil)
|
48
|
+
case value
|
49
|
+
when Array
|
50
|
+
value.map { |v|
|
51
|
+
build_nested_query(v, "#{prefix}[]")
|
52
|
+
}.join("&")
|
53
|
+
when Hash
|
54
|
+
value.map { |k, v|
|
55
|
+
build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
56
|
+
}.reject(&:empty?).join('&')
|
57
|
+
when nil
|
58
|
+
prefix
|
30
59
|
else
|
31
|
-
raise
|
60
|
+
raise ArgumentError, "value must be a Hash" if prefix.nil?
|
61
|
+
"#{prefix}=#{escape(value)}"
|
32
62
|
end
|
33
63
|
end
|
34
|
-
self.class.new(copy)
|
35
|
-
end
|
36
64
|
|
37
|
-
|
38
|
-
|
65
|
+
def escape(value)
|
66
|
+
URI.encode_www_form_component(value)
|
67
|
+
end
|
39
68
|
end
|
40
69
|
end
|
data/lib/iuri/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '1.
|
1
|
+
module IURI
|
2
|
+
VERSION = '1.1.0'
|
3
3
|
end
|
data/test/iuri_test.rb
CHANGED
@@ -2,23 +2,45 @@ require 'minitest/autorun'
|
|
2
2
|
require 'iuri'
|
3
3
|
|
4
4
|
class IURITest < Minitest::Test
|
5
|
-
def
|
5
|
+
def test_setting_known_components
|
6
6
|
uri1 = IURI.parse('http://lifx.co')
|
7
7
|
uri2 = uri1.merge(scheme: 'https', path: '/foo/bar', query: 'baz=true')
|
8
8
|
|
9
9
|
assert_equal 'https://lifx.co/foo/bar?baz=true', uri2.to_s
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def test_setting_unknown_components_raises_key_error
|
13
13
|
assert_raises(KeyError) do
|
14
14
|
IURI.parse('http://lifx.co').merge(combobulator: 42)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def test_setting_params
|
19
|
+
uri1 = IURI.parse('http://lifx.co')
|
20
|
+
uri2 = uri1.merge(params: {a: '1', b: ['1', '2', '3'], c: {d: '1'}})
|
21
|
+
|
22
|
+
assert_equal 'http://lifx.co?a=1&b[]=1&b[]=2&b[]=3&c[d]=1', uri2.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_getting_known_components
|
26
|
+
uri = IURI.parse('http://lifx.co/foo/bar?baz=true')
|
27
|
+
|
28
|
+
assert uri.scheme, 'http'
|
29
|
+
assert uri.host, 'lifx.co'
|
30
|
+
assert uri.path, '/foo/bar'
|
31
|
+
assert uri.query, 'baz=true'
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_merge_returns_copy
|
19
35
|
uri1 = IURI.parse('http://lifx.co')
|
20
36
|
uri2 = uri1.merge(path: '/foo/bar')
|
21
37
|
|
22
38
|
refute_same uri1, uri2
|
23
39
|
end
|
40
|
+
|
41
|
+
def test_inspect
|
42
|
+
uri = IURI.parse('http://lifx.co')
|
43
|
+
|
44
|
+
assert_match /\A#<IURI/, uri.inspect
|
45
|
+
end
|
24
46
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iuri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tate Johnson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.4.2
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 5.4.2
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,7 +52,8 @@ dependencies:
|
|
38
52
|
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
|
-
description: Build complex URIs with chainability and immutability.
|
55
|
+
description: Build complex URIs with chainability and immutability. No string concatenation
|
56
|
+
required.
|
42
57
|
email:
|
43
58
|
- tate@lifx.co
|
44
59
|
executables: []
|
@@ -46,6 +61,7 @@ extensions: []
|
|
46
61
|
extra_rdoc_files: []
|
47
62
|
files:
|
48
63
|
- ".gitignore"
|
64
|
+
- ".travis.yml"
|
49
65
|
- Gemfile
|
50
66
|
- LICENSE.txt
|
51
67
|
- README.md
|
@@ -54,7 +70,7 @@ files:
|
|
54
70
|
- lib/iuri.rb
|
55
71
|
- lib/iuri/version.rb
|
56
72
|
- test/iuri_test.rb
|
57
|
-
homepage:
|
73
|
+
homepage: https://github.com/tatey/iuri
|
58
74
|
licenses:
|
59
75
|
- MIT
|
60
76
|
metadata: {}
|
@@ -80,4 +96,3 @@ specification_version: 4
|
|
80
96
|
summary: Build complex URIs with chainability and immutability.
|
81
97
|
test_files:
|
82
98
|
- test/iuri_test.rb
|
83
|
-
has_rdoc:
|