evoke_client 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.markdown +34 -0
- data/Rakefile +17 -0
- data/evoke_client.gemspec +35 -0
- data/lib/evoke_client.rb +33 -0
- data/lib/evoke_client/base.rb +23 -0
- data/lib/evoke_client/stub.rb +7 -0
- data/lib/query_string.rb +16 -0
- data/shoulda_macros/rest_client.rb +16 -0
- data/test/evoke_client_test.rb +104 -0
- data/test/test_helper.rb +11 -0
- metadata +75 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Justin Knowlden, Thumble Monks
|
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.markdown
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Evoke Client
|
2
|
+
|
3
|
+
evoke-client is a simple rest-client utility for allowing your application to converse with the [Evoke Service](http://evoke.thumblemonks.com). The source code for [Evoke can be found on GitHub](http://github.com/thumblemonks/evoke) along with what Evoke is intended for.
|
4
|
+
|
5
|
+
### Usage
|
6
|
+
|
7
|
+
evoke = Evoke.new(:url => 'http://example.com/users/unsubscribe', :callback_at => (Time.now + 86400))
|
8
|
+
evoke.save
|
9
|
+
|
10
|
+
# What happens if save fails
|
11
|
+
|
12
|
+
### Configuration
|
13
|
+
|
14
|
+
By default, evoke-client tries to talk to the Evoke service, generously hosted by Thumble Monks :) Because Evoke itself is open source and able to be run by you anywhere you want it to, the only real configuration parameters are for the hostname and port that you want evoke-client to talk to Evoke on. For instance, when we use Evoke in our projects, we may want to test with a local instance while doing development.
|
15
|
+
|
16
|
+
To modify host and port, just set the following:
|
17
|
+
|
18
|
+
Evoke.host = "example.com"
|
19
|
+
Evoke.port = "4567"
|
20
|
+
# Choosing 4567 because Evoke is written for Sinatra
|
21
|
+
|
22
|
+
### Installation
|
23
|
+
|
24
|
+
gem install thumblemonks-evoke_client
|
25
|
+
|
26
|
+
#### Dependencies
|
27
|
+
|
28
|
+
These should be automatically installed when you install evoke_client
|
29
|
+
|
30
|
+
* [rest-client](http://github.com/adamwiggins/rest-client)
|
31
|
+
|
32
|
+
## License
|
33
|
+
|
34
|
+
MIT, baby! (see file named MIT-LICENSE)
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
desc 'Default task: run all tests'
|
6
|
+
task :default => [:test]
|
7
|
+
|
8
|
+
task(:set_test_env) { ENV['APP_ENV'] ||= 'test' }
|
9
|
+
|
10
|
+
task(:environment) { }
|
11
|
+
|
12
|
+
task :test => [:set_test_env]
|
13
|
+
desc 'Run all tests'
|
14
|
+
Rake::TestTask.new do |t|
|
15
|
+
t.test_files = FileList['test/*_test.rb']
|
16
|
+
t.verbose = true
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "evoke_client"
|
3
|
+
s.version = "0.2.0"
|
4
|
+
s.date = "2009-06-07"
|
5
|
+
s.summary = "Rest client interface for talking REST to the evoke service"
|
6
|
+
s.email = %w[gus@gusg.us]
|
7
|
+
s.homepage = "http://github.com/thumblemonks/evoke_client"
|
8
|
+
s.description = "Rest client interface for talking REST to the evoke service"
|
9
|
+
s.authors = %w[Justin\ Knowlden]
|
10
|
+
s.post_install_message = %q{Choosy wizards choose Thumble Monks.}
|
11
|
+
|
12
|
+
s.has_rdoc = false
|
13
|
+
s.rdoc_options = ["--main", "README.markdown"]
|
14
|
+
s.extra_rdoc_files = ["README.markdown"]
|
15
|
+
|
16
|
+
s.add_dependency("rest-client", [">= 0.9.2"])
|
17
|
+
|
18
|
+
# run git ls-files to get an updated list
|
19
|
+
s.files = %w[
|
20
|
+
MIT-LICENSE
|
21
|
+
README.markdown
|
22
|
+
Rakefile
|
23
|
+
evoke_client.gemspec
|
24
|
+
lib/evoke_client.rb
|
25
|
+
lib/evoke_client/base.rb
|
26
|
+
lib/evoke_client/stub.rb
|
27
|
+
lib/query_string.rb
|
28
|
+
shoulda_macros/rest_client.rb
|
29
|
+
]
|
30
|
+
|
31
|
+
s.test_files = %w[
|
32
|
+
test/evoke_client_test.rb
|
33
|
+
test/test_helper.rb
|
34
|
+
]
|
35
|
+
end
|
data/lib/evoke_client.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'query_string'
|
2
|
+
require 'evoke_client/base'
|
3
|
+
require 'evoke_client/stub'
|
4
|
+
|
5
|
+
class Evoke
|
6
|
+
class ConnectionRefused < Exception; end
|
7
|
+
|
8
|
+
# Configuration
|
9
|
+
|
10
|
+
def self.test?; @test == true; end
|
11
|
+
def self.test=(setting) @test = setting; end
|
12
|
+
|
13
|
+
def self.host; @host || 'evoke.thumblemonks.com'; end
|
14
|
+
def self.host=(host) @host = host; end
|
15
|
+
|
16
|
+
def self.port; @port; end
|
17
|
+
def self.port=(port) @port = port; end
|
18
|
+
|
19
|
+
def self.host_and_port
|
20
|
+
[host, port].compact.join(':')
|
21
|
+
end
|
22
|
+
|
23
|
+
# Logic
|
24
|
+
|
25
|
+
def self.create_or_update!(*args)
|
26
|
+
prepare(*args).save
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.prepare(*args)
|
30
|
+
(test? ? EvokeClient::Stub : EvokeClient::Base).new(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'restclient'
|
2
|
+
|
3
|
+
module EvokeClient
|
4
|
+
class Base
|
5
|
+
attr_reader :params, :headers
|
6
|
+
|
7
|
+
def initialize(params={})
|
8
|
+
@evoke = ::RestClient::Resource.new("http://#{Evoke.host_and_port}/callbacks")
|
9
|
+
@params = params
|
10
|
+
@params[:callback_at] = @params[:callback_at].utc if @params[:callback_at]
|
11
|
+
@params[:data] = @params[:data].to_query_string if @params[:data]
|
12
|
+
end
|
13
|
+
|
14
|
+
def save
|
15
|
+
@evoke[params[:guid]].get
|
16
|
+
@evoke[params[:guid]].put(@params)
|
17
|
+
rescue ::RestClient::ResourceNotFound
|
18
|
+
@evoke.post(@params)
|
19
|
+
rescue Errno::ECONNREFUSED
|
20
|
+
raise Evoke::ConnectionRefused, "Connection refused while connecting to #{Evoke.host_and_port}"
|
21
|
+
end
|
22
|
+
end # Base
|
23
|
+
end # EvokeClient
|
data/lib/query_string.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module EvokeClient
|
2
|
+
module Hash
|
3
|
+
def to_query_string
|
4
|
+
map do |key, val|
|
5
|
+
"#{key}=#{val}"
|
6
|
+
end.join('&')
|
7
|
+
end
|
8
|
+
end # Hash
|
9
|
+
|
10
|
+
module String
|
11
|
+
alias_method :to_query_string, :to_s
|
12
|
+
end # String
|
13
|
+
end # EvokeClient
|
14
|
+
|
15
|
+
Hash.instance_eval { include EvokeClient::Hash }
|
16
|
+
String.instance_eval { include EvokeClient::String }
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module EvokeClient
|
2
|
+
module RestClient
|
3
|
+
module Shoulda
|
4
|
+
def expect_restful_request(method, *args)
|
5
|
+
::RestClient::Resource.any_instance.expects(method).with(*args)
|
6
|
+
end
|
7
|
+
|
8
|
+
def expect_restful_request_failure(method, *raises)
|
9
|
+
::RestClient::Resource.any_instance.expects(method).raises(*raises)
|
10
|
+
end
|
11
|
+
|
12
|
+
end # Shoulda
|
13
|
+
end # RestClient
|
14
|
+
end # EvokeClient
|
15
|
+
|
16
|
+
Test::Unit::TestCase.instance_eval { include EvokeClient::RestClient::Shoulda }
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class EvokeTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@params = {:url => 'foo', :callback_at => Time.now}
|
6
|
+
end
|
7
|
+
|
8
|
+
def teardown
|
9
|
+
Evoke.test = false
|
10
|
+
end
|
11
|
+
|
12
|
+
context "preparing an evokation" do
|
13
|
+
setup do
|
14
|
+
@data = {:foo => 'bar', 'goo' => 'car'}
|
15
|
+
@expected_data = "foo=bar&goo=car"
|
16
|
+
@evoke = Evoke.prepare(@params.merge(:data => @data))
|
17
|
+
end
|
18
|
+
|
19
|
+
before_should("convert times to UTC") { Time.any_instance.expects(:utc) }
|
20
|
+
|
21
|
+
should "convert data to a single escaped parameter string" do
|
22
|
+
assert_match /foo=bar&?/, @evoke.params[:data]
|
23
|
+
assert_match /goo=car&?/, @evoke.params[:data]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "saving" do
|
28
|
+
context "a new callback" do
|
29
|
+
setup do
|
30
|
+
expect_restful_request_failure(:get, ::RestClient::ResourceNotFound)
|
31
|
+
expect_restful_request(:post, @params)
|
32
|
+
@evoke = Evoke.prepare(@params)
|
33
|
+
end
|
34
|
+
should("try and post params after not finding a resource") { @evoke.save }
|
35
|
+
end
|
36
|
+
|
37
|
+
context "an existing callback" do
|
38
|
+
setup do
|
39
|
+
expect_restful_request(:get)
|
40
|
+
expect_restful_request(:put, @params)
|
41
|
+
@evoke = Evoke.prepare(@params)
|
42
|
+
end
|
43
|
+
should("try and put params after finding a resource") { @evoke.save }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "create_or_update!" do
|
48
|
+
should "initialize instance and call save" do
|
49
|
+
fake_evoke = EvokeClient::Base.new
|
50
|
+
EvokeClient::Base.expects(:new).with(@params).returns(fake_evoke)
|
51
|
+
fake_evoke.expects(:save)
|
52
|
+
Evoke.create_or_update!(@params)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "connection refused" do
|
57
|
+
setup do
|
58
|
+
expect_restful_request_failure(:get, Errno::ECONNREFUSED)
|
59
|
+
end
|
60
|
+
|
61
|
+
should "reraise Evoke::ConnectionRefused when saving" do
|
62
|
+
assert_raise(Evoke::ConnectionRefused) { Evoke.prepare({}).save }
|
63
|
+
end
|
64
|
+
|
65
|
+
should "reraise Evoke::ConnectionRefused when storing" do
|
66
|
+
assert_raise(Evoke::ConnectionRefused) { Evoke.create_or_update!({}) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "host and port:" do
|
71
|
+
context "when unchanged" do
|
72
|
+
setup do
|
73
|
+
Evoke.host = nil
|
74
|
+
Evoke.port = nil
|
75
|
+
end
|
76
|
+
should("return default host") { assert_equal 'evoke.thumblemonks.com', Evoke.host }
|
77
|
+
should("return default port") { assert_nil Evoke.port }
|
78
|
+
should("return default host and port") { assert_equal 'evoke.thumblemonks.com', Evoke.host_and_port }
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when changed" do
|
82
|
+
setup do
|
83
|
+
Evoke.host = 'example.com'
|
84
|
+
Evoke.port = 4567
|
85
|
+
end
|
86
|
+
|
87
|
+
should("return specified host") { assert_equal 'example.com', Evoke.host }
|
88
|
+
should("return specified port") { assert_equal 4567, Evoke.port }
|
89
|
+
should("return specified host and port") { assert_equal 'example.com:4567', Evoke.host_and_port }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when test mode is on" do
|
94
|
+
setup do
|
95
|
+
Evoke.test = true
|
96
|
+
@evoke = Evoke.prepare({})
|
97
|
+
end
|
98
|
+
|
99
|
+
should "expect an EvokeClient::Stub class" do
|
100
|
+
assert_kind_of EvokeClient::Stub, @evoke
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: evoke_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Knowlden
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-07 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rest-client
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.2
|
24
|
+
version:
|
25
|
+
description: Rest client interface for talking REST to the evoke service
|
26
|
+
email:
|
27
|
+
- gus@gusg.us
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- README.markdown
|
34
|
+
files:
|
35
|
+
- MIT-LICENSE
|
36
|
+
- README.markdown
|
37
|
+
- Rakefile
|
38
|
+
- evoke_client.gemspec
|
39
|
+
- lib/evoke_client.rb
|
40
|
+
- lib/evoke_client/base.rb
|
41
|
+
- lib/evoke_client/stub.rb
|
42
|
+
- lib/query_string.rb
|
43
|
+
- shoulda_macros/rest_client.rb
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://github.com/thumblemonks/evoke_client
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message: Choosy wizards choose Thumble Monks.
|
49
|
+
rdoc_options:
|
50
|
+
- --main
|
51
|
+
- README.markdown
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.3.5
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Rest client interface for talking REST to the evoke service
|
73
|
+
test_files:
|
74
|
+
- test/evoke_client_test.rb
|
75
|
+
- test/test_helper.rb
|