milkman 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.coveralls.yml +1 -0
- data/.gitignore +9 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +97 -0
- data/Rakefile +1 -0
- data/bin/milkman +4 -0
- data/lib/locales/en.yml +5 -0
- data/lib/milkman.rb +20 -0
- data/lib/milkman/authorizer.rb +44 -0
- data/lib/milkman/cli.rb +12 -0
- data/lib/milkman/client.rb +28 -0
- data/lib/milkman/request.rb +43 -0
- data/lib/milkman/utility.rb +27 -0
- data/lib/milkman/version.rb +3 -0
- data/milkman.gemspec +32 -0
- data/spec/milkman/authorizer_spec.rb +67 -0
- data/spec/milkman/cli_spec.rb +12 -0
- data/spec/milkman/client_spec.rb +73 -0
- data/spec/milkman/request_spec.rb +62 -0
- data/spec/milkman/utility_spec.rb +69 -0
- data/spec/milkman_spec.rb +13 -0
- data/spec/spec_helper.rb +13 -0
- metadata +231 -0
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
milkman
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-1.9.3-p392
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Kevin Tuhumury
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Milkman
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/kevintuhumury/milkman.png?branch=master)](https://travis-ci.org/kevintuhumury/milkman)
|
4
|
+
[![Dependency Status](https://gemnasium.com/kevintuhumury/milkman.png)](https://gemnasium.com/kevintuhumury/milkman)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/kevintuhumury/milkman.png)](https://codeclimate.com/github/kevintuhumury/milkman)
|
6
|
+
[![Coverage Status](https://coveralls.io/repos/kevintuhumury/milkman/badge.png?branch=master)](https://coveralls.io/r/kevintuhumury/milkman)
|
7
|
+
|
8
|
+
This gem provides a Ruby wrapper around the [Remember The Milk](https://www.rememberthemilk.com) (RTM) API, using HTTParty. Milkman is a library to access the RTM API in an easy way. It maps all of the methods, which are described in the [official documentation](https://www.rememberthemilk.com/services/api/methods/). Whenever new methods are added to the RTM API, you'll be able to use them immediately through Milkman.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'milkman'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install milkman
|
23
|
+
|
24
|
+
## Authorize Milkman
|
25
|
+
|
26
|
+
To use Milkman you'll need to authorize the gem with Remember The Milk. In order to do that, you'll need to apply for an API key and shared secret. When that's done, you'll need to run the `milkman` executable.
|
27
|
+
|
28
|
+
### Apply for an API key and shared secret
|
29
|
+
|
30
|
+
You can retrieve an API key and shared secret from the official Remember The Milk [site](https://www.rememberthemilk.com/services/api/keys.rtm). Just follow the instructions and once you've received the API key and shared secret, move on to the next step.
|
31
|
+
|
32
|
+
### Run the `milkman` executable
|
33
|
+
|
34
|
+
milkman authorize API_KEY SHARED_SECRET
|
35
|
+
|
36
|
+
Something like the following will be shown to you:
|
37
|
+
|
38
|
+
Copy the URL below and follow the steps on Remember The Milk (RTM) to authorize Milkman:
|
39
|
+
|
40
|
+
http://www.rememberthemilk.com/services/auth/?api_key=API_KEY&shared_secret=SHARED_SECRET&perms=read&format=json&api_sig=08da0d11ef239318027364133ac1a644
|
41
|
+
|
42
|
+
Once you've authorized Milkman, you'll receive a hash called 'frob' from Remember The Milk. The page from Remember The Milk will list something like the following: 'No callback URL specified for this API key. Your frob value is YOUR_FROB'. Copy and paste that YOUR_FROB value below and press <enter>:
|
43
|
+
|
44
|
+
Copy the URL (as requested) and paste it in your browser. Next copy the frob from the Remember The Milk website, paste it in your shell and press enter. Once you've done that, you'll receive the authentication token (auth token) from Remember The Milk:
|
45
|
+
|
46
|
+
USERNAME, you've successfully authorized Milkman with Remember The Milk. As you can see we've received your username and an authorization token. Both this auth token, your API key and shared secret should be saved for later use. You can either save them in a YAML file and load them in your application, include them in the Ruby script where you're using this gem or set them as environment variables. That's completely up to you.
|
47
|
+
|
48
|
+
Both the auth token, API key and shared secret are listed below. Save them using one of the methods above (or perhaps another solution) as you'll need all of them to use Milkman in your own project. Oh, and Remember... The Milk!
|
49
|
+
|
50
|
+
api_key: API_KEY
|
51
|
+
shared_secret: SHARED_SECRET
|
52
|
+
auth_token: AUTH_TOKEN
|
53
|
+
|
54
|
+
Take note of the variables and save them, since you'll need them to use Milkman.
|
55
|
+
|
56
|
+
## Using Milkman
|
57
|
+
|
58
|
+
Using Milkman is easy. All you need to know is that all calls go through the `Milkman::Client` class. Specifically it's `get` method. Let's say you want to retrieve all your tasks from RTM. Well, there's a method for that and it's called: `rtm.tasks.getList`. More information about that method can be found [here](https://www.rememberthemilk.com/services/api/methods/rtm.tasks.getList.rtm).
|
59
|
+
|
60
|
+
### Create an instance of the Milkman client
|
61
|
+
|
62
|
+
In order to retrieve the above information, we'll need an instance of the Milkman client. So let's create it:
|
63
|
+
|
64
|
+
client = Milkman::Client.new api_key: API_KEY, shared_secret: SHARED_SECRET, auth_token: AUTH_TOKEN
|
65
|
+
|
66
|
+
That's it.
|
67
|
+
|
68
|
+
### Milking the cow, err... Calling our method
|
69
|
+
|
70
|
+
Now, let's call our `rtm.tasks.getList` method:
|
71
|
+
|
72
|
+
client.get "rtm.tasks.getList"
|
73
|
+
|
74
|
+
The above call will return every task you have. As can be seen on the [API page](https://www.rememberthemilk.com/services/api/methods/rtm.tasks.getList.rtm) of the above method, there are a couple of optional parameters, like `list_id`, `filter` and `last_sync`. These can be used as follows:
|
75
|
+
|
76
|
+
client.get "rtm.tasks.getList", { list_id: 1, filter: "some filter" }
|
77
|
+
|
78
|
+
### Response format
|
79
|
+
|
80
|
+
Eventhough the API documentation shows the responses as XML, Milkman will return JSON as it's default response format.
|
81
|
+
|
82
|
+
## Contributing
|
83
|
+
|
84
|
+
You're very welcome to contribute to this gem. To do so, please follow these steps:
|
85
|
+
|
86
|
+
1. Fork this project
|
87
|
+
2. Clone your fork on your local machine
|
88
|
+
3. Install the development dependencies with `bundle install`
|
89
|
+
4. Create your feature branch with `git checkout -b my-new-feature`
|
90
|
+
5. Run the specs with `rspec` and make sure everything is covered with RSpec
|
91
|
+
6. Commit your changes `git commit -am 'Added new feature'`
|
92
|
+
7. Push to your branch `git push origin my-new-feature`
|
93
|
+
8. Create a new Pull Request
|
94
|
+
|
95
|
+
## Copyright
|
96
|
+
|
97
|
+
Copyright 2013 Kevin Tuhumury. Released under the MIT License.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/milkman
ADDED
data/lib/locales/en.yml
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
en:
|
2
|
+
milkman:
|
3
|
+
authorization:
|
4
|
+
frob_message: "\nCopy the URL below and follow the steps on Remember The Milk (RTM) to authorize Milkman:\n\n%{url}\n\nOnce you've authorized Milkman, you'll receive a hash called 'frob' from Remember The Milk. The page from Remember The Milk will list something like the following: 'No callback URL specified for this API key. Your frob value is YOUR_FROB'. Copy and paste that YOUR_FROB value below and press <enter>:\n\n"
|
5
|
+
auth_token_message: "\n%{username}, you've successfully authorized Milkman with Remember The Milk. As you can see we've received your username and an authorization token. Both this auth token, your API key and shared secret should be saved for later use. You can either save them in a YAML file and load them in your application, include them in the Ruby script where you're using this gem or set them as environment variables. That's completely up to you.\n\nBoth the auth token, API key and shared secret are listed below. Save them using one of the methods above (or perhaps another solution) as you'll need all of them to use Milkman in your own project. Oh, and Remember... The Milk!\n\n\tapi_key: %{api_key}\n\tshared_secret: %{shared_secret}\n\tauth_token: %{auth_token}\n\n"
|
data/lib/milkman.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "i18n"
|
2
|
+
|
3
|
+
module Milkman
|
4
|
+
|
5
|
+
AUTH_URL = "http://www.rememberthemilk.com/services/auth/"
|
6
|
+
BASE_URL = "http://api.rememberthemilk.com/services/rest/"
|
7
|
+
|
8
|
+
I18n.load_path += Dir.glob(File.join(File.dirname(__FILE__), "locales/*.yml"))
|
9
|
+
|
10
|
+
class NoMilkError < StandardError; end
|
11
|
+
class InvalidResponseError < StandardError; end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
require "milkman/cli"
|
16
|
+
require "milkman/utility"
|
17
|
+
require "milkman/request"
|
18
|
+
require "milkman/client"
|
19
|
+
require "milkman/authorizer"
|
20
|
+
require "milkman/version"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Milkman
|
2
|
+
class Authorizer
|
3
|
+
|
4
|
+
include Utility
|
5
|
+
|
6
|
+
attr_accessor :options
|
7
|
+
|
8
|
+
def initialize(attributes)
|
9
|
+
@options = attributes.merge! default_options
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.authorize(options)
|
13
|
+
new(options).authorize
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorize
|
17
|
+
puts I18n.t("milkman.authorization.frob_message", url: frob_message_url)
|
18
|
+
puts I18n.t("milkman.authorization.auth_token_message", username: response["rsp"]["auth"]["user"]["username"], api_key: options[:api_key], shared_secret: options[:shared_secret], auth_token: response["rsp"]["auth"]["token"])
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def response
|
24
|
+
@response ||= Milkman::Request.call request_url(signed_options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def signed_options
|
28
|
+
sign options[:shared_secret], options.merge!(method: "rtm.auth.getToken", frob: frob)
|
29
|
+
end
|
30
|
+
|
31
|
+
def frob
|
32
|
+
STDIN.gets.strip
|
33
|
+
end
|
34
|
+
|
35
|
+
def frob_message_url
|
36
|
+
authorization_url sign(options[:shared_secret], options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def authorization_url(parameters)
|
40
|
+
[ AUTH_URL, encode(parameters) ].join "?"
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/milkman/cli.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
module Milkman
|
4
|
+
class CLI < Thor
|
5
|
+
|
6
|
+
desc "authorize API_KEY SHARED_SECRET", "Authorize Milkman with Remember The Milk (RTM) by entering an API key and shared secret."
|
7
|
+
def authorize(api_key, shared_secret)
|
8
|
+
Authorizer.authorize api_key: api_key, shared_secret: shared_secret
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Milkman
|
2
|
+
class Client
|
3
|
+
|
4
|
+
include Utility
|
5
|
+
|
6
|
+
attr_accessor :options
|
7
|
+
|
8
|
+
def initialize(attributes)
|
9
|
+
@options = attributes.merge default_options
|
10
|
+
|
11
|
+
if !has_required_options?
|
12
|
+
raise NoMilkError, "The API key and shared secret are required."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def get(method, request_options = {})
|
17
|
+
signed_options = sign options[:shared_secret], options.merge!(method: method).merge!(request_options)
|
18
|
+
Milkman::Request.call request_url(signed_options)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def has_required_options?
|
24
|
+
options[:api_key] && options[:shared_secret]
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "httparty"
|
2
|
+
|
3
|
+
module Milkman
|
4
|
+
class Request
|
5
|
+
|
6
|
+
include HTTParty
|
7
|
+
|
8
|
+
def self.call(url)
|
9
|
+
new(url).parsed_response
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(url)
|
13
|
+
@url = url
|
14
|
+
end
|
15
|
+
|
16
|
+
def parsed_response
|
17
|
+
if code == 200
|
18
|
+
@response.parsed_response
|
19
|
+
else
|
20
|
+
raise InvalidResponseError, message
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def request
|
27
|
+
@response ||= self.class.get @url
|
28
|
+
end
|
29
|
+
|
30
|
+
def response
|
31
|
+
request.response
|
32
|
+
end
|
33
|
+
|
34
|
+
def code
|
35
|
+
response.code.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
def message
|
39
|
+
"#{@response.message} (#{@response.code}): #{@response.body} #{@response.inspect}"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Milkman
|
2
|
+
module Utility
|
3
|
+
|
4
|
+
def sign(shared_secret, parameters)
|
5
|
+
parameters.delete(:api_sig)
|
6
|
+
parameters[:api_sig] = Digest::MD5.hexdigest format(shared_secret, parameters)
|
7
|
+
parameters
|
8
|
+
end
|
9
|
+
|
10
|
+
def format(shared_secret, parameters)
|
11
|
+
[ shared_secret, parameters.sort.flatten.join ].join
|
12
|
+
end
|
13
|
+
|
14
|
+
def encode(options)
|
15
|
+
URI::encode_www_form options
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_url(options)
|
19
|
+
[ BASE_URL, encode(options) ].join "?"
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_options
|
23
|
+
{ perms: "delete", format: "json" }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/milkman.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'milkman/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "milkman"
|
8
|
+
gem.version = Milkman::VERSION
|
9
|
+
gem.authors = ["Kevin Tuhumury"]
|
10
|
+
gem.email = ["kevin.tuhumury@gmail.com"]
|
11
|
+
gem.homepage = "http://github.com/kevintuhumury/milkman"
|
12
|
+
gem.summary = %q{Milkman is a Ruby wrapper for the Remember The Milk (RTM) API.}
|
13
|
+
gem.description = %q{This gem provides a Ruby wrapper around the Remember The Milk (RTM) API for use in your own project.}
|
14
|
+
gem.license = "MIT"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.executables = ["milkman"]
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_runtime_dependency "thor"
|
22
|
+
gem.add_runtime_dependency "i18n"
|
23
|
+
gem.add_runtime_dependency "httparty"
|
24
|
+
|
25
|
+
gem.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
gem.add_development_dependency "rake"
|
27
|
+
|
28
|
+
gem.add_development_dependency "rspec"
|
29
|
+
gem.add_development_dependency "simplecov"
|
30
|
+
gem.add_development_dependency "capture_stdout"
|
31
|
+
gem.add_development_dependency "coveralls"
|
32
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Milkman
|
4
|
+
describe Authorizer do
|
5
|
+
|
6
|
+
let(:options) do
|
7
|
+
{ api_key: "<api_key>", shared_secret: "<shared_secret>" }
|
8
|
+
end
|
9
|
+
|
10
|
+
context "#initialize" do
|
11
|
+
|
12
|
+
it "saves a references to the specified options" do
|
13
|
+
hash = { api_key: "<api_key>", shared_secret: "<shared_secret>", format: "json", perms: "delete" }
|
14
|
+
|
15
|
+
client = described_class.new(options)
|
16
|
+
client.options.should eq hash
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
context ".authorize" do
|
22
|
+
|
23
|
+
it "authorizes" do
|
24
|
+
described_class.any_instance.should_receive(:authorize)
|
25
|
+
described_class.authorize options
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context "#authorize" do
|
31
|
+
|
32
|
+
let(:output) do
|
33
|
+
capture_stdout { described_class.authorize options }
|
34
|
+
end
|
35
|
+
|
36
|
+
let(:response) do
|
37
|
+
{"rsp" => {"auth" => {"user" => {"username" => "<username>"}, "token" => "<token>"}}}
|
38
|
+
end
|
39
|
+
|
40
|
+
before { STDIN.stub(:gets).and_return "<frob>" }
|
41
|
+
|
42
|
+
it "makes a call to the RTM API" do
|
43
|
+
Milkman::Request.should_receive(:call).with(any_args).and_return response
|
44
|
+
capture_stdout { described_class.authorize options }
|
45
|
+
end
|
46
|
+
|
47
|
+
context "output" do
|
48
|
+
|
49
|
+
before do
|
50
|
+
Milkman::Request.stub(:call).with(any_args).and_return response
|
51
|
+
end
|
52
|
+
|
53
|
+
it "notifies the user of entering the frob value" do
|
54
|
+
described_class.any_instance.stub(:frob_message_url).and_return "<url>"
|
55
|
+
output.should include "\nCopy the URL below and follow the steps on Remember The Milk (RTM) to authorize Milkman:\n\n<url>\n\nOnce you've authorized Milkman, you'll receive a hash called 'frob' from Remember The Milk. The page from Remember The Milk will list something like the following: 'No callback URL specified for this API key. Your frob value is YOUR_FROB'. Copy and paste that YOUR_FROB value below and press <enter>:"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "notifies the user of the received auth token, API key and shared secret" do
|
59
|
+
output.should include "<username>, you've successfully authorized Milkman with Remember The Milk. As you can see we've received your username and an authorization token. Both this auth token, your API key and shared secret should be saved for later use. You can either save them in a YAML file and load them in your application, include them in the Ruby script where you're using this gem or set them as environment variables. That's completely up to you.\n\nBoth the auth token, API key and shared secret are listed below. Save them using one of the methods above (or perhaps another solution) as you'll need all of them to use Milkman in your own project. Oh, and Remember... The Milk!\n\n\tapi_key: <api_key>\n\tshared_secret: <shared_secret>\n\tauth_token: <token>"
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Milkman
|
4
|
+
describe Client do
|
5
|
+
|
6
|
+
let(:options) do
|
7
|
+
{ api_key: "foo", shared_secret: "bar" }
|
8
|
+
end
|
9
|
+
|
10
|
+
context "#initialize" do
|
11
|
+
|
12
|
+
it "saves a references to the specified options" do
|
13
|
+
hash = { api_key: "foo", shared_secret: "bar", format: "json", perms: "delete" }
|
14
|
+
|
15
|
+
client = described_class.new(options)
|
16
|
+
client.options.should eq hash
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when the required API key and shared secret aren't specified" do
|
20
|
+
|
21
|
+
before do
|
22
|
+
options[:api_key] = nil
|
23
|
+
options[:shared_secret] = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises a NoMilkError" do
|
27
|
+
expect { described_class.new(options) }.to raise_error NoMilkError, "The API key and shared secret are required."
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when the API key is specified, but the shared secret isn't" do
|
33
|
+
|
34
|
+
before { options[:shared_secret] = nil }
|
35
|
+
|
36
|
+
it "raises a NoMilkError" do
|
37
|
+
expect { described_class.new(options) }.to raise_error NoMilkError, "The API key and shared secret are required."
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when the API key isn't specified, but the shared secret is" do
|
43
|
+
|
44
|
+
before { options[:api_key] = nil }
|
45
|
+
|
46
|
+
it "raises a NoMilkError" do
|
47
|
+
expect { described_class.new(options) }.to raise_error NoMilkError, "The API key and shared secret are required."
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when both the API key and shared secret are specified" do
|
53
|
+
|
54
|
+
it "doesn't raise a NoMilkError" do
|
55
|
+
expect { described_classClient.new(options) }.to_not raise_error NoMilkError
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
context "#get" do
|
63
|
+
|
64
|
+
it "requests a call to the RTM API with the specified method" do
|
65
|
+
Milkman::Request.should_receive(:call).with "http://api.rememberthemilk.com/services/rest/?api_key=foo&shared_secret=bar&perms=delete&format=json&method=method&api_sig=57c35d820267ab89717e291d619860d2"
|
66
|
+
|
67
|
+
client = described_class.new(options)
|
68
|
+
client.get "method"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Milkman
|
4
|
+
describe Request do
|
5
|
+
|
6
|
+
let(:url) { "#{BASE_URL}?foo=bar" }
|
7
|
+
|
8
|
+
let(:response) do
|
9
|
+
stub(code: 500, message: "Message", body: "Response Body", parsed_response: stub).as_null_object
|
10
|
+
end
|
11
|
+
|
12
|
+
before do
|
13
|
+
described_class.stub(:get).and_return response
|
14
|
+
end
|
15
|
+
|
16
|
+
context ".call" do
|
17
|
+
|
18
|
+
before { response.stub(:code).and_return 200 }
|
19
|
+
|
20
|
+
it "calls parsed_response" do
|
21
|
+
described_class.any_instance.should_receive(:parsed_response)
|
22
|
+
described_class.call url
|
23
|
+
end
|
24
|
+
|
25
|
+
it "makes a call to the RTM API" do
|
26
|
+
described_class.should_receive(:get).with url
|
27
|
+
described_class.call url
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context "#parsed_response" do
|
33
|
+
|
34
|
+
context "when the response is OK (code: 200)" do
|
35
|
+
|
36
|
+
before { response.stub(:code).and_return 200 }
|
37
|
+
|
38
|
+
it "parses the HTTParty response" do
|
39
|
+
response.should_receive(:parsed_response)
|
40
|
+
described_class.call url
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when the response isn't OK" do
|
46
|
+
|
47
|
+
before { described_class.stub!(:code).and_return 500 }
|
48
|
+
|
49
|
+
it "raises an InvalidResponseError" do
|
50
|
+
expect { described_class.call(url) }.to raise_error InvalidResponseError
|
51
|
+
end
|
52
|
+
|
53
|
+
it "notifies the user with a formatted message" do
|
54
|
+
expect { described_class.call(url) }.to raise_error InvalidResponseError, "Message (500): Response Body #{response.inspect}"
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class Klass
|
4
|
+
# Dummy Class
|
5
|
+
end
|
6
|
+
|
7
|
+
module Milkman
|
8
|
+
describe Utility do
|
9
|
+
|
10
|
+
let(:klass) { Klass.new.extend Utility }
|
11
|
+
|
12
|
+
let(:parameters) do
|
13
|
+
{ foo: "bar", baz: "qux"}
|
14
|
+
end
|
15
|
+
|
16
|
+
context "#sign" do
|
17
|
+
|
18
|
+
subject { klass.sign "SECRET", parameters }
|
19
|
+
|
20
|
+
it "adds an api_sig to the specified parameters" do
|
21
|
+
parameters.should_not include(:api_sig)
|
22
|
+
expect { subject }.to change { parameters.size }.from(2).to(3)
|
23
|
+
parameters.should include(:api_sig)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "calculates a MD5 hash of the formatted shared secret and specified parameters" do
|
27
|
+
subject[:api_sig].should eq "e307a0ab45b29409338e21e33dd2cfca"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context "#format" do
|
33
|
+
|
34
|
+
it "sorts the specified parameters by key name, concatenates key value pairs and attaches it to the shared secret" do
|
35
|
+
klass.format("SECRET", parameters).should eq "SECRETbazquxfoobar"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
context "#encode" do
|
41
|
+
|
42
|
+
it "encodes the specified options to an url encoded string" do
|
43
|
+
klass.encode(foo: "bar", baz: "qux").should eq "foo=bar&baz=qux"
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
context "#request_url" do
|
49
|
+
|
50
|
+
it "creates a request url with url encoded query parameters" do
|
51
|
+
klass.request_url(foo: "bar", baz: "qux").should eq "http://api.rememberthemilk.com/services/rest/?foo=bar&baz=qux"
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
context "#default_options" do
|
57
|
+
|
58
|
+
it "knows its default API permissions" do
|
59
|
+
klass.default_options[:perms].should eq "delete"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "knows its default API response format" do
|
63
|
+
klass.default_options[:format].should eq "json"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Milkman do
|
4
|
+
|
5
|
+
it "knows its AUTH_URL" do
|
6
|
+
Milkman::AUTH_URL.should eq "http://www.rememberthemilk.com/services/auth/"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "knows its BASE_URL" do
|
10
|
+
Milkman::BASE_URL.should eq "http://api.rememberthemilk.com/services/rest/"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
5
|
+
SimpleCov::Formatter::HTMLFormatter,
|
6
|
+
Coveralls::SimpleCov::Formatter
|
7
|
+
]
|
8
|
+
SimpleCov.start do
|
9
|
+
add_filter "spec"
|
10
|
+
end
|
11
|
+
|
12
|
+
require "milkman"
|
13
|
+
require "capture_stdout"
|
metadata
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: milkman
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kevin Tuhumury
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: thor
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: i18n
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
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: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: httparty
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.3'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '1.3'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rake
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: simplecov
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: capture_stdout
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: coveralls
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
description: This gem provides a Ruby wrapper around the Remember The Milk (RTM) API
|
159
|
+
for use in your own project.
|
160
|
+
email:
|
161
|
+
- kevin.tuhumury@gmail.com
|
162
|
+
executables:
|
163
|
+
- milkman
|
164
|
+
extensions: []
|
165
|
+
extra_rdoc_files: []
|
166
|
+
files:
|
167
|
+
- .coveralls.yml
|
168
|
+
- .gitignore
|
169
|
+
- .ruby-gemset
|
170
|
+
- .ruby-version
|
171
|
+
- .travis.yml
|
172
|
+
- Gemfile
|
173
|
+
- LICENSE.txt
|
174
|
+
- README.md
|
175
|
+
- Rakefile
|
176
|
+
- bin/milkman
|
177
|
+
- lib/locales/en.yml
|
178
|
+
- lib/milkman.rb
|
179
|
+
- lib/milkman/authorizer.rb
|
180
|
+
- lib/milkman/cli.rb
|
181
|
+
- lib/milkman/client.rb
|
182
|
+
- lib/milkman/request.rb
|
183
|
+
- lib/milkman/utility.rb
|
184
|
+
- lib/milkman/version.rb
|
185
|
+
- milkman.gemspec
|
186
|
+
- spec/milkman/authorizer_spec.rb
|
187
|
+
- spec/milkman/cli_spec.rb
|
188
|
+
- spec/milkman/client_spec.rb
|
189
|
+
- spec/milkman/request_spec.rb
|
190
|
+
- spec/milkman/utility_spec.rb
|
191
|
+
- spec/milkman_spec.rb
|
192
|
+
- spec/spec_helper.rb
|
193
|
+
homepage: http://github.com/kevintuhumury/milkman
|
194
|
+
licenses:
|
195
|
+
- MIT
|
196
|
+
post_install_message:
|
197
|
+
rdoc_options: []
|
198
|
+
require_paths:
|
199
|
+
- lib
|
200
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
segments:
|
207
|
+
- 0
|
208
|
+
hash: 1332773264260098832
|
209
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
210
|
+
none: false
|
211
|
+
requirements:
|
212
|
+
- - ! '>='
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
segments:
|
216
|
+
- 0
|
217
|
+
hash: 1332773264260098832
|
218
|
+
requirements: []
|
219
|
+
rubyforge_project:
|
220
|
+
rubygems_version: 1.8.25
|
221
|
+
signing_key:
|
222
|
+
specification_version: 3
|
223
|
+
summary: Milkman is a Ruby wrapper for the Remember The Milk (RTM) API.
|
224
|
+
test_files:
|
225
|
+
- spec/milkman/authorizer_spec.rb
|
226
|
+
- spec/milkman/cli_spec.rb
|
227
|
+
- spec/milkman/client_spec.rb
|
228
|
+
- spec/milkman/request_spec.rb
|
229
|
+
- spec/milkman/utility_spec.rb
|
230
|
+
- spec/milkman_spec.rb
|
231
|
+
- spec/spec_helper.rb
|