mwunsch-weary 0.1.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/LICENSE +20 -0
- data/README.md +5 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/lib/weary/exceptions.rb +3 -0
- data/lib/weary/request.rb +80 -0
- data/lib/weary/resource.rb +74 -0
- data/lib/weary/response.rb +109 -0
- data/lib/weary.rb +150 -0
- data/spec/weary/request_spec.rb +26 -0
- data/spec/weary_spec.rb +140 -0
- metadata +65 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Mark Wunsch
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
# Weary
|
2
|
+
|
3
|
+
_The Weary need REST_
|
4
|
+
|
5
|
+
Weary is a tiny little DSL for making the consumption of RESTful web services simple. It is the little brother to [HTTParty](http://github.com/jnunemaker/httparty/ "JNunemaker's HTTParty"). It provides a thin, gossamer-like layer over the Net/HTTP library.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
|
4
|
+
task :default => :spec
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gemspec|
|
9
|
+
gemspec.name = "weary"
|
10
|
+
gemspec.summary = "A little DSL for consuming RESTful web services"
|
11
|
+
gemspec.email = "mark@markwunsch.com"
|
12
|
+
gemspec.homepage = "http://github.com/mwunsch/weary"
|
13
|
+
gemspec.description = "The Weary need REST: a tiny DSL that makes the consumption of RESTful web services simple."
|
14
|
+
gemspec.authors = "Mark Wunsch"
|
15
|
+
gemspec.has_rdoc = false
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
Spec::Rake::SpecTask.new do |t|
|
24
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
t.spec_opts = ['--color','--format nested']
|
26
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Weary
|
2
|
+
class Request
|
3
|
+
|
4
|
+
attr_reader :uri
|
5
|
+
attr_accessor :options
|
6
|
+
|
7
|
+
def initialize(url, http_verb= :get, options={})
|
8
|
+
self.method = http_verb
|
9
|
+
self.uri = url
|
10
|
+
self.options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def uri=(url)
|
14
|
+
@uri = URI.parse(url)
|
15
|
+
end
|
16
|
+
|
17
|
+
def method=(http_verb)
|
18
|
+
@http_verb = case http_verb
|
19
|
+
when *Methods[:get]
|
20
|
+
:get
|
21
|
+
when *Methods[:post]
|
22
|
+
:post
|
23
|
+
when *Methods[:put]
|
24
|
+
:put
|
25
|
+
when *Methods[:delete]
|
26
|
+
:delete
|
27
|
+
when *Methods[:head]
|
28
|
+
:head
|
29
|
+
else
|
30
|
+
raise ArgumentError, "Only GET, POST, PUT, DELETE, and HEAD methods are supported"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def method
|
35
|
+
@http_verb
|
36
|
+
end
|
37
|
+
|
38
|
+
def perform
|
39
|
+
req = http.request(request)
|
40
|
+
response = Response.new(req, @http_verb)
|
41
|
+
unless options[:no_follow]
|
42
|
+
if response.redirected?
|
43
|
+
response.follow_redirect
|
44
|
+
else
|
45
|
+
response
|
46
|
+
end
|
47
|
+
else
|
48
|
+
response
|
49
|
+
end
|
50
|
+
end
|
51
|
+
alias make perform
|
52
|
+
|
53
|
+
private
|
54
|
+
def http
|
55
|
+
connection = Net::HTTP.new(@uri.host, @uri.port)
|
56
|
+
connection.use_ssl = @uri.is_a?(URI::HTTPS)
|
57
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE if connection.use_ssl
|
58
|
+
connection
|
59
|
+
end
|
60
|
+
|
61
|
+
def request
|
62
|
+
prepare = case @http_verb
|
63
|
+
when :get
|
64
|
+
Net::HTTP::Get.new(@uri.request_uri)
|
65
|
+
when :post
|
66
|
+
Net::HTTP::Post.new(@uri.request_uri)
|
67
|
+
when :put
|
68
|
+
Net::HTTP::Put.new(@uri.request_uri)
|
69
|
+
when :delete
|
70
|
+
Net::HTTP::Delete.new(@uri.request_uri)
|
71
|
+
when :head
|
72
|
+
Net::HTTP::Head.new(@uri.request_uri)
|
73
|
+
end
|
74
|
+
prepare.body = options[:body].is_a?(Hash) ? options[:body].to_params : options[:body] if options[:body]
|
75
|
+
prepare.basic_auth(options[:basic_auth][:username], options[:basic_auth][:password]) if options[:basic_auth]
|
76
|
+
prepare
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Weary
|
2
|
+
class Resource
|
3
|
+
attr_reader :name, :with, :requires, :via, :format, :url
|
4
|
+
|
5
|
+
def initialize(name,options={})
|
6
|
+
@domain = options[:domain]
|
7
|
+
self.name = name
|
8
|
+
self.via = options[:via]
|
9
|
+
self.with = options[:with]
|
10
|
+
self.requires = options[:requires]
|
11
|
+
self.format = options[:format]
|
12
|
+
self.url = options[:url]
|
13
|
+
@authenticates = (options[:authenticates] != false)
|
14
|
+
@follows = (options[:no_follow] == false)
|
15
|
+
end
|
16
|
+
|
17
|
+
def name=(resource)
|
18
|
+
@name = resource.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def via=(verb)
|
22
|
+
@via = verb
|
23
|
+
end
|
24
|
+
|
25
|
+
def with=(params)
|
26
|
+
if params.empty?
|
27
|
+
@with = nil
|
28
|
+
else
|
29
|
+
@with = params.collect {|x| x.to_sym }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def url=(pattern)
|
34
|
+
if pattern.index("<domain>")
|
35
|
+
raise StandardError, "Domain flag found but the domain is not defined" if @domain.nil?
|
36
|
+
pattern = pattern.gsub("<domain>", @domain)
|
37
|
+
end
|
38
|
+
pattern = pattern.gsub("<resource>", @name)
|
39
|
+
pattern = pattern.gsub("<format>", @format.to_s)
|
40
|
+
@url = pattern
|
41
|
+
end
|
42
|
+
|
43
|
+
def requires=(params)
|
44
|
+
if (params.nil? || params.empty?)
|
45
|
+
@requires = nil
|
46
|
+
else
|
47
|
+
@requires = params
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def format=(type)
|
52
|
+
@format = type
|
53
|
+
end
|
54
|
+
|
55
|
+
def authenticates?
|
56
|
+
@authenticates
|
57
|
+
end
|
58
|
+
|
59
|
+
def follows_redirects?
|
60
|
+
@follows
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_hash
|
64
|
+
{@name.to_sym => {:via => @via,
|
65
|
+
:with => @with,
|
66
|
+
:requires => @requires,
|
67
|
+
:authenticates => authenticates?,
|
68
|
+
:format => @format,
|
69
|
+
:url => @url},
|
70
|
+
:no_follow => !follows_redirects?}
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Weary
|
2
|
+
class Response
|
3
|
+
|
4
|
+
attr_reader :raw, :method, :code, :message, :header, :content_type, :cookie, :body
|
5
|
+
alias mime_type content_type
|
6
|
+
|
7
|
+
def initialize(http_response, http_method)
|
8
|
+
raise ArgumentError, "Must be a Net::HTTPResponse" unless http_response.is_a?(Net::HTTPResponse)
|
9
|
+
@raw = http_response
|
10
|
+
@method = http_method
|
11
|
+
@code = http_response.code.to_i
|
12
|
+
@message = http_response.message
|
13
|
+
@header = http_response.to_hash
|
14
|
+
@content_type = http_response.content_type
|
15
|
+
@cookie = http_response['Set-Cookie']
|
16
|
+
@body = http_response.body
|
17
|
+
self.format = http_response.content_type
|
18
|
+
end
|
19
|
+
|
20
|
+
def redirected?
|
21
|
+
@raw.is_a?(Net::HTTPRedirection)
|
22
|
+
end
|
23
|
+
|
24
|
+
def success?
|
25
|
+
(200..299).include?(@code)
|
26
|
+
end
|
27
|
+
|
28
|
+
def format=(type)
|
29
|
+
@format = case type
|
30
|
+
when 'text/xml', 'application/xml'
|
31
|
+
:xml
|
32
|
+
when 'application/json', 'text/json', 'application/javascript', 'text/javascript'
|
33
|
+
:json
|
34
|
+
when 'text/html'
|
35
|
+
:html
|
36
|
+
when 'application/x-yaml', 'text/yaml'
|
37
|
+
:yaml
|
38
|
+
when 'text/plain'
|
39
|
+
:plain
|
40
|
+
else
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def format
|
46
|
+
@format
|
47
|
+
end
|
48
|
+
|
49
|
+
def follow_redirect
|
50
|
+
if redirected?
|
51
|
+
Request.new(@raw['location'], @method).perform
|
52
|
+
else
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse
|
58
|
+
raise StandardError, "The Response has no body. #{@method.to_s.upcase} request sent." unless @body
|
59
|
+
handle_errors
|
60
|
+
case @format
|
61
|
+
when :xml, :html
|
62
|
+
Crack::XML.parse @body
|
63
|
+
when :json
|
64
|
+
Crack::JSON.parse @body
|
65
|
+
when :yaml
|
66
|
+
YAML::load @body
|
67
|
+
else
|
68
|
+
@body
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def search(selector)
|
73
|
+
raise ArgumentError, "Search can only be used with an XML or HTML document." unless @format != (:xml || :html)
|
74
|
+
doc = Nokogiri.parse(@body)
|
75
|
+
doc.search(selector)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
def handle_errors
|
80
|
+
case @code
|
81
|
+
when 301,302
|
82
|
+
raise HTTPError, "#{@message} to #{@raw['location']}"
|
83
|
+
when 200...400
|
84
|
+
return
|
85
|
+
when 400
|
86
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
87
|
+
when 401
|
88
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
89
|
+
when 403
|
90
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
91
|
+
when 404
|
92
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
93
|
+
when 405
|
94
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
95
|
+
when 409
|
96
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
97
|
+
when 422
|
98
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
99
|
+
when 401...500
|
100
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
101
|
+
when 500...600
|
102
|
+
raise HTTPError, "Failed with #{@code}: #{@message}"
|
103
|
+
else
|
104
|
+
raise HTTPError, "Unknown response code: #{@code}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
data/lib/weary.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'net/http'
|
5
|
+
require 'net/https'
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'crack'
|
9
|
+
|
10
|
+
gem 'nokogiri'
|
11
|
+
autoload :Yaml, 'yaml'
|
12
|
+
autoload :Nokogiri, 'nokogiri'
|
13
|
+
|
14
|
+
require 'weary/request'
|
15
|
+
require 'weary/response'
|
16
|
+
require 'weary/resource'
|
17
|
+
require 'weary/exceptions'
|
18
|
+
|
19
|
+
|
20
|
+
module Weary
|
21
|
+
|
22
|
+
Methods = { :get => [:get, :GET, /\bget\b/i],
|
23
|
+
:post => [:post, :POST, /\bpost\b/i],
|
24
|
+
:put => [:put, :PUT, /\bput\b/i],
|
25
|
+
:delete => [:delete, :del, :DELETE, :DEL, /\bdelete\b/i],
|
26
|
+
:head => [:head, :HEAD, /\bhead\b/i] }
|
27
|
+
|
28
|
+
# Weary::Query quickly performs a :get request on a URL and parses the request
|
29
|
+
def self.Query(url)
|
30
|
+
req = Weary::Request.new(url, :get).perform
|
31
|
+
req.parse
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :domain, :resources
|
35
|
+
|
36
|
+
def on_domain(domain)
|
37
|
+
parse_domain = URI.extract(domain)
|
38
|
+
raise ArgumentError, 'The domain must be a URL.' if parse_domain.empty?
|
39
|
+
@domain = parse_domain[0]
|
40
|
+
end
|
41
|
+
alias domain= on_domain
|
42
|
+
|
43
|
+
def as_format(format)
|
44
|
+
@default_format = format.to_sym
|
45
|
+
end
|
46
|
+
alias format= as_format
|
47
|
+
|
48
|
+
def construct_url(pattern)
|
49
|
+
@url_pattern = pattern.to_s
|
50
|
+
end
|
51
|
+
alias url= construct_url
|
52
|
+
|
53
|
+
def authenticates_with(username,password)
|
54
|
+
@username = username
|
55
|
+
@password = password
|
56
|
+
return nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def declare_resource(resource, options={})
|
60
|
+
# available options:
|
61
|
+
# :via = get, post, etc. defaults to get
|
62
|
+
# :with = paramaters passed to body or query
|
63
|
+
# :requires = members of :with that must be in the action
|
64
|
+
# :authenticates = boolean; uses basic_authentication
|
65
|
+
# :url = a pattern
|
66
|
+
# :format = to set format, defaults to :json
|
67
|
+
# :no_follow = boolean; defaults to false. do not follow redirects
|
68
|
+
|
69
|
+
|
70
|
+
@resources ||= []
|
71
|
+
|
72
|
+
r = Weary::Resource.new(resource, set_defaults(options))
|
73
|
+
declaration = r.to_hash
|
74
|
+
|
75
|
+
@resources << declaration
|
76
|
+
|
77
|
+
craft_methods(r)
|
78
|
+
return declaration
|
79
|
+
end
|
80
|
+
|
81
|
+
def get(resource,options={})
|
82
|
+
options[:via] = :get
|
83
|
+
declare_resource(resource,options)
|
84
|
+
end
|
85
|
+
|
86
|
+
def post(resource,options={})
|
87
|
+
options[:via] = :post
|
88
|
+
declare_resource(resource,options)
|
89
|
+
end
|
90
|
+
|
91
|
+
def put(resource,options={})
|
92
|
+
options[:via] = :put
|
93
|
+
declare_resource(resource,options)
|
94
|
+
end
|
95
|
+
|
96
|
+
def delete(resource,options={})
|
97
|
+
options[:via] = :delete
|
98
|
+
declare_resource(resource,options)
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
def set_defaults(hash)
|
103
|
+
hash[:domain] = @domain
|
104
|
+
hash[:via] ||= :get
|
105
|
+
hash[:with] ||= []
|
106
|
+
hash[:with] = hash[:with] | hash[:requires] unless hash[:requires].nil?
|
107
|
+
hash[:format] ||= (@default_format || :json)
|
108
|
+
hash[:authenticates] ||= false
|
109
|
+
hash[:authenticates] = false if hash[:authenticates] == "false"
|
110
|
+
if hash[:authenticates]
|
111
|
+
raise StandardError, "Can not authenticate unless username and password are defined" unless (@username && @password)
|
112
|
+
end
|
113
|
+
hash[:url] ||= (@url_pattern || "<domain><resource>.<format>")
|
114
|
+
hash[:no_follow] ||= false
|
115
|
+
return hash
|
116
|
+
end
|
117
|
+
|
118
|
+
def craft_methods(resource)
|
119
|
+
code = %Q{
|
120
|
+
def #{resource.name}(params={})
|
121
|
+
options ||= {}
|
122
|
+
url = "#{resource.url}"
|
123
|
+
}
|
124
|
+
unless resource.requires.nil?
|
125
|
+
resource.requires.each do |required|
|
126
|
+
code << %Q{raise ArgumentError, "This resource requires parameter: ':#{required}'" unless params.has_key?(:#{required}) \n}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
unless resource.with.nil?
|
130
|
+
with = %Q\[#{resource.with.collect {|x| ":#{x}"}.join(',')}]\
|
131
|
+
code << "unnecessary = params.keys - #{with} \n"
|
132
|
+
code << "unnecessary.each { |x| params.delete(x) } \n"
|
133
|
+
end
|
134
|
+
if resource.via == (:post || :put)
|
135
|
+
code << "options[:body] = params unless params.empty? \n"
|
136
|
+
else
|
137
|
+
code << "options[:query] = params unless params.empty? \n"
|
138
|
+
code << %Q{url << "?" + options[:query].to_params unless options[:query].nil? \n}
|
139
|
+
end
|
140
|
+
if resource.authenticates?
|
141
|
+
code << %Q{options[:basic_auth] = {:username => "#{@username}", :password => "#{@password}"} \n}
|
142
|
+
end
|
143
|
+
code << %Q{
|
144
|
+
Weary::Request.new(url, :#{resource.via}, options).perform
|
145
|
+
end
|
146
|
+
}
|
147
|
+
class_eval code
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'rspec'
|
3
|
+
require 'spec'
|
4
|
+
require File.join(File.dirname(__FILE__), '../..', 'lib', 'weary')
|
5
|
+
|
6
|
+
describe Weary::Request do
|
7
|
+
|
8
|
+
it "should contain a url" do
|
9
|
+
test = Weary::Request.new("http://google.com")
|
10
|
+
test.uri.is_a?(URI).should == true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should parse the http method" do
|
14
|
+
test = Weary::Request.new("http://google.com", "POST")
|
15
|
+
test.method.should == :post
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should craft a Net/HTTP Request" do
|
19
|
+
test = Weary::Request.new("http://google.com").send :http
|
20
|
+
test.class.should == Net::HTTP
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should follow redirects" do
|
24
|
+
pending "Not sure how to test this"
|
25
|
+
end
|
26
|
+
end
|
data/spec/weary_spec.rb
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'rspec'
|
3
|
+
require 'spec'
|
4
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'weary')
|
5
|
+
|
6
|
+
describe Weary do
|
7
|
+
before do
|
8
|
+
@test = Class.new
|
9
|
+
@test.instance_eval { extend Weary }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "default domain" do
|
13
|
+
it 'should be set with a url' do
|
14
|
+
@test.on_domain("http://twitter.com/")
|
15
|
+
@test.domain.should == "http://twitter.com/"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should also be set by it's alias" do
|
19
|
+
@test.domain = "http://twitter.com/"
|
20
|
+
@test.domain.should == "http://twitter.com/"
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should raise an exception when a url is not present' do
|
24
|
+
lambda { @test.on_domain("foobar") }.should raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should only take the first url given' do
|
28
|
+
@test.on_domain("with http://google.com/ and http://yahoo.com/")
|
29
|
+
@test.domain.should == "http://google.com/"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "default format" do
|
34
|
+
it 'can be set' do
|
35
|
+
@test.as_format("xml")
|
36
|
+
@test.instance_variable_defined?(:@default_format).should == true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should also be set by it's alias" do
|
40
|
+
@test.format = "xml"
|
41
|
+
@test.instance_variable_defined?(:@default_format).should == true
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should be a symbol' do
|
45
|
+
@test.as_format("xml")
|
46
|
+
@test.instance_variable_get(:@default_format).class.should == Symbol
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "default url pattern" do
|
51
|
+
it 'can be set' do
|
52
|
+
@test.construct_url("<domain><resource>.<format>")
|
53
|
+
@test.instance_variable_defined?(:@url_pattern).should == true
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should also be set by it's alias" do
|
57
|
+
@test.url = "<domain><resource>.<format>"
|
58
|
+
@test.instance_variable_defined?(:@url_pattern).should == true
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should be a string' do
|
62
|
+
@test.construct_url(123)
|
63
|
+
@test.instance_variable_get(:@url_pattern).class.should == String
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "basic authentication credentials" do
|
68
|
+
it "should accept a username and password" do
|
69
|
+
@test.authenticates_with("foo","bar")
|
70
|
+
@test.instance_variable_get(:@username).should == "foo"
|
71
|
+
@test.instance_variable_get(:@password).should == "bar"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "resource declaration" do
|
76
|
+
before do
|
77
|
+
@test.domain = "http://twitter.com/"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should adds a new resource" do
|
81
|
+
@test.declare_resource("resource")
|
82
|
+
@test.resources[0].has_key?(:resource).should == true
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should default to a GET request" do
|
86
|
+
@test.declare_resource("resource")[:resource][:via].should == :get
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should default to JSON if no format is defined" do
|
90
|
+
@test.declare_resource("resource")[:resource][:format].should == :json
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should use the declared format, if a specific format is not defined" do
|
94
|
+
@test.format = :xml
|
95
|
+
@test.declare_resource("resource")[:resource][:format].should == :xml
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should override the default format with it's own format" do
|
99
|
+
@test.format = :xml
|
100
|
+
@test.declare_resource("resource",{:format => :yaml})[:resource][:format].should == :yaml
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should form a url if there is a default pattern" do
|
104
|
+
@test.declare_resource("resource")[:resource][:url].should == "http://twitter.com/resource.json"
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should override the default pattern with it's own url" do
|
108
|
+
@test.declare_resource("resource",{:url => "http://foobar.com/<resource>"})[:resource][:url].should == "http://foobar.com/resource"
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should be able to contain a set of allowed parameters" do
|
112
|
+
@test.declare_resource("resource",{:with => [:id]})[:resource][:with].empty?.should == false
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should be able to contain a set of required parameters" do
|
116
|
+
@test.declare_resource("resource",{:requires => [:id]})[:resource][:requires].empty?.should == false
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should merge required parameters into allowed parameters" do
|
120
|
+
@test.declare_resource("resource",{:requires => [:id]})[:resource][:with].empty?.should == false
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should authenticate with username and password" do
|
124
|
+
@test.authenticates_with("foo","bar")
|
125
|
+
@test.declare_resource("resource",{:authenticates => true})[:resource][:authenticates].should == true
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should raise an exception if authentication is required but no credentials are supplied" do
|
129
|
+
lambda do
|
130
|
+
@test.declare_resource("resource",{:authenticates => true})
|
131
|
+
end.should raise_error
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should create a method for an instantiated object" do
|
135
|
+
@test.declare_resource("resource")
|
136
|
+
@test.public_method_defined?(:resource).should == true
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mwunsch-weary
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Wunsch
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-08 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: "The Weary need REST: a tiny DSL that makes the consumption of RESTful web services simple."
|
17
|
+
email: mark@markwunsch.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README.md
|
28
|
+
- Rakefile
|
29
|
+
- VERSION
|
30
|
+
- lib/weary.rb
|
31
|
+
- lib/weary/exceptions.rb
|
32
|
+
- lib/weary/request.rb
|
33
|
+
- lib/weary/resource.rb
|
34
|
+
- lib/weary/response.rb
|
35
|
+
- spec/weary/request_spec.rb
|
36
|
+
- spec/weary_spec.rb
|
37
|
+
has_rdoc: false
|
38
|
+
homepage: http://github.com/mwunsch/weary
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --charset=UTF-8
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.2.0
|
60
|
+
signing_key:
|
61
|
+
specification_version: 2
|
62
|
+
summary: A little DSL for consuming RESTful web services
|
63
|
+
test_files:
|
64
|
+
- spec/weary/request_spec.rb
|
65
|
+
- spec/weary_spec.rb
|