tylerhunt-relax 0.0.5 → 0.1.1
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/LICENSE +1 -1
- data/README.rdoc +194 -0
- data/Rakefile +54 -0
- data/VERSION.yml +4 -0
- data/lib/relax.rb +15 -10
- data/lib/relax/action.rb +49 -0
- data/lib/relax/context.rb +41 -0
- data/lib/relax/contextable.rb +15 -0
- data/lib/relax/endpoint.rb +21 -0
- data/lib/relax/instance.rb +23 -0
- data/lib/relax/parameter.rb +19 -0
- data/lib/relax/performer.rb +47 -0
- data/lib/relax/service.rb +20 -87
- data/spec/relax/context_spec.rb +10 -0
- data/spec/relax/endpoint_spec.rb +99 -0
- data/spec/relax/integration_spec.rb +63 -0
- data/spec/relax/service_spec.rb +32 -0
- data/spec/services/flickr.rb +78 -0
- data/spec/services/service_with_custom_parser.rb +28 -0
- data/spec/spec_helper.rb +13 -0
- metadata +77 -38
- data/README +0 -171
- data/lib/relax/parsers.rb +0 -13
- data/lib/relax/parsers/base.rb +0 -34
- data/lib/relax/parsers/factory.rb +0 -43
- data/lib/relax/parsers/hpricot.rb +0 -145
- data/lib/relax/parsers/rexml.rb +0 -158
- data/lib/relax/query.rb +0 -46
- data/lib/relax/request.rb +0 -95
- data/lib/relax/response.rb +0 -78
- data/lib/relax/symbolic_hash.rb +0 -79
- data/spec/parsers/factory_spec.rb +0 -29
- data/spec/parsers/hpricot_spec.rb +0 -35
- data/spec/parsers/rexml_spec.rb +0 -40
- data/spec/query_spec.rb +0 -60
- data/spec/request_spec.rb +0 -108
- data/spec/response_spec.rb +0 -98
- data/spec/symbolic_hash_spec.rb +0 -67
@@ -0,0 +1,28 @@
|
|
1
|
+
class TestCustomParser
|
2
|
+
|
3
|
+
def initialize(options = {}, &block)
|
4
|
+
end
|
5
|
+
|
6
|
+
def parse(input)
|
7
|
+
'parsed'
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
class ServiceWithCustomParser < Relax::Service
|
13
|
+
endpoint "http://test.local/rest" do
|
14
|
+
|
15
|
+
action :test do
|
16
|
+
parser TestCustomParser do
|
17
|
+
element :status, :attribute => :stat
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
FakeWeb.register_uri(:get, 'http://test.local/rest', :string => <<-RESPONSE)
|
25
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
26
|
+
<test stat="ok">
|
27
|
+
</test>
|
28
|
+
RESPONSE
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
gem 'rspec', '~> 1.2.2'
|
6
|
+
require 'spec'
|
7
|
+
|
8
|
+
gem 'fakeweb', '~> 1.2.2'
|
9
|
+
require 'fakeweb'
|
10
|
+
|
11
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'relax')
|
12
|
+
require File.join(File.dirname(__FILE__), 'services', 'flickr')
|
13
|
+
require File.join(File.dirname(__FILE__), 'services', 'service_with_custom_parser')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tylerhunt-relax
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Hunt
|
@@ -9,17 +9,58 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-06-03 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: rest-client
|
17
|
+
type: :runtime
|
17
18
|
version_requirement:
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
19
20
|
requirements:
|
20
|
-
- -
|
21
|
+
- - ~>
|
21
22
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
23
|
+
version: 0.9.2
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: nokogiri
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.2.3
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: relief
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.0.3
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: jeweler
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.11.0
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.2.2
|
23
64
|
version:
|
24
65
|
description:
|
25
66
|
email: tyler@tylerhunt.com
|
@@ -28,36 +69,34 @@ executables: []
|
|
28
69
|
extensions: []
|
29
70
|
|
30
71
|
extra_rdoc_files:
|
31
|
-
- README
|
32
72
|
- LICENSE
|
73
|
+
- README.rdoc
|
33
74
|
files:
|
34
|
-
- lib/relax
|
35
|
-
- lib/relax/parsers
|
36
|
-
- lib/relax/parsers/base.rb
|
37
|
-
- lib/relax/parsers/factory.rb
|
38
|
-
- lib/relax/parsers/hpricot.rb
|
39
|
-
- lib/relax/parsers/rexml.rb
|
40
|
-
- lib/relax/parsers.rb
|
41
|
-
- lib/relax/query.rb
|
42
|
-
- lib/relax/request.rb
|
43
|
-
- lib/relax/response.rb
|
44
|
-
- lib/relax/service.rb
|
45
|
-
- lib/relax/symbolic_hash.rb
|
46
|
-
- lib/relax.rb
|
47
|
-
- spec/parsers/factory_spec.rb
|
48
|
-
- spec/parsers/hpricot_spec.rb
|
49
|
-
- spec/parsers/rexml_spec.rb
|
50
|
-
- spec/query_spec.rb
|
51
|
-
- spec/request_spec.rb
|
52
|
-
- spec/response_spec.rb
|
53
|
-
- spec/symbolic_hash_spec.rb
|
54
|
-
- README
|
55
75
|
- LICENSE
|
76
|
+
- README.rdoc
|
77
|
+
- Rakefile
|
78
|
+
- VERSION.yml
|
79
|
+
- lib/relax.rb
|
80
|
+
- lib/relax/action.rb
|
81
|
+
- lib/relax/context.rb
|
82
|
+
- lib/relax/contextable.rb
|
83
|
+
- lib/relax/endpoint.rb
|
84
|
+
- lib/relax/instance.rb
|
85
|
+
- lib/relax/parameter.rb
|
86
|
+
- lib/relax/performer.rb
|
87
|
+
- lib/relax/service.rb
|
88
|
+
- spec/relax/context_spec.rb
|
89
|
+
- spec/relax/endpoint_spec.rb
|
90
|
+
- spec/relax/integration_spec.rb
|
91
|
+
- spec/relax/service_spec.rb
|
92
|
+
- spec/services/flickr.rb
|
93
|
+
- spec/services/service_with_custom_parser.rb
|
94
|
+
- spec/spec_helper.rb
|
56
95
|
has_rdoc: true
|
57
|
-
homepage: http://
|
96
|
+
homepage: http://github.com/tylerhunt/relax
|
58
97
|
post_install_message:
|
59
|
-
rdoc_options:
|
60
|
-
|
98
|
+
rdoc_options:
|
99
|
+
- --charset=UTF-8
|
61
100
|
require_paths:
|
62
101
|
- lib
|
63
102
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -78,12 +117,12 @@ rubyforge_project: relax
|
|
78
117
|
rubygems_version: 1.2.0
|
79
118
|
signing_key:
|
80
119
|
specification_version: 2
|
81
|
-
summary: A
|
120
|
+
summary: A flexible library for creating web service consumers.
|
82
121
|
test_files:
|
83
|
-
- spec/
|
84
|
-
- spec/
|
85
|
-
- spec/
|
86
|
-
- spec/
|
87
|
-
- spec/
|
88
|
-
- spec/
|
89
|
-
- spec/
|
122
|
+
- spec/relax/context_spec.rb
|
123
|
+
- spec/relax/endpoint_spec.rb
|
124
|
+
- spec/relax/integration_spec.rb
|
125
|
+
- spec/relax/service_spec.rb
|
126
|
+
- spec/services/flickr.rb
|
127
|
+
- spec/services/service_with_custom_parser.rb
|
128
|
+
- spec/spec_helper.rb
|
data/README
DELETED
@@ -1,171 +0,0 @@
|
|
1
|
-
= Relax
|
2
|
-
|
3
|
-
Relax is a simple library that provides a foundation for writing REST consumer
|
4
|
-
APIs, including the logic to handle the HTTP requests, build URLs with query
|
5
|
-
parameters, and parse XML responses.
|
6
|
-
|
7
|
-
It provides a basic set of functionality common to most REST consumers:
|
8
|
-
|
9
|
-
- building HTTP queries (Relax::Request)
|
10
|
-
- issuing HTTP requests (Relax::Service)
|
11
|
-
- parsing XML responses (Relax::Response)
|
12
|
-
|
13
|
-
|
14
|
-
== Tutorial
|
15
|
-
|
16
|
-
This short tutorial will walk you through the basic steps of creating a simple Flickr API that supports a single call to search for photos by tags.
|
17
|
-
|
18
|
-
=== Step 1
|
19
|
-
|
20
|
-
In the first step we're going to simply include Relax, and define the basis for
|
21
|
-
our Service class.
|
22
|
-
|
23
|
-
require 'rubygems'
|
24
|
-
require 'relax'
|
25
|
-
|
26
|
-
module Flickr
|
27
|
-
class Service < Relax::Service
|
28
|
-
ENDPOINT = 'http://api.flickr.com/services/rest/'
|
29
|
-
|
30
|
-
def initialize
|
31
|
-
super(ENDPOINT)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
=== Step 2
|
38
|
-
|
39
|
-
Next we're going to define common Request and Response classes for use
|
40
|
-
throughout our API. This gives us a single point to add any shared
|
41
|
-
functionality. For Flickr, this means that each request will have a "method"
|
42
|
-
parameter, and each response will have a "stat" attribute that will equal "ok"
|
43
|
-
when the response comes back without any errors.
|
44
|
-
|
45
|
-
module Flickr
|
46
|
-
class Request < Relax::Request
|
47
|
-
parameter :method
|
48
|
-
end
|
49
|
-
|
50
|
-
class Response < Relax::Response
|
51
|
-
def successful?
|
52
|
-
root[:stat] == 'ok'
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
While we're at it, we're also going to add a new line to the constructor from
|
58
|
-
our service to make sure that our Flickr API key gets passed along with each
|
59
|
-
request as well.
|
60
|
-
|
61
|
-
module Flickr
|
62
|
-
class Service < Relax::Service
|
63
|
-
ENDPOINT = 'http://api.flickr.com/services/rest/'
|
64
|
-
|
65
|
-
def initialize(api_key)
|
66
|
-
super(ENDPOINT)
|
67
|
-
Request[:api_key] = api_key
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
When we call our Request class as we have here, we're basically setting up a
|
73
|
-
value on our request that acts like a template. Each request we create now will
|
74
|
-
have the api_key property prepopulated for us.
|
75
|
-
|
76
|
-
|
77
|
-
=== Step 3
|
78
|
-
|
79
|
-
Next, we're going to need a basic Photo class to represent photos that Flickr
|
80
|
-
returns to us.
|
81
|
-
|
82
|
-
module Flickr
|
83
|
-
class Photo < Response
|
84
|
-
parameter :id, :attribute => true, :type => :integer
|
85
|
-
parameter :title, :attribute => true
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
Here we're creating a Response class that extends our Flickr::Response, which
|
90
|
-
has two parameters: "id" and "title." By setting the attribute option to true,
|
91
|
-
we're telling Relax to look for an attribute by that name on the XML root
|
92
|
-
instead of checking for an element by that name. The type options can be used
|
93
|
-
to specify what type of data we're expecting the response to give us. The
|
94
|
-
default type is string.
|
95
|
-
|
96
|
-
|
97
|
-
=== Step 4
|
98
|
-
|
99
|
-
Now we arrive at the final piece of the puzzle: a service call module. To keep
|
100
|
-
things contained, a Relax best practice is to create a module for each call
|
101
|
-
on your service. The one we're creating here is the PhotoSearch module for the
|
102
|
-
"flickr.photos.search" call on the Flickr API.
|
103
|
-
|
104
|
-
There are three main pieces to every service call module:
|
105
|
-
|
106
|
-
1. a Relax::Request object
|
107
|
-
2. a Relax::Response object
|
108
|
-
3. a call method that calls Relax::Service#call
|
109
|
-
|
110
|
-
Here's what the PhotoSearch module looks like:
|
111
|
-
|
112
|
-
module Flickr
|
113
|
-
module PhotoSearch
|
114
|
-
class PhotoSearchRequest < Flickr::Request
|
115
|
-
parameter :per_page
|
116
|
-
parameter :tags
|
117
|
-
|
118
|
-
def initialize(options = {})
|
119
|
-
super
|
120
|
-
@method = 'flickr.photos.search'
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
class PhotoSearchResponse < Flickr::Response
|
125
|
-
parameter :photos, :element => 'photos/photo', :collection => Photo
|
126
|
-
end
|
127
|
-
|
128
|
-
def search(options = {})
|
129
|
-
call(PhotoSearchRequest.new(options), PhotoSearchResponse)
|
130
|
-
end
|
131
|
-
|
132
|
-
def find_by_tag(tags, options = {})
|
133
|
-
search(options.merge(:tags => tags))
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
As you can see, we have our request (PhotoSearchRequest), response
|
139
|
-
(PhotoSearchResponse), and call method (actually, two in this case: search and
|
140
|
-
find_by_tag). This now needs to be included into our Flickr::Service class,
|
141
|
-
and then we'll be able to use it by calling either of the call methods.
|
142
|
-
|
143
|
-
module Flickr
|
144
|
-
class Service < Relax::Service
|
145
|
-
include Flickr::PhotoSearch
|
146
|
-
|
147
|
-
ENDPOINT = 'http://api.flickr.com/services/rest/'
|
148
|
-
|
149
|
-
def initialize(api_key)
|
150
|
-
super(ENDPOINT)
|
151
|
-
Request[:api_key] = api_key
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
Now we're ready to make a call against the API:
|
157
|
-
|
158
|
-
flickr = Flickr::Service.new(ENV['FLICKR_API_KEY'])
|
159
|
-
relax = flickr.find_by_tag('relax', :per_page => 10)
|
160
|
-
|
161
|
-
if relax.successful?
|
162
|
-
relax.photos.each do |photo|
|
163
|
-
puts "[#{photo.id}] #{photo.title}"
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
This will output the IDs and titles for the first 10 photos on Flickr that have
|
168
|
-
the tag "relax."
|
169
|
-
|
170
|
-
|
171
|
-
Copyright (c) 2007-2008 Tyler Hunt, released under the MIT license
|
data/lib/relax/parsers.rb
DELETED
data/lib/relax/parsers/base.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
module Relax
|
2
|
-
module Parsers
|
3
|
-
|
4
|
-
class Base
|
5
|
-
|
6
|
-
attr_reader :parent
|
7
|
-
attr_reader :parameters
|
8
|
-
|
9
|
-
def initialize(raw, parent)
|
10
|
-
@parent = parent
|
11
|
-
@parameters = parent.class.instance_variable_get('@parameters')
|
12
|
-
parse!
|
13
|
-
end
|
14
|
-
|
15
|
-
def parse!; end
|
16
|
-
|
17
|
-
def root; end
|
18
|
-
def is?(name); end
|
19
|
-
def has?(name); end
|
20
|
-
def element(name); end
|
21
|
-
def elements(name); end
|
22
|
-
|
23
|
-
def attribute(element, name); end
|
24
|
-
def value(value); end
|
25
|
-
def text_value(value); end
|
26
|
-
def integer_value(value); end
|
27
|
-
def float_value(value); end
|
28
|
-
def date_value(value); end
|
29
|
-
def time_value(value); end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
module Relax
|
2
|
-
module Parsers
|
3
|
-
|
4
|
-
##
|
5
|
-
# Manages the Relax::Parsers in the library.
|
6
|
-
#
|
7
|
-
module Factory
|
8
|
-
|
9
|
-
class << self
|
10
|
-
|
11
|
-
##
|
12
|
-
# Returns the parser class which has been registered for the given
|
13
|
-
# +name+.
|
14
|
-
#
|
15
|
-
def get(name)
|
16
|
-
@@parsers ||= {}
|
17
|
-
@@parsers[name] || raise(UnrecognizedParser, "Given parser name not recognized: #{name.inspect}. Expected one of: #{@@parsers.keys.inspect}")
|
18
|
-
end
|
19
|
-
|
20
|
-
##
|
21
|
-
# Registers a new parser with the factory. The +name+ should be unique,
|
22
|
-
# but if not, it will override the previously defined parser for the
|
23
|
-
# given +name+.
|
24
|
-
#
|
25
|
-
def register(name, klass)
|
26
|
-
@@parsers ||= {}
|
27
|
-
@@parsers[:default] = klass if @@parsers.empty?
|
28
|
-
@@parsers[name] = klass
|
29
|
-
end
|
30
|
-
|
31
|
-
##
|
32
|
-
# Removes all registered parsers from the factory.
|
33
|
-
#
|
34
|
-
def clear!
|
35
|
-
@@parsers = {}
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|