popit 0.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/.gitignore +7 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +119 -0
- data/Rakefile +16 -0
- data/USAGE +1 -0
- data/lib/popit/version.rb +3 -0
- data/lib/popit.rb +115 -0
- data/popit.gemspec +24 -0
- data/spec/popit_spec.rb +99 -0
- data/spec/spec_helper.rb +3 -0
- metadata +124 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Open North Inc.
|
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,119 @@
|
|
1
|
+
# The PopIt API Ruby Gem
|
2
|
+
|
3
|
+
A Ruby wrapper for the [PopIt](http://popit.mysociety.org/) API, which allows you to create, read, update and delete items from PopIt.
|
4
|
+
|
5
|
+
[](http://travis-ci.org/opennorth/popit-ruby)
|
6
|
+
[](https://gemnasium.com/opennorth/popit-ruby)
|
7
|
+
[](https://codeclimate.com/github/opennorth/popit-ruby)
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
gem install popit
|
12
|
+
|
13
|
+
## API Examples
|
14
|
+
|
15
|
+
Require the PopIt gem:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'popit'
|
19
|
+
```
|
20
|
+
|
21
|
+
Create an API client:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
api = PopIt.new :instance_name => 'demo'
|
25
|
+
```
|
26
|
+
|
27
|
+
You can pass the options:
|
28
|
+
|
29
|
+
* `:instance_name` the PopIt instance, usually the first part of the domain name
|
30
|
+
* `:host_name` the PopIt API's host name – defaults to "popit.mysociety.org"
|
31
|
+
* `:port` the PopIt API's port – defaults to 80
|
32
|
+
* `:version` the PopIt API version – defaults to "v1"
|
33
|
+
* `:user` a user name – if blank, the API will be read-only
|
34
|
+
* `:password` the user's password
|
35
|
+
|
36
|
+
For brevity, we only show examples for `person` items, but you use the same code to operate on organisations and positions by substituting `organisation` or `position` for `person`.
|
37
|
+
|
38
|
+
More documentation at [RubyDoc.info](http://rdoc.info/gems/popit/PopIt).
|
39
|
+
|
40
|
+
### Read
|
41
|
+
|
42
|
+
Get all people:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
response = api.person.get
|
46
|
+
p response['results']
|
47
|
+
```
|
48
|
+
|
49
|
+
Get one person:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
response = api.person('47cc67093475061e3d95369d').get
|
53
|
+
p response['result']
|
54
|
+
```
|
55
|
+
|
56
|
+
You can search...
|
57
|
+
|
58
|
+
* people by slug, name or summary
|
59
|
+
* organisations by slug or name
|
60
|
+
* positions by title, person or organisation
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
response = api.person.get :name => 'John Doe'
|
64
|
+
p response['results']
|
65
|
+
```
|
66
|
+
|
67
|
+
### Create
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
response = api.person.post :name => 'John Doe'
|
71
|
+
id = response['result']['_id']
|
72
|
+
```
|
73
|
+
|
74
|
+
### Update
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
response = api.person('47cc67093475061e3d95369d').put :name => 'Jane Doe'
|
78
|
+
p response['result']
|
79
|
+
```
|
80
|
+
|
81
|
+
### Delete
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
success = api.person('47cc67093475061e3d95369d').delete
|
85
|
+
```
|
86
|
+
|
87
|
+
## Error Handling
|
88
|
+
|
89
|
+
If you:
|
90
|
+
|
91
|
+
* attempt to read an item that doesn't exist
|
92
|
+
* attempt to create, update or delete an item without authenticating
|
93
|
+
* attempt to operate on something other than people, organisations and positions
|
94
|
+
|
95
|
+
you will raise a `PopIt::Error` exception. The exception's message will be the error message from the PopIt API.
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
require 'popit'
|
99
|
+
api = PopIt.new :instance_name => 'demo'
|
100
|
+
api.person.get 'foo' # raises PopIt::Error
|
101
|
+
```
|
102
|
+
|
103
|
+
## Running Tests
|
104
|
+
|
105
|
+
To run the tests, create a `spec_auth.yml` file in the `spec` directory with the contents:
|
106
|
+
|
107
|
+
```yml
|
108
|
+
instance_name: YOUR_TEST_INSTANCE
|
109
|
+
user: YOUR_USERNAME
|
110
|
+
password: YOUR_PASSWORD
|
111
|
+
```
|
112
|
+
|
113
|
+
**If you care about the data in an instance, do not use that instance to run tests!**
|
114
|
+
|
115
|
+
## Bugs? Questions?
|
116
|
+
|
117
|
+
This gem's main repository is on GitHub: [http://github.com/opennorth/popit-ruby](http://github.com/opennorth/popit-ruby), where your contributions, forks, bug reports, feature requests, and feedback are greatly welcomed.
|
118
|
+
|
119
|
+
Copyright (c) 2011 Open North Inc., released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
task :default => :spec
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'yard'
|
11
|
+
YARD::Rake::YardocTask.new
|
12
|
+
rescue LoadError
|
13
|
+
task :yard do
|
14
|
+
abort 'YARD is not available. In order to run yard, you must: gem install yard'
|
15
|
+
end
|
16
|
+
end
|
data/USAGE
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
See README.md for full usage details.
|
data/lib/popit.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'yajl'
|
3
|
+
|
4
|
+
# A Ruby wrapper for the PopIt API.
|
5
|
+
#
|
6
|
+
# @see https://github.com/mysociety/popit/blob/master/lib/apps/api/api_v1.js
|
7
|
+
class PopIt
|
8
|
+
class Error < StandardError; end
|
9
|
+
|
10
|
+
include HTTParty
|
11
|
+
|
12
|
+
attr_reader :instance_name, :host_name, :port, :version, :username, :password
|
13
|
+
|
14
|
+
# Initializes a PopIt API client.
|
15
|
+
#
|
16
|
+
# @param [Hash] opts the API client's configuration
|
17
|
+
# @option opts [String] :instance_name the instance name
|
18
|
+
# @option opts [String] :host_name the PopIt API's host name, eg "popit.mysociety.org"
|
19
|
+
# @option opts [String] :post the PopIt API's port, eg "80"
|
20
|
+
# @option opts [String] :version the PopIt API version, eg "v1"
|
21
|
+
# @option opts [String] :user a user name
|
22
|
+
# @option opts [String] :password the user's password
|
23
|
+
def initialize(opts = {})
|
24
|
+
unless opts.has_key? :instance_name
|
25
|
+
raise ArgumentError, 'Missing key :instance_name'
|
26
|
+
end
|
27
|
+
|
28
|
+
@instance_name = opts[:instance_name]
|
29
|
+
@host_name = opts[:host_name] || 'popit.mysociety.org'
|
30
|
+
@port = opts[:port]
|
31
|
+
@version = opts[:version] || 'v1'
|
32
|
+
@username = opts[:user]
|
33
|
+
@password = opts[:password]
|
34
|
+
end
|
35
|
+
|
36
|
+
def base_uri
|
37
|
+
"http://#{instance_name}.#{host_name}:#{port}/api/#{version}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def get(path, opts = {})
|
41
|
+
request :get, path, opts
|
42
|
+
end
|
43
|
+
|
44
|
+
def post(path, opts = {})
|
45
|
+
request :post, path, opts
|
46
|
+
end
|
47
|
+
|
48
|
+
def put(path, opts = {})
|
49
|
+
request :put, path, opts
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete(path, opts = {})
|
53
|
+
request :delete, path, opts
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def request(http_method, path, opts = {})
|
59
|
+
path = "#{base_uri}/#{path}"
|
60
|
+
|
61
|
+
response = case http_method
|
62
|
+
when :get
|
63
|
+
self.class.send http_method, path, :query => opts
|
64
|
+
when :delete
|
65
|
+
self.class.send http_method, path, :basic_auth => {:username => username, :password => password}, :query => opts
|
66
|
+
when :post, :put
|
67
|
+
self.class.send http_method, path, :basic_auth => {:username => username, :password => password}, :body => opts
|
68
|
+
end
|
69
|
+
|
70
|
+
unless ['200', '201', '204'].include? response.response.code
|
71
|
+
message = if response.response.content_type == 'text/html'
|
72
|
+
response.response.code
|
73
|
+
else
|
74
|
+
response.response.body
|
75
|
+
end
|
76
|
+
raise PopIt::Error, message
|
77
|
+
end
|
78
|
+
|
79
|
+
response.parsed_response
|
80
|
+
end
|
81
|
+
|
82
|
+
def method_missing(*args)
|
83
|
+
Chain.new(self, args)
|
84
|
+
end
|
85
|
+
|
86
|
+
class Chain
|
87
|
+
attr_reader :klass, :chain
|
88
|
+
|
89
|
+
def initialize(klass, chain)
|
90
|
+
@klass = klass
|
91
|
+
@chain = chain
|
92
|
+
end
|
93
|
+
|
94
|
+
def get(opts = {})
|
95
|
+
@klass.get chain.join('/'), opts
|
96
|
+
end
|
97
|
+
|
98
|
+
def post(opts = {})
|
99
|
+
@klass.post chain.join('/'), opts
|
100
|
+
end
|
101
|
+
|
102
|
+
def put(opts = {})
|
103
|
+
@klass.put chain.join('/'), opts
|
104
|
+
end
|
105
|
+
|
106
|
+
def delete(opts = {})
|
107
|
+
@klass.delete chain.join('/'), opts
|
108
|
+
end
|
109
|
+
|
110
|
+
def method_missing(*args)
|
111
|
+
@chain += args
|
112
|
+
self
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/popit.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "popit/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "popit"
|
7
|
+
s.version = PopIt::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Open North"]
|
10
|
+
s.email = ["info@opennorth.ca"]
|
11
|
+
s.homepage = "http://github.com/opennorth/popit-ruby"
|
12
|
+
s.summary = %q{The PopIt API Ruby Gem}
|
13
|
+
s.description = %q{A Ruby wrapper for the PopIt API}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_runtime_dependency('yajl-ruby', '~> 1.0')
|
21
|
+
s.add_runtime_dependency('httparty', '~> 0.8.0')
|
22
|
+
s.add_development_dependency('rspec', '~> 2.10')
|
23
|
+
s.add_development_dependency('rake')
|
24
|
+
end
|
data/spec/popit_spec.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
# We don't want to test the PopIt API. We want to check that the wrapper works.
|
6
|
+
#
|
7
|
+
# @see https://github.com/mysociety/popit-python/blob/master/test.py
|
8
|
+
describe PopIt do
|
9
|
+
let :unauthenticated do
|
10
|
+
PopIt.new :instance_name => 'tttest'
|
11
|
+
end
|
12
|
+
|
13
|
+
let :authenticated do
|
14
|
+
PopIt.new YAML.load_file(File.expand_path(File.dirname(__FILE__) + '/spec_auth.yml'))
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should fail to send a request to a bad instance' do
|
18
|
+
api = PopIt.new :instance_name => '47cc67093475061e3d95369d'
|
19
|
+
expect { api.person.get }.to raise_error(PopIt::Error, '404')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should fail to send a request to a bad version' do
|
23
|
+
api = PopIt.new :instance_name => 'tttest', :version => 'v0'
|
24
|
+
expect { api.person.get }.to raise_error(PopIt::Error, '{"error":"page not found"}')
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with a PopIt instance' do
|
28
|
+
before :all do
|
29
|
+
@person = authenticated.person.post(:name => 'John Doe', :slug => 'john-doe')['result']
|
30
|
+
end
|
31
|
+
|
32
|
+
let :person do
|
33
|
+
@person
|
34
|
+
end
|
35
|
+
|
36
|
+
let :id do
|
37
|
+
@person['_id']
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should fail to send a request to a bad schema' do
|
41
|
+
expect { unauthenticated.foo.get }.to raise_error(PopIt::Error, '{"error":"page not found"}')
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when unauthenticated' do
|
45
|
+
it 'should get all items' do
|
46
|
+
response = unauthenticated.person.get
|
47
|
+
results = response['results']
|
48
|
+
results.should be_an(Array)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should get one item by name' do
|
52
|
+
response = unauthenticated.person.get :name => 'John Doe'
|
53
|
+
results = response['results']
|
54
|
+
results.should be_an(Array)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should get one item' do
|
58
|
+
response = unauthenticated.person(id).get
|
59
|
+
result = response['result']
|
60
|
+
result.should == person
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should fail to get a non-existent item' do
|
64
|
+
expect { unauthenticated.person('foo').get }.to raise_error(PopIt::Error, '{"error":"page not found"}')
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should fail to create an item' do
|
68
|
+
expect {unauthenticated.person.post :name => 'John Doe', :slug => 'john-doe'}.to raise_error(PopIt::Error, %({"error":"not authenticated"}))
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should fail to update an item' do
|
72
|
+
expect {unauthenticated.person(id).put :name => 'Jane Doe'}.to raise_error(PopIt::Error, %({"error":"not authenticated"}))
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should fail to delete an item' do
|
76
|
+
expect {unauthenticated.person(id).delete}.to raise_error(PopIt::Error, %({"error":"not authenticated"}))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when authenticated' do
|
81
|
+
it 'should create an item' do
|
82
|
+
response = authenticated.person.post :name => 'John Smith'
|
83
|
+
result = response['result']
|
84
|
+
result['name'].should == 'John Smith'
|
85
|
+
authenticated.person(result['_id']).delete # cleanup
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should update an item' do
|
89
|
+
response = authenticated.person(id).put :name => 'John Smith'
|
90
|
+
response.should == nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should delete an item' do
|
94
|
+
response = authenticated.person(id).delete
|
95
|
+
response.should == {}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: popit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Open North
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: yajl-ruby
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.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: '1.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: httparty
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.8.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.8.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.10'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.10'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
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: '0'
|
78
|
+
description: A Ruby wrapper for the PopIt API
|
79
|
+
email:
|
80
|
+
- info@opennorth.ca
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- .gitignore
|
86
|
+
- .travis.yml
|
87
|
+
- Gemfile
|
88
|
+
- LICENSE
|
89
|
+
- README.md
|
90
|
+
- Rakefile
|
91
|
+
- USAGE
|
92
|
+
- lib/popit.rb
|
93
|
+
- lib/popit/version.rb
|
94
|
+
- popit.gemspec
|
95
|
+
- spec/popit_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
homepage: http://github.com/opennorth/popit-ruby
|
98
|
+
licenses: []
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ! '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 1.8.24
|
118
|
+
signing_key:
|
119
|
+
specification_version: 3
|
120
|
+
summary: The PopIt API Ruby Gem
|
121
|
+
test_files:
|
122
|
+
- spec/popit_spec.rb
|
123
|
+
- spec/spec_helper.rb
|
124
|
+
has_rdoc:
|