thumblemonks-evoke_client 0.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/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
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,38 @@
1
+ require 'restclient'
2
+ require 'query_string'
3
+
4
+ class Evoke
5
+ class ConnectionRefused < Exception; end
6
+
7
+ def self.host; @host || 'evoke.thumblemonks.com'; end
8
+ def self.host=(host) @host = host; end
9
+
10
+ def self.port; @port; end
11
+ def self.port=(port) @port = port; end
12
+
13
+ def self.host_and_port
14
+ [host, port].compact.join(':')
15
+ end
16
+
17
+ def self.create_or_update!(*args)
18
+ Evoke.new(*args).save
19
+ end
20
+
21
+ attr_reader :params, :headers
22
+
23
+ def initialize(params={})
24
+ @evoke = RestClient::Resource.new("http://#{Evoke.host_and_port}/callbacks")
25
+ @params = params
26
+ @params[:callback_at] = @params[:callback_at].utc if @params[:callback_at]
27
+ @params[:data] = @params[:data].to_query_string if @params[:data]
28
+ end
29
+
30
+ def save
31
+ @evoke[params[:guid]].get
32
+ @evoke[params[:guid]].put(@params)
33
+ rescue RestClient::ResourceNotFound
34
+ @evoke.post(@params)
35
+ rescue Errno::ECONNREFUSED
36
+ raise ConnectionRefused, "Connection refused while connecting to #{Evoke.host_and_port}"
37
+ end
38
+ end
@@ -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,83 @@
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
+ context "initializing a new evokation" do
9
+ setup do
10
+ @data = {:foo => 'bar', 'goo' => 'car'}
11
+ @expected_data = "foo=bar&goo=car"
12
+ @evoke = Evoke.new(@params.merge(:data => @data))
13
+ end
14
+
15
+ before_should("convert times to UTC") { Time.any_instance.expects(:utc) }
16
+
17
+ should "convert data to a single escaped parameter string" do
18
+ assert_match /foo=bar&?/, @evoke.params[:data]
19
+ assert_match /goo=car&?/, @evoke.params[:data]
20
+ end
21
+ end
22
+
23
+ context "saving" do
24
+ context "a new callback" do
25
+ setup do
26
+ expect_restful_request_failure(:get, ::RestClient::ResourceNotFound)
27
+ expect_restful_request(:post, @params)
28
+ @evoke = Evoke.new(@params)
29
+ end
30
+ should("try and post params after not finding a resource") { @evoke.save }
31
+ end
32
+
33
+ context "an existing callback" do
34
+ setup do
35
+ expect_restful_request(:get)
36
+ expect_restful_request(:put, @params)
37
+ @evoke = Evoke.new(@params)
38
+ end
39
+ should("try and put params after finding a resource") { @evoke.save }
40
+ end
41
+ end
42
+
43
+ context "create_or_update!" do
44
+ should "initialize instance and call save" do
45
+ fake_evoke = Evoke.new({})
46
+ Evoke.expects(:new).with(@params).returns(fake_evoke)
47
+ fake_evoke.expects(:save)
48
+ Evoke.create_or_update!(@params)
49
+ end
50
+ end
51
+
52
+ context "connection refused" do
53
+ setup do
54
+ RestClient::Resource.any_instance.expects(:get).raises(Errno::ECONNREFUSED)
55
+ end
56
+
57
+ should "reraise Evoke::ConnectionRefused when saving" do
58
+ assert_raise(Evoke::ConnectionRefused) { Evoke.new({}).save }
59
+ end
60
+
61
+ should "reraise Evoke::ConnectionRefused when storing" do
62
+ assert_raise(Evoke::ConnectionRefused) { Evoke.create_or_update!({}) }
63
+ end
64
+ end
65
+
66
+ context "host and port:" do
67
+ should("return default host") { assert_equal 'evoke.thumblemonks.com', Evoke.host }
68
+ should("return default port") { assert_nil Evoke.port }
69
+ should("return default host and port") { assert_equal 'evoke.thumblemonks.com', Evoke.host_and_port }
70
+
71
+ context "when changed" do
72
+ setup do
73
+ Evoke.host = 'example.com'
74
+ Evoke.port = 4567
75
+ end
76
+
77
+ should("return specified host") { assert_equal 'example.com', Evoke.host }
78
+ should("return specified port") { assert_equal 4567, Evoke.port }
79
+ should("return specified host and port") { assert_equal 'example.com:4567', Evoke.host_and_port }
80
+ end
81
+ end
82
+
83
+ end
@@ -0,0 +1,17 @@
1
+ module EvokeClient
2
+ module RestClient
3
+ module Shoulda
4
+
5
+ def expect_restful_request(method, *args)
6
+ ::RestClient::Resource.any_instance.expects(method).with(*args)
7
+ end
8
+
9
+ def expect_restful_request_failure(method, *raises)
10
+ ::RestClient::Resource.any_instance.expects(method).raises(*raises)
11
+ end
12
+
13
+ end # Shoulda
14
+ end # RestClient
15
+ end # EvokeClient
16
+
17
+ Test::Unit::TestCase.instance_eval { include EvokeClient::RestClient::Shoulda }
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'shoulda'
3
+ require 'mocha'
4
+ require 'redgreen'
5
+
6
+ Shoulda.autoload_macros(File.join(File.dirname(__FILE__), '..'))
7
+
8
+ require 'evoke_client'
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thumblemonks-evoke_client
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Justin Knowlden
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-03 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Rest client interface for talking REST to the evoke service
17
+ email:
18
+ - gus@gusg.us
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README.markdown
25
+ files:
26
+ - MIT-LICENSE
27
+ - README.markdown
28
+ - Rakefile
29
+ - lib/evoke_client.rb
30
+ - lib/query_string.rb
31
+ has_rdoc: false
32
+ homepage: http://github.com/thumblemonks/evoke_client
33
+ post_install_message: Choosy architectonics choose Thumble Monks.
34
+ rdoc_options:
35
+ - --main
36
+ - README.markdown
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ requirements: []
52
+
53
+ rubyforge_project:
54
+ rubygems_version: 1.2.0
55
+ signing_key:
56
+ specification_version: 2
57
+ summary: Rest client interface for talking REST to the evoke service
58
+ test_files:
59
+ - test/evoke_client_test.rb
60
+ - test/shoulda_macros/rest_client.rb
61
+ - test/test_helper.rb