someapi 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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +2 -0
- data/lib/someapi/version.rb +3 -0
- data/lib/someapi.rb +135 -0
- data/someapi.gemspec +25 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f026e9cad3240ec1c275409e82272d601ca13230
|
4
|
+
data.tar.gz: e73c051d5f2eba1c9f10e90cc948365be6d9c05b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c64f30f3523c35d6604c939553a321faab0fc8b05f45c00ddd7fea0d8201a01c263a48186bc54dfec9f9d561c177e9ec22513bb47f030b2b96b7c5ee99b9854b
|
7
|
+
data.tar.gz: f97a01af2f90419dbe770d16e0e14c2ed75309e4717cc0d1751007e93d68111fbb35cb81b3c7494dd26f0fc14f928a206940b7113b6070a32c79a0c377fdf7c2
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Daniel Smith
|
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,80 @@
|
|
1
|
+
# SomeAPI
|
2
|
+
|
3
|
+
Built around HTTParty, SomeAPI provides a generic wrapper for your favourite RESTful WebAPI. Simply extend Some::API and apply your usual HTTParty options like base_uri, then call your new API and party harder!
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'someapi'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install someapi
|
18
|
+
|
19
|
+
## Party harder
|
20
|
+
|
21
|
+
It's easier than 123!
|
22
|
+
|
23
|
+
1. Create your wrapper:
|
24
|
+
|
25
|
+
class Github < Some::API
|
26
|
+
base_uri 'https://api.github.com'
|
27
|
+
headers 'User-Agent' => 'p45-dashboard'
|
28
|
+
default_params 'client_id' => ENV['GITHUB_CLIENT_ID'],
|
29
|
+
'client_secret' => ENV['GITHUB_CLIENT_SECRET']
|
30
|
+
format :json
|
31
|
+
end
|
32
|
+
|
33
|
+
2. Start using it! Simply string method calls and subscripts together like it's a real API wrapper. Add a bang (`!`) at the end to initiate the HTTP request, returning an HTTParty response, so all your favourite HTTParty features are still intact. Party on!
|
34
|
+
|
35
|
+
github = Guthub.new
|
36
|
+
...
|
37
|
+
github.get.users[@username].repos!
|
38
|
+
github.post.repos[@username][@repo].pulls! body: { title: "Foo", body: "Pull my Foo", ... }
|
39
|
+
github.delete.repos.[@username][@repo].!
|
40
|
+
|
41
|
+
## Make a mockery of your tests
|
42
|
+
|
43
|
+
Don't stub your toe on external services!
|
44
|
+
|
45
|
+
1. Add `gem 'webmock'` to your Gemfile under the test group
|
46
|
+
|
47
|
+
2. Add the following somewhere in your testing framework's configuration (like `spec_helper.rb`)
|
48
|
+
|
49
|
+
Some::API.include WebMock::API
|
50
|
+
|
51
|
+
3. Adding `stub` before the HTTP method in a SomeAPI request will instead return a Webmock stub after the bang.
|
52
|
+
|
53
|
+
github = Github.new
|
54
|
+
...
|
55
|
+
github.stub.get.users[@username].repos!.
|
56
|
+
to_return status: 200, body: @somehash.to_json
|
57
|
+
|
58
|
+
Stubs look exactly the same as their corresponding requests except for the presence of `stub`, so you can literally copy-pasta from your controllers to your specs and vice-versa without fiddling.
|
59
|
+
|
60
|
+
## Tips and Gotchas
|
61
|
+
|
62
|
+
If your request ends in a `[someth]` remember to put a dot before the bang, as in the examples. Ruby doesn't define the (very odd and mostly useless actually) operator for `[]!`.
|
63
|
+
|
64
|
+
Posting hashes can be done more succinctly by using the `<<` operator, as follows (using the post example from above):
|
65
|
+
|
66
|
+
github.post.repos[@username][@repo].pulls << { title: "Foo", body: "Pull my Foo", ... }
|
67
|
+
|
68
|
+
Also note that every time you do this (put the bang at the beginning of a request):
|
69
|
+
|
70
|
+
!github.get.users[@some_user]
|
71
|
+
|
72
|
+
a baby seal/platypus/kitten will die a horrific death. Also, it looks really bad and will confuse the crap out of you and your peers.
|
73
|
+
|
74
|
+
## Thank you for helping us help you help us all
|
75
|
+
|
76
|
+
1. Fork it ( https://github.com/[my-github-username]/someapi/fork )
|
77
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
78
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
79
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
80
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/lib/someapi.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
require "someapi/version"
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
|
5
|
+
module Some
|
6
|
+
|
7
|
+
class API
|
8
|
+
include HTTParty
|
9
|
+
|
10
|
+
API_REGEX = /^[a-zA-Z0-9_]+[!]?$/
|
11
|
+
|
12
|
+
def initialize options={}, meth=nil, path=nil, stubbed=false
|
13
|
+
@meth = meth
|
14
|
+
@path = path
|
15
|
+
@options = options
|
16
|
+
|
17
|
+
# stubbed is a flag set when you're stubbing the API call
|
18
|
+
# used in testing
|
19
|
+
# just call 'stub' in the call chain before the http_method method
|
20
|
+
@stubbed = stubbed
|
21
|
+
end
|
22
|
+
|
23
|
+
# http_method methods
|
24
|
+
# used in the call chain to set the http method
|
25
|
+
%W(get post put patch delete copy move head options).each do |meth|
|
26
|
+
define_method(meth) do
|
27
|
+
unless @meth
|
28
|
+
self.class.new Hash.new, meth.to_s, nil, @stubbed
|
29
|
+
else
|
30
|
+
self[meth]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# use in the call chain to flag this request as a stub
|
36
|
+
# used in testing for setting up API-call stubs
|
37
|
+
def stub
|
38
|
+
unless @meth
|
39
|
+
self.class.new Hash.new, @meth, @path, true
|
40
|
+
else
|
41
|
+
self['stub']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# sort of an alias for 'posting' (or whatever) an object
|
46
|
+
# just syntactic sugar for {body: obj} really
|
47
|
+
# I would have used '=' but that would return the object you posted! >.<
|
48
|
+
def << obj
|
49
|
+
self.! body: obj
|
50
|
+
end
|
51
|
+
|
52
|
+
# seriously this could be alias_method :>>, :!
|
53
|
+
def >> options
|
54
|
+
self.! options
|
55
|
+
end
|
56
|
+
|
57
|
+
# 'calls' the API request
|
58
|
+
# (or makes the stub, if stubbed)
|
59
|
+
def ! options = {}
|
60
|
+
unless @stubbed
|
61
|
+
self.class.send(@meth, @path || '/', deep_merge(options,@options))
|
62
|
+
else
|
63
|
+
uri = "#{self.class.base_uri}#{@path}"
|
64
|
+
|
65
|
+
deep_merge(options,@options)
|
66
|
+
process_headers(options)
|
67
|
+
process_query(options)
|
68
|
+
options = self.class.default_options.
|
69
|
+
merge(@options.merge(options))
|
70
|
+
|
71
|
+
stub_request(@meth.to_sym, uri.to_s).with(options)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# chains 'thing' onto URL path
|
76
|
+
def [] thing
|
77
|
+
self.class.new @options, @meth, "#{@path || ''}/#{thing}", @stubbed
|
78
|
+
end
|
79
|
+
|
80
|
+
# this is where the fun begins...
|
81
|
+
def method_missing meth, *args, &block
|
82
|
+
meths = meth.to_s
|
83
|
+
if @meth && meths =~ API_REGEX
|
84
|
+
|
85
|
+
if meths.end_with?('!')
|
86
|
+
# `foo! bar' is syntactic sugar for `foo.! bar'
|
87
|
+
self[meths[0...-1]].!(args[0] || {})
|
88
|
+
|
89
|
+
else
|
90
|
+
# chain the method name onto URL path
|
91
|
+
self[meths]
|
92
|
+
end
|
93
|
+
else
|
94
|
+
super
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def respond_to_missing? meth
|
99
|
+
@meth && meth.to_s =~ API_REGEX
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
# shamelessly stolen from HTTParty
|
105
|
+
def process_headers(options)
|
106
|
+
if options[:headers] && self.class.headers.any?
|
107
|
+
options[:headers] = self.class.headers.merge(options[:headers])
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# shamelessly copied from above, but for :query
|
112
|
+
def process_query(options)
|
113
|
+
if self.class.default_options[:default_params]
|
114
|
+
options[:query] = self.class.default_options[:default_params].
|
115
|
+
merge(options[:query] || {})
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# merge a hash within a hash from two hashes (yo-dawg...)
|
120
|
+
def merge_stuff(a,b,tag)
|
121
|
+
if a[tag] && b[tag]
|
122
|
+
a[tag] = b[tag].merge(a[tag])
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# just merge_stuff like :headers and :query... you know, HTTP stuff
|
127
|
+
def deep_merge(a,b)
|
128
|
+
merge_stuff(a,b,:headers)
|
129
|
+
merge_stuff(a,b,:query)
|
130
|
+
b.merge(a)
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
data/someapi.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'someapi/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "someapi"
|
8
|
+
spec.version = Some::VERSION
|
9
|
+
spec.authors = ["Daniel Smith"]
|
10
|
+
spec.email = ["jellymann@gmail.com"]
|
11
|
+
spec.summary = %q{A generic RESTful API wrapper.}
|
12
|
+
spec.description = %q{Built around HTTParty, SomeAPI provides a generic wrapper for your favourite RESTful WebAPI. Simply extend Some::API and apply your usual HTTParty options like base_uri, then call your new API and party harder!}
|
13
|
+
spec.homepage = "https://github.com/jellymann/someapi"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "httparty", "~> 0.13.1"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: someapi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.13.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.13.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Built around HTTParty, SomeAPI provides a generic wrapper for your favourite
|
56
|
+
RESTful WebAPI. Simply extend Some::API and apply your usual HTTParty options like
|
57
|
+
base_uri, then call your new API and party harder!
|
58
|
+
email:
|
59
|
+
- jellymann@gmail.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- ".gitignore"
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE.txt
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- lib/someapi.rb
|
70
|
+
- lib/someapi/version.rb
|
71
|
+
- someapi.gemspec
|
72
|
+
homepage: https://github.com/jellymann/someapi
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.3.0
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: A generic RESTful API wrapper.
|
96
|
+
test_files: []
|