jeff 0.3.2 → 0.4.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/Guardfile +1 -1
- data/README.md +13 -31
- data/jeff.gemspec +2 -3
- data/lib/jeff.rb +33 -37
- data/lib/jeff/version.rb +1 -1
- data/spec/jeff_spec.rb +9 -21
- metadata +11 -30
- data/examples/amazon.yml.example +0 -3
- data/examples/debug.rb +0 -41
- data/lib/jeff/document.rb +0 -48
- data/lib/jeff/streamer.rb +0 -22
- data/spec/jeff/document_spec.rb +0 -49
- data/spec/jeff/streamer_spec.rb +0 -28
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# Jeff
|
2
2
|
|
3
3
|
**Jeff** is a light-weight module that mixes in client behaviour for
|
4
|
-
[Amazon Web Services (AWS)][aws]. It wraps [Excon][excon]
|
5
|
-
[
|
4
|
+
[Amazon Web Services (AWS)][aws]. It wraps [Excon][excon] and implements
|
5
|
+
[Signature Version 2][sign].
|
6
6
|
|
7
7
|
![jeff][jeff]
|
8
8
|
|
9
9
|
## Usage
|
10
10
|
|
11
|
-
Build a
|
11
|
+
Build a hypothetical client.
|
12
12
|
|
13
13
|
```ruby
|
14
14
|
class Client
|
@@ -20,15 +20,14 @@ Customise default headers and parameters.
|
|
20
20
|
|
21
21
|
```ruby
|
22
22
|
class Client
|
23
|
-
|
24
|
-
params 'Service' => 'SomeService',
|
23
|
+
params 'Service' => 'Service',
|
25
24
|
'Tag' => -> { tag }
|
26
25
|
|
27
26
|
attr_accessor :tag
|
28
27
|
end
|
29
28
|
```
|
30
29
|
|
31
|
-
Set
|
30
|
+
Set AWS endpoint and credentials.
|
32
31
|
|
33
32
|
```ruby
|
34
33
|
client = Client.new.tap do |config|
|
@@ -41,33 +40,16 @@ end
|
|
41
40
|
You should now be able to access the endpoint.
|
42
41
|
|
43
42
|
```ruby
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
puts res.status # => 200
|
48
|
-
puts res.body.root # => { 'Foo' => 'Bar' }
|
49
|
-
```
|
50
|
-
|
51
|
-
### Chunked Requests
|
52
|
-
|
53
|
-
You can upload large files performantly by passing a proc that delivers
|
54
|
-
chunks.
|
55
|
-
|
56
|
-
```ruby
|
57
|
-
file = File.open 'data'
|
58
|
-
chunker = -> { file.read Excon::CHUNK_SIZE).to_s }
|
59
|
-
|
60
|
-
client.post query: {},
|
61
|
-
request_block: chunker
|
43
|
+
client.post query: { 'Foo' => 'Bar' },
|
44
|
+
body: 'data'
|
62
45
|
```
|
63
46
|
|
64
47
|
## Compatibility
|
65
48
|
|
66
|
-
**Jeff** is compatible with [
|
49
|
+
**Jeff** is compatible with [Ruby 1.9 flavours][travis].
|
67
50
|
|
68
|
-
[aws]:
|
69
|
-
[excon]:
|
70
|
-
[jeff]:
|
71
|
-
[
|
72
|
-
[
|
73
|
-
[travis]: http://travis-ci.org/#!/hakanensari/jeff
|
51
|
+
[aws]: http://aws.amazon.com/
|
52
|
+
[excon]: https://github.com/geemus/excon
|
53
|
+
[jeff]: http://f.cl.ly/items/0a3R3J0k1R2f423k1q2l/jeff.jpg
|
54
|
+
[sign]: http://docs.amazonwebservices.com/general/latest/gr/signature-version-2.html
|
55
|
+
[travis]: http://travis-ci.org/#!/hakanensari/jeff
|
data/jeff.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |gem|
|
|
7
7
|
gem.email = ['hakan.ensari@papercavalier.com']
|
8
8
|
gem.description = %q{Minimum-viable Amazon Web Services (AWS) client}
|
9
9
|
gem.summary = %q{AWS client}
|
10
|
-
gem.homepage = 'https://github.com/
|
10
|
+
gem.homepage = 'https://github.com/papercavalier/jeff'
|
11
11
|
|
12
12
|
gem.files = `git ls-files`.split($\)
|
13
13
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -16,8 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.require_paths = ['lib']
|
17
17
|
gem.version = Jeff::VERSION
|
18
18
|
|
19
|
-
gem.add_dependency 'excon',
|
20
|
-
gem.add_dependency 'nokogiri', '~> 1.5'
|
19
|
+
gem.add_dependency 'excon', '~> 0.15.0'
|
21
20
|
gem.add_development_dependency 'guard-rspec'
|
22
21
|
gem.add_development_dependency 'rake'
|
23
22
|
gem.add_development_dependency 'rspec'
|
data/lib/jeff.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
require 'time'
|
2
|
-
|
3
1
|
require 'excon'
|
2
|
+
require 'time'
|
4
3
|
|
5
4
|
require 'jeff/secret'
|
6
|
-
require 'jeff/streamer'
|
7
5
|
require 'jeff/version'
|
8
6
|
|
7
|
+
# Jeff is a light-weight module that mixes in client behaviour for Amazon Web
|
8
|
+
# Services (AWS).
|
9
9
|
module Jeff
|
10
|
+
USER_AGENT = "Jeff/#{VERSION} (Language=Ruby; #{`hostname`.chomp})"
|
11
|
+
|
10
12
|
MissingEndpoint = Class.new ArgumentError
|
11
13
|
MissingKey = Class.new ArgumentError
|
12
14
|
MissingSecret = Class.new ArgumentError
|
@@ -15,6 +17,13 @@ module Jeff
|
|
15
17
|
|
16
18
|
def self.included(base)
|
17
19
|
base.extend ClassMethods
|
20
|
+
|
21
|
+
base.headers 'User-Agent' => USER_AGENT
|
22
|
+
|
23
|
+
base.params 'AWSAccessKeyId' => -> { key },
|
24
|
+
'SignatureVersion' => '2',
|
25
|
+
'SignatureMethod' => 'HmacSHA256',
|
26
|
+
'Timestamp' => -> { Time.now.utc.iso8601 }
|
18
27
|
end
|
19
28
|
|
20
29
|
# Internal: Builds a sorted query.
|
@@ -23,7 +32,7 @@ module Jeff
|
|
23
32
|
#
|
24
33
|
# Returns a query String.
|
25
34
|
def build_query(hsh)
|
26
|
-
|
35
|
+
params
|
27
36
|
.merge(hsh)
|
28
37
|
.sort
|
29
38
|
.map { |k, v| "#{k}=#{ escape v }" }
|
@@ -32,22 +41,10 @@ module Jeff
|
|
32
41
|
|
33
42
|
# Internal: Returns an Excon::Connection.
|
34
43
|
def connection
|
35
|
-
@connection ||= Excon.new endpoint, headers:
|
44
|
+
@connection ||= Excon.new endpoint, headers: headers,
|
36
45
|
idempotent: true
|
37
46
|
end
|
38
47
|
|
39
|
-
# Internal: Returns the Hash default request parameters.
|
40
|
-
def default_params
|
41
|
-
self.class.params.reduce({}) do |a, (k, v)|
|
42
|
-
a.update k => (v.is_a?(Proc) ? instance_exec(&v) : v)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Internal: Returns the Hash default headers.
|
47
|
-
def default_headers
|
48
|
-
self.class.headers
|
49
|
-
end
|
50
|
-
|
51
48
|
# Internal: Gets the String AWS endpoint.
|
52
49
|
#
|
53
50
|
# Raises a MissingEndpoint error if endpoint is missing.
|
@@ -58,6 +55,11 @@ module Jeff
|
|
58
55
|
# Sets the String AWS endpoint.
|
59
56
|
attr_writer :endpoint
|
60
57
|
|
58
|
+
# Internal: Returns the Hash default headers.
|
59
|
+
def headers
|
60
|
+
self.class.headers
|
61
|
+
end
|
62
|
+
|
61
63
|
# Internal: Gets the String AWS access key id.
|
62
64
|
#
|
63
65
|
# Raises a MissingKey error if key is missing.
|
@@ -68,6 +70,13 @@ module Jeff
|
|
68
70
|
# Sets the String AWS access key id.
|
69
71
|
attr_writer :key
|
70
72
|
|
73
|
+
# Internal: Returns the Hash default request parameters.
|
74
|
+
def params
|
75
|
+
self.class.params.reduce({}) do |a, (k, v)|
|
76
|
+
a.update k => (v.is_a?(Proc) ? instance_exec(&v) : v)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
71
80
|
# Internal: Gets the Jeff::Secret.
|
72
81
|
#
|
73
82
|
# Raises a MissingSecret error if secret is missing.
|
@@ -84,18 +93,13 @@ module Jeff
|
|
84
93
|
@secret = Secret.new key
|
85
94
|
end
|
86
95
|
|
87
|
-
# Generate HTTP request verb methods that sign queries and
|
88
|
-
#
|
89
|
-
Excon::HTTP_VERBS.
|
96
|
+
# Generate HTTP request verb methods that sign queries and return response
|
97
|
+
# bodies as IO objects.
|
98
|
+
Excon::HTTP_VERBS.each do |method|
|
90
99
|
eval <<-DEF
|
91
100
|
def #{method}(opts = {})
|
92
|
-
|
93
|
-
|
94
|
-
response_block: streamer
|
95
|
-
res = connection.request sign opts
|
96
|
-
res.body = streamer
|
97
|
-
|
98
|
-
res
|
101
|
+
opts.update method: :#{method}
|
102
|
+
connection.request sign opts
|
99
103
|
end
|
100
104
|
DEF
|
101
105
|
end
|
@@ -134,16 +138,13 @@ module Jeff
|
|
134
138
|
end
|
135
139
|
|
136
140
|
module ClassMethods
|
137
|
-
# Amazon recommends that libraries identify themselves via a User Agent.
|
138
|
-
USER_AGENT = "Jeff/#{VERSION} (Language=Ruby; #{`hostname`.chomp})"
|
139
|
-
|
140
141
|
# Gets/Updates the default headers.
|
141
142
|
#
|
142
143
|
# hsh - A Hash of headers.
|
143
144
|
#
|
144
145
|
# Returns the Hash headers.
|
145
146
|
def headers(hsh = nil)
|
146
|
-
@headers ||= {
|
147
|
+
@headers ||= {}
|
147
148
|
@headers.update hsh if hsh
|
148
149
|
|
149
150
|
@headers
|
@@ -155,12 +156,7 @@ module Jeff
|
|
155
156
|
#
|
156
157
|
# Returns the Hash parameters.
|
157
158
|
def params(hsh = nil)
|
158
|
-
@params ||= {
|
159
|
-
'AWSAccessKeyId' => -> { key },
|
160
|
-
'SignatureVersion' => '2',
|
161
|
-
'SignatureMethod' => 'HmacSHA256',
|
162
|
-
'Timestamp' => -> { Time.now.utc.iso8601 }
|
163
|
-
}
|
159
|
+
@params ||= {}
|
164
160
|
@params.update hsh if hsh
|
165
161
|
|
166
162
|
@params
|
data/lib/jeff/version.rb
CHANGED
data/spec/jeff_spec.rb
CHANGED
@@ -61,8 +61,8 @@ describe Jeff do
|
|
61
61
|
client.key = 'key'
|
62
62
|
end
|
63
63
|
|
64
|
-
describe '#
|
65
|
-
subject { client.
|
64
|
+
describe '#params' do
|
65
|
+
subject { client.params }
|
66
66
|
|
67
67
|
it 'should include the key' do
|
68
68
|
subject['AWSAccessKeyId'].should eql client.key
|
@@ -116,11 +116,13 @@ describe Jeff do
|
|
116
116
|
|
117
117
|
Excon::HTTP_VERBS.each do |method|
|
118
118
|
describe "##{method}" do
|
119
|
-
subject
|
119
|
+
subject do
|
120
|
+
client.send(method, mock: true).body
|
121
|
+
end
|
120
122
|
|
121
123
|
before do
|
122
124
|
Excon.stub({ method: method.to_sym }) do |params|
|
123
|
-
{ body:
|
125
|
+
{ body: method, status: 200 }
|
124
126
|
end
|
125
127
|
end
|
126
128
|
|
@@ -132,12 +134,12 @@ describe Jeff do
|
|
132
134
|
end
|
133
135
|
end
|
134
136
|
|
135
|
-
context 'given a
|
137
|
+
context 'given a temporary failure' do
|
136
138
|
before do
|
137
139
|
has_run = false
|
138
140
|
Excon.stub({ method: :get }) do |params|
|
139
141
|
if has_run
|
140
|
-
{ status: 200 }
|
142
|
+
{ body: 'ok', status: 200 }
|
141
143
|
else
|
142
144
|
has_run = true
|
143
145
|
raise Excon::Errors::SocketError.new Exception.new 'Mock Error'
|
@@ -148,21 +150,7 @@ describe Jeff do
|
|
148
150
|
after { Excon.stubs.clear }
|
149
151
|
|
150
152
|
it 'should retry' do
|
151
|
-
client.get(mock: true).
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
context 'given a malformed XML' do
|
156
|
-
before do
|
157
|
-
Excon.stub({ method: :get }) do |params|
|
158
|
-
{ body: "\n<?xml version=\"1.0\" ?><foo/>" }
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
after { Excon.stubs.clear }
|
163
|
-
|
164
|
-
it 'should not raise an error' do
|
165
|
-
client.get mock: true
|
153
|
+
client.get(mock: true).body.should eq 'ok'
|
166
154
|
end
|
167
155
|
end
|
168
156
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jeff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: excon
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 0.15.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,23 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: nokogiri
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ~>
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: '1.5'
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '1.5'
|
29
|
+
version: 0.15.0
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
31
|
name: guard-rspec
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,20 +89,14 @@ files:
|
|
105
89
|
- LICENSE
|
106
90
|
- README.md
|
107
91
|
- Rakefile
|
108
|
-
- examples/amazon.yml.example
|
109
|
-
- examples/debug.rb
|
110
92
|
- jeff.gemspec
|
111
93
|
- lib/jeff.rb
|
112
|
-
- lib/jeff/document.rb
|
113
94
|
- lib/jeff/secret.rb
|
114
|
-
- lib/jeff/streamer.rb
|
115
95
|
- lib/jeff/version.rb
|
116
|
-
- spec/jeff/document_spec.rb
|
117
96
|
- spec/jeff/secret_spec.rb
|
118
|
-
- spec/jeff/streamer_spec.rb
|
119
97
|
- spec/jeff_spec.rb
|
120
98
|
- spec/spec_helper.rb
|
121
|
-
homepage: https://github.com/
|
99
|
+
homepage: https://github.com/papercavalier/jeff
|
122
100
|
licenses: []
|
123
101
|
post_install_message:
|
124
102
|
rdoc_options: []
|
@@ -130,12 +108,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
130
108
|
- - ! '>='
|
131
109
|
- !ruby/object:Gem::Version
|
132
110
|
version: '0'
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
hash: -177229951203254918
|
133
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
115
|
none: false
|
135
116
|
requirements:
|
136
117
|
- - ! '>='
|
137
118
|
- !ruby/object:Gem::Version
|
138
119
|
version: '0'
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
hash: -177229951203254918
|
139
123
|
requirements: []
|
140
124
|
rubyforge_project:
|
141
125
|
rubygems_version: 1.8.23
|
@@ -143,9 +127,6 @@ signing_key:
|
|
143
127
|
specification_version: 3
|
144
128
|
summary: AWS client
|
145
129
|
test_files:
|
146
|
-
- spec/jeff/document_spec.rb
|
147
130
|
- spec/jeff/secret_spec.rb
|
148
|
-
- spec/jeff/streamer_spec.rb
|
149
131
|
- spec/jeff_spec.rb
|
150
132
|
- spec/spec_helper.rb
|
151
|
-
has_rdoc:
|
data/examples/amazon.yml.example
DELETED
data/examples/debug.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
$:.unshift File.expand_path '../../lib', __FILE__
|
2
|
-
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
require 'jeff'
|
6
|
-
require 'pry'
|
7
|
-
require 'pry-doc'
|
8
|
-
|
9
|
-
class Client
|
10
|
-
include Jeff
|
11
|
-
|
12
|
-
params 'AssociateTag' => -> { tag },
|
13
|
-
'Service' => 'AWSECommerceService',
|
14
|
-
'Version' => '2011-08-01'
|
15
|
-
|
16
|
-
attr_accessor :tag
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
self.key = config['key']
|
20
|
-
self.secret = config['secret']
|
21
|
-
self.tag = config['tag']
|
22
|
-
self.endpoint = 'http://ecs.amazonaws.com/onca/xml'
|
23
|
-
end
|
24
|
-
|
25
|
-
def find(asins)
|
26
|
-
params = {
|
27
|
-
'Operation' => 'ItemLookup',
|
28
|
-
'ItemId' => Array(asins).join(',')
|
29
|
-
}
|
30
|
-
|
31
|
-
get query: params
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def config
|
37
|
-
@config ||= YAML.load_file File.expand_path '../amazon.yml', __FILE__
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
binding.pry
|
data/lib/jeff/document.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
|
-
module Jeff
|
4
|
-
class Document < Nokogiri::XML::SAX::Document
|
5
|
-
def characters(val)
|
6
|
-
val.strip!
|
7
|
-
unless val.empty?
|
8
|
-
(node['__content__'] ||= '') << val
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def end_element(key)
|
13
|
-
child = @stack.pop
|
14
|
-
|
15
|
-
if child.keys == ['__content__']
|
16
|
-
child = child['__content__']
|
17
|
-
end
|
18
|
-
|
19
|
-
case node[key]
|
20
|
-
when Array
|
21
|
-
node[key] << child
|
22
|
-
when Hash, String
|
23
|
-
node[key] = [node[key], child]
|
24
|
-
else
|
25
|
-
node[key] = child
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def start_element(key, attrs = [])
|
30
|
-
@stack << {}
|
31
|
-
attrs.each { |attr| node.store *attr }
|
32
|
-
end
|
33
|
-
|
34
|
-
def start_document
|
35
|
-
@stack = [{}]
|
36
|
-
end
|
37
|
-
|
38
|
-
def root
|
39
|
-
@stack.first
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def node
|
45
|
-
@stack.last
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
data/lib/jeff/streamer.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'jeff/document'
|
2
|
-
|
3
|
-
module Jeff
|
4
|
-
class Streamer
|
5
|
-
def initialize
|
6
|
-
@parser = Nokogiri::XML::SAX::PushParser.new Document.new
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(chunk, remaining_bytes, total_bytes)
|
10
|
-
@parser << chunk.sub(/^\n/, '')
|
11
|
-
@parser.finish if remaining_bytes == 0
|
12
|
-
end
|
13
|
-
|
14
|
-
def document
|
15
|
-
@parser.document
|
16
|
-
end
|
17
|
-
|
18
|
-
def root
|
19
|
-
document.root
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/spec/jeff/document_spec.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Jeff
|
4
|
-
describe Document do
|
5
|
-
let(:io) do
|
6
|
-
StringIO.new %{
|
7
|
-
<?xml version=\"1.0\" ?>
|
8
|
-
<ItemAttributes>
|
9
|
-
<Title>Anti-Oedipus</Title>
|
10
|
-
<Author>Gilles Deleuze</Author>
|
11
|
-
<Author>Felix Guattari</Author>
|
12
|
-
<Creator Role="Translator">Robert Hurley</Creator>
|
13
|
-
</ItemAttributes>
|
14
|
-
}.strip
|
15
|
-
end
|
16
|
-
|
17
|
-
let(:doc) { described_class.new }
|
18
|
-
let(:parser) { Nokogiri::XML::SAX::Parser.new doc }
|
19
|
-
|
20
|
-
before do
|
21
|
-
io.rewind
|
22
|
-
parser.parse io
|
23
|
-
end
|
24
|
-
|
25
|
-
describe '#root' do
|
26
|
-
subject { doc.root['ItemAttributes'] }
|
27
|
-
|
28
|
-
it { should be_a Hash }
|
29
|
-
|
30
|
-
it 'should handle only children' do
|
31
|
-
subject['Title'].should eql 'Anti-Oedipus'
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'should hande arrays' do
|
35
|
-
subject['Author'].should be_an Array
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'should handle attributes' do
|
39
|
-
creator = subject['Creator']
|
40
|
-
creator['Role'].should eql 'Translator'
|
41
|
-
creator['__content__'].should eql 'Robert Hurley'
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'should ignore space between tags' do
|
45
|
-
should_not have_key '__content__'
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/spec/jeff/streamer_spec.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Jeff
|
4
|
-
describe Streamer do
|
5
|
-
let(:streamer) { Streamer.new }
|
6
|
-
|
7
|
-
let(:xml) do
|
8
|
-
%{
|
9
|
-
<?xml version="1.0" ?>
|
10
|
-
<foo>
|
11
|
-
<bar>1</bar>
|
12
|
-
</foo>
|
13
|
-
}.strip.gsub />\s+</, '><'
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'should parse a stream' do
|
17
|
-
bytes_sent = 0
|
18
|
-
total_bytes = xml.size
|
19
|
-
|
20
|
-
xml.scan(/.{1,8}/m).each do |chunk|
|
21
|
-
bytes_sent += chunk.size
|
22
|
-
streamer.call chunk, total_bytes - bytes_sent, total_bytes
|
23
|
-
end
|
24
|
-
|
25
|
-
streamer.root.should have_key 'foo'
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|