apipie-bindings 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -16
- data/lib/apipie_bindings.rb +2 -8
- data/lib/apipie_bindings/action.rb +6 -2
- data/lib/apipie_bindings/api.rb +68 -12
- data/lib/apipie_bindings/indifferent_hash.rb +34 -0
- data/lib/apipie_bindings/inflector.rb +138 -0
- data/lib/apipie_bindings/param.rb +1 -3
- data/lib/apipie_bindings/resource.rb +1 -3
- data/lib/apipie_bindings/rest_client_oauth.rb +19 -0
- data/lib/apipie_bindings/version.rb +1 -1
- data/test/unit/indifferent_hash_test.rb +28 -0
- data/test/unit/inflector_test.rb +17 -0
- data/test/unit/test_helper.rb +0 -2
- metadata +12 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e98e08faa75e6ddb6b5e35d356fcf4d1dfc548bb
|
4
|
+
data.tar.gz: fcae54e949cd27fa457aadde6c5f5635fedf538a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e0e6b3250f9a427425750a907dc6178ae17398621a18d43242a4f0de3b930814c31cead0677e0b5e69270a88c1779273277b7631430c9287caf40407f0a5701
|
7
|
+
data.tar.gz: 3ed5c01d24123399875283af1162acda2559c7959ef2ccd5ff20466901e5dc7db768eb36c00aab4c71d349c5de24512a7ecdedd3fc9213690ecbd8df4072a3b0
|
data/README.md
CHANGED
@@ -7,9 +7,9 @@ Features
|
|
7
7
|
--------
|
8
8
|
|
9
9
|
#### Caching
|
10
|
-
The bindings cache the apidoc from the server. It has separated caches for each server it connects to. If the server sends
|
10
|
+
The bindings cache the apidoc from the server. It has separated caches for each server it connects to. If the server sends the apipie checksum in the headers ```Apipie-Checksum: <md5>``` , the bindings can expire the cache and reload updated version before next request. If the server does not send the hashes, the cache does not expire and has to be deleted manually when necessary.
|
11
11
|
|
12
|
-
|
12
|
+
The ability to send checksums comes with Apipie 0.1.1, see the [docs](https://github.com/Apipie/apipie-rails#json-checksums) on how to set it up.
|
13
13
|
|
14
14
|
#### API introspection
|
15
15
|
It is possible to list available resources, actions, params, routes and its attributes
|
@@ -18,63 +18,67 @@ It is possible to list available resources, actions, params, routes and its attr
|
|
18
18
|
```
|
19
19
|
$ rake install
|
20
20
|
$ irb
|
21
|
-
irb
|
21
|
+
irb> require 'apipie-bindings'
|
22
22
|
|
23
|
-
irb
|
23
|
+
irb> api = ApipieBindings::API.new({:uri => 'http://localhost:3000/', :username => 'admin', :password => :changeme})
|
24
24
|
```
|
25
25
|
|
26
26
|
##### Listing resources
|
27
27
|
|
28
28
|
```
|
29
|
-
irb
|
29
|
+
irb> api.resources
|
30
30
|
=> [<Resource :roles>, <Resource :images>, <Resource :reports>, <Resource :hosts>, .... <Resource :architectures>]
|
31
31
|
```
|
32
32
|
|
33
33
|
##### Listing actions
|
34
34
|
|
35
35
|
```
|
36
|
-
irb
|
36
|
+
irb> api.resource(:architectures).actions
|
37
37
|
=> [<Action :index>, <Action :show>, <Action :create>, <Action :update>, <Action :destroy>]
|
38
38
|
```
|
39
39
|
|
40
40
|
##### Listing routes
|
41
41
|
```
|
42
|
-
irb
|
42
|
+
irb> api.resource(:architectures).action(:show).routes
|
43
43
|
=> [<Route /api/architectures/:id>]
|
44
44
|
```
|
45
45
|
|
46
46
|
##### Listing params
|
47
47
|
|
48
48
|
```
|
49
|
-
irb
|
49
|
+
irb> api.resource(:architectures).action(:show).params
|
50
50
|
=> [<Param *id (String)>]
|
51
51
|
|
52
52
|
|
53
|
-
irb
|
53
|
+
irb> api.resource(:architectures).action(:show).params.first.required?
|
54
54
|
=> true
|
55
55
|
```
|
56
56
|
|
57
57
|
##### Calling methods (all the calls bellow are equivalent)
|
58
58
|
|
59
59
|
```
|
60
|
-
irb
|
60
|
+
irb> api.resource(:architectures).call(:show, :id => 1)
|
61
61
|
=> {"name"=>"x86_64", "id"=>1, "created_at"=>"2013-12-03T15:00:08Z", "updated_at"=>"2013-12-03T15:00:08Z"}
|
62
62
|
|
63
|
-
irb
|
63
|
+
irb> api.call(:architectures, :show, :id => 1)
|
64
64
|
=> {"name"=>"x86_64", "id"=>1, "created_at"=>"2013-12-03T15:00:08Z", "updated_at"=>"2013-12-03T15:00:08Z"}
|
65
65
|
|
66
|
-
irb
|
66
|
+
irb> api.resource(:architectures).action(:show).call(:id => 1)
|
67
67
|
=> {"name"=>"x86_64", "id"=>1, "created_at"=>"2013-12-03T15:00:08Z", "updated_at"=>"2013-12-03T15:00:08Z"}
|
68
68
|
|
69
69
|
```
|
70
70
|
|
71
|
+
Documentation
|
72
|
+
-------------
|
73
|
+
there is not much of the library documented yet, but we started to document our API with Yard.
|
74
|
+
The docs are installed with the gem and can be viewed from the docs dir directly or by running
|
75
|
+
```yard server --gems``` or **online** on [rubydoc.info](http://rubydoc.info/github/Apipie/apipie-bindings/)
|
76
|
+
|
77
|
+
|
71
78
|
TODO
|
72
79
|
----
|
73
80
|
* parameter validation
|
74
|
-
*
|
75
|
-
* error handling
|
76
|
-
* logging
|
77
|
-
* lots of other things
|
81
|
+
* update docs
|
78
82
|
|
79
83
|
|
80
84
|
License
|
data/lib/apipie_bindings.rb
CHANGED
@@ -1,12 +1,6 @@
|
|
1
|
-
module ApipieBindings
|
2
|
-
|
3
|
-
def self.log
|
4
|
-
Logging.logger['API']
|
5
|
-
end
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
1
|
require 'apipie_bindings/version'
|
2
|
+
require 'apipie_bindings/inflector'
|
3
|
+
require 'apipie_bindings/indifferent_hash'
|
10
4
|
require 'apipie_bindings/api'
|
11
5
|
require 'apipie_bindings/resource'
|
12
6
|
require 'apipie_bindings/action'
|
data/lib/apipie_bindings/api.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'rest_client'
|
3
3
|
require 'oauth'
|
4
|
-
require 'logging'
|
5
4
|
require 'awesome_print'
|
5
|
+
require 'apipie_bindings/rest_client_oauth'
|
6
|
+
require 'logger'
|
7
|
+
require 'tmpdir'
|
6
8
|
module ApipieBindings
|
7
9
|
|
8
10
|
class API
|
@@ -10,13 +12,51 @@ module ApipieBindings
|
|
10
12
|
attr_reader :apidoc_cache_name, :fake_responses
|
11
13
|
attr_writer :dry_run
|
12
14
|
|
15
|
+
# Creates new API bindings instance
|
16
|
+
# @param [Hash] config API bindings configuration
|
17
|
+
# @option config [String] :uri base URL of the server
|
18
|
+
# @option config [String] :username username to access the API
|
19
|
+
# @option config [String] :password username to access the API
|
20
|
+
# @option config [Hash] :oauth options to access API using OAuth
|
21
|
+
# * *:consumer_key* (String) OAuth key
|
22
|
+
# * *:consumer_secret* (String) OAuth secret
|
23
|
+
# * *:options* (Hash) options passed to OAuth
|
24
|
+
# @option config [Hash] :headers additional headers to send with the requests
|
25
|
+
# @option config [String] :api_version ('1') version of the API
|
26
|
+
# @option config [String] :apidoc_cache_dir ('/tmp/apipie_bindings/<URI>') where
|
27
|
+
# to cache the JSON description of the API
|
28
|
+
# @option config [String] :apidoc_cache_name ('default.json') name of te cache file.
|
29
|
+
# If there is cache in the :apidoc_cache_dir, it is used.
|
30
|
+
# @option config [Hash] :fake_responses ({}) responses to return if used in dry run mode
|
31
|
+
# @option config [Bool] :dry_run (false) dry run mode allows to test your scripts
|
32
|
+
# and not touch the API. The results are taken form exemples in the API description
|
33
|
+
# or from the :fake_responses
|
34
|
+
# @option config [Bool] :aggressive_cache_checking (false) check before every request
|
35
|
+
# if the local cache of API description (JSON) is up to date. By default it is checked
|
36
|
+
# *after* each API request
|
37
|
+
# @option config [Object] :logger (Logger.new(STDERR)) custom logger class
|
38
|
+
# @param [Hash] options params that are passed to ResClient as-is
|
39
|
+
# @example connect to a server
|
40
|
+
# ApipieBindings::API.new({:uri => 'http://localhost:3000/',
|
41
|
+
# :username => 'admin', :password => 'changeme',
|
42
|
+
# :api_version => '2', :aggressive_cache_checking => true})
|
43
|
+
# @example connect with a local API description
|
44
|
+
# ApipieBindings::API.new({:apidoc_cache_dir => 'test/unit/data',
|
45
|
+
# :apidoc_cache_name => 'architecture'})
|
13
46
|
def initialize(config, options={})
|
14
47
|
@uri = config[:uri]
|
15
|
-
@api_version = config[:api_version] ||
|
16
|
-
@apidoc_cache_dir = config[:apidoc_cache_dir] || File.join('
|
48
|
+
@api_version = config[:api_version] || 1
|
49
|
+
@apidoc_cache_dir = config[:apidoc_cache_dir] || File.join(Dir.tmpdir, 'apipie_bindings', @uri.tr(':/', '_'))
|
17
50
|
@apidoc_cache_name = config[:apidoc_cache_name] || set_default_name
|
18
51
|
@dry_run = config[:dry_run] || false
|
19
|
-
@
|
52
|
+
@aggressive_cache_checking = config[:aggressive_cache_checking] || false
|
53
|
+
@fake_responses = config[:fake_responses] || {}
|
54
|
+
|
55
|
+
@logger = config[:logger]
|
56
|
+
unless @logger
|
57
|
+
@logger = Logger.new(STDERR)
|
58
|
+
@logger.level = Logger::ERROR
|
59
|
+
end
|
20
60
|
|
21
61
|
config = config.dup
|
22
62
|
|
@@ -52,6 +92,7 @@ module ApipieBindings
|
|
52
92
|
end
|
53
93
|
|
54
94
|
def load_apidoc
|
95
|
+
check_cache if @aggressive_cache_checking
|
55
96
|
if File.exist?(apidoc_cache_file)
|
56
97
|
JSON.parse(File.read(apidoc_cache_file), :symbolize_names => true)
|
57
98
|
end
|
@@ -62,12 +103,12 @@ module ApipieBindings
|
|
62
103
|
path = "/apidoc/v#{@api_version}.json"
|
63
104
|
begin
|
64
105
|
response = http_call('get', path, {},
|
65
|
-
{:accept => "application/json
|
106
|
+
{:accept => "application/json"}, {:response => :raw})
|
66
107
|
rescue
|
67
108
|
raise "Could not load data from #{@uri}#{path}"
|
68
109
|
end
|
69
110
|
File.open(apidoc_cache_file, "w") { |f| f.write(response.body) }
|
70
|
-
|
111
|
+
log.debug "New apidoc loaded from the server"
|
71
112
|
load_apidoc
|
72
113
|
end
|
73
114
|
|
@@ -88,11 +129,14 @@ module ApipieBindings
|
|
88
129
|
ApipieBindings::Resource.new(name, self)
|
89
130
|
end
|
90
131
|
|
132
|
+
# List available resources
|
133
|
+
# @return [Array<ApipieBindings::Resource>]
|
91
134
|
def resources
|
92
135
|
apidoc[:docs][:resources].keys.map { |res| resource(res) }
|
93
136
|
end
|
94
137
|
|
95
138
|
def call(resource_name, action_name, params={}, headers={}, options={})
|
139
|
+
check_cache if @aggressive_cache_checking
|
96
140
|
resource = resource(resource_name)
|
97
141
|
action = resource.action(action_name)
|
98
142
|
route = action.find_route(params)
|
@@ -116,9 +160,8 @@ module ApipieBindings
|
|
116
160
|
headers[:params] = params if params
|
117
161
|
end
|
118
162
|
|
119
|
-
|
120
|
-
|
121
|
-
# logger.debug "Headers: #{headers.inspect}"
|
163
|
+
log.info "#{http_method.to_s.upcase} #{path}"
|
164
|
+
log.debug "Params: #{params.ai}"
|
122
165
|
|
123
166
|
args << headers if headers
|
124
167
|
|
@@ -128,11 +171,11 @@ module ApipieBindings
|
|
128
171
|
response = RestClient::Response.create(ex.response, ex.status, ex.args)
|
129
172
|
else
|
130
173
|
response = @client[path].send(*args)
|
131
|
-
update_cache(response.headers[:
|
174
|
+
update_cache(response.headers[:apipie_checksum])
|
132
175
|
end
|
133
176
|
|
134
177
|
result = options[:response] == :raw ? response : process_data(response)
|
135
|
-
|
178
|
+
log.debug "Response #{result.ai}"
|
136
179
|
result
|
137
180
|
end
|
138
181
|
|
@@ -149,7 +192,7 @@ module ApipieBindings
|
|
149
192
|
def update_cache(cache_name)
|
150
193
|
if !cache_name.nil? && (cache_name != @apidoc_cache_name)
|
151
194
|
clean_cache
|
152
|
-
|
195
|
+
log.debug "Cache expired. (#{@apidoc_cache_name} -> #{cache_name})"
|
153
196
|
@apidoc_cache_name = cache_name
|
154
197
|
end
|
155
198
|
end
|
@@ -159,6 +202,19 @@ module ApipieBindings
|
|
159
202
|
Dir["#{@apidoc_cache_dir}/*.json"].each { |f| File.delete(f) }
|
160
203
|
end
|
161
204
|
|
205
|
+
def check_cache
|
206
|
+
begin
|
207
|
+
response = http_call('get', "/apidoc/apipie_checksum", {}, {:accept => "application/json"})
|
208
|
+
response['checksum']
|
209
|
+
rescue
|
210
|
+
nil
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def log
|
215
|
+
@logger
|
216
|
+
end
|
217
|
+
|
162
218
|
private
|
163
219
|
|
164
220
|
def find_match(fakes, resource, action, params)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ApipieBindings
|
2
|
+
|
3
|
+
class IndifferentHash < Hash
|
4
|
+
|
5
|
+
def initialize(constructor = {})
|
6
|
+
super()
|
7
|
+
merge!(constructor)
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](k)
|
11
|
+
if has_key?(k)
|
12
|
+
convert_value(super(k))
|
13
|
+
elsif k.is_a?(Symbol) && has_key?(k.to_s)
|
14
|
+
convert_value(super(k.to_s))
|
15
|
+
elsif k.is_a?(String) && has_key?(k.to_sym)
|
16
|
+
convert_value(super(k.to_sym))
|
17
|
+
else
|
18
|
+
convert_value(super(k))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def convert_value(value)
|
25
|
+
if value.kind_of?(Hash) && !value.is_a?(IndifferentHash)
|
26
|
+
IndifferentHash.new(value)
|
27
|
+
elsif value.kind_of?(Array)
|
28
|
+
value.map { |v| convert_value(v) }
|
29
|
+
else
|
30
|
+
value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# Based on ActiveSupport Inflector (https://github.com/rails/rails.git)
|
2
|
+
# Inflection rules taken from davidcelis's Inflections (https://github.com/davidcelis/inflections.git)
|
3
|
+
module ApipieBindings
|
4
|
+
|
5
|
+
class Inflections
|
6
|
+
@__instance__ = {}
|
7
|
+
|
8
|
+
def self.instance(locale = :en)
|
9
|
+
@__instance__[locale] ||= new
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms, :acronym_regex
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], [], [], {}, /(?=a)b/
|
16
|
+
end
|
17
|
+
|
18
|
+
def acronym(word)
|
19
|
+
@acronyms[word.downcase] = word
|
20
|
+
@acronym_regex = /#{@acronyms.values.join("|")}/
|
21
|
+
end
|
22
|
+
|
23
|
+
def plural(rule, replacement)
|
24
|
+
@uncountables.delete(rule) if rule.is_a?(String)
|
25
|
+
@uncountables.delete(replacement)
|
26
|
+
@plurals.unshift([rule, replacement])
|
27
|
+
end
|
28
|
+
|
29
|
+
def singular(rule, replacement)
|
30
|
+
@uncountables.delete(rule) if rule.is_a?(String)
|
31
|
+
@uncountables.delete(replacement)
|
32
|
+
@singulars.unshift([rule, replacement])
|
33
|
+
end
|
34
|
+
|
35
|
+
def irregular(singular, plural)
|
36
|
+
@uncountables.delete(singular)
|
37
|
+
@uncountables.delete(plural)
|
38
|
+
|
39
|
+
s0 = singular[0]
|
40
|
+
srest = singular[1..-1]
|
41
|
+
|
42
|
+
p0 = plural[0]
|
43
|
+
prest = plural[1..-1]
|
44
|
+
|
45
|
+
if s0.upcase == p0.upcase
|
46
|
+
plural(/(#{s0})#{srest}$/i, '\1' + prest)
|
47
|
+
plural(/(#{p0})#{prest}$/i, '\1' + prest)
|
48
|
+
|
49
|
+
singular(/(#{s0})#{srest}$/i, '\1' + srest)
|
50
|
+
singular(/(#{p0})#{prest}$/i, '\1' + srest)
|
51
|
+
else
|
52
|
+
plural(/#{s0.upcase}(?i)#{srest}$/, p0.upcase + prest)
|
53
|
+
plural(/#{s0.downcase}(?i)#{srest}$/, p0.downcase + prest)
|
54
|
+
plural(/#{p0.upcase}(?i)#{prest}$/, p0.upcase + prest)
|
55
|
+
plural(/#{p0.downcase}(?i)#{prest}$/, p0.downcase + prest)
|
56
|
+
|
57
|
+
singular(/#{s0.upcase}(?i)#{srest}$/, s0.upcase + srest)
|
58
|
+
singular(/#{s0.downcase}(?i)#{srest}$/, s0.downcase + srest)
|
59
|
+
singular(/#{p0.upcase}(?i)#{prest}$/, s0.upcase + srest)
|
60
|
+
singular(/#{p0.downcase}(?i)#{prest}$/, s0.downcase + srest)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def uncountable(*words)
|
65
|
+
(@uncountables << words).flatten!
|
66
|
+
end
|
67
|
+
|
68
|
+
def human(rule, replacement)
|
69
|
+
@humans.unshift([rule, replacement])
|
70
|
+
end
|
71
|
+
|
72
|
+
def clear(scope = :all)
|
73
|
+
case scope
|
74
|
+
when :all
|
75
|
+
@plurals, @singulars, @uncountables, @humans = [], [], [], []
|
76
|
+
else
|
77
|
+
instance_variable_set "@#{scope}", []
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Inflector
|
83
|
+
|
84
|
+
def self.pluralize(word, locale = :en)
|
85
|
+
apply_inflections(word, inflections(locale).plurals)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.singularize(word, locale = :en)
|
89
|
+
apply_inflections(word, inflections(locale).singulars)
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.inflections(locale = :en)
|
93
|
+
if block_given?
|
94
|
+
yield ApipieBindings::Inflections.instance(locale)
|
95
|
+
else
|
96
|
+
ApipieBindings::Inflections.instance(locale)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def self.apply_inflections(word, rules)
|
103
|
+
result = word.to_s.dup
|
104
|
+
|
105
|
+
if word.empty? || inflections.uncountables.include?(result.downcase[/\b\w+\Z/])
|
106
|
+
result
|
107
|
+
else
|
108
|
+
rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
109
|
+
result
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
Inflector.inflections(:en) do |inflect|
|
115
|
+
inflect.clear
|
116
|
+
|
117
|
+
inflect.plural(/$/, 's')
|
118
|
+
inflect.plural(/([sxz]|[cs]h)$/i, '\1es')
|
119
|
+
inflect.plural(/([^aeiouy]o)$/i, '\1es')
|
120
|
+
inflect.plural(/([^aeiouy])y$/i, '\1ies')
|
121
|
+
|
122
|
+
inflect.singular(/s$/i, '')
|
123
|
+
inflect.singular(/(ss)$/i, '\1')
|
124
|
+
inflect.singular(/([sxz]|[cs]h)es$/, '\1')
|
125
|
+
inflect.singular(/([^aeiouy]o)es$/, '\1')
|
126
|
+
inflect.singular(/([^aeiouy])ies$/i, '\1y')
|
127
|
+
|
128
|
+
inflect.irregular('child', 'children')
|
129
|
+
inflect.irregular('person', 'people')
|
130
|
+
inflect.irregular('self', 'selves')
|
131
|
+
inflect.irregular('man', 'men')
|
132
|
+
inflect.irregular('sex', 'sexes')
|
133
|
+
inflect.irregular('move', 'moves')
|
134
|
+
|
135
|
+
inflect.uncountable(%w(equipment information money species series fish sheep police))
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
-
|
3
1
|
module ApipieBindings
|
4
2
|
|
5
3
|
class Param
|
@@ -7,7 +5,7 @@ module ApipieBindings
|
|
7
5
|
attr_reader :name, :params, :expected_type, :description, :validator
|
8
6
|
|
9
7
|
def initialize(param)
|
10
|
-
param = param
|
8
|
+
param = ApipieBindings::IndifferentHash.new(param)
|
11
9
|
@name = param[:name]
|
12
10
|
params = param[:params] || []
|
13
11
|
@params = params.map { |p| ApipieBindings::Param.new(p) }
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/string'
|
2
|
-
|
3
1
|
module ApipieBindings
|
4
2
|
|
5
3
|
class Resource
|
@@ -33,7 +31,7 @@ module ApipieBindings
|
|
33
31
|
end
|
34
32
|
|
35
33
|
def singular_name
|
36
|
-
@name.to_s
|
34
|
+
ApipieBindings::Inflector.singularize(@name.to_s)
|
37
35
|
end
|
38
36
|
|
39
37
|
def to_s
|
@@ -0,0 +1,19 @@
|
|
1
|
+
unless RestClient.const_defined? :OAUTH_EXTENSION
|
2
|
+
RestClient::OAUTH_EXTENSION = lambda do |request, args|
|
3
|
+
if args[:oauth]
|
4
|
+
uri = URI.parse args[:url]
|
5
|
+
default_options = { :site => "#{uri.scheme}://#{uri.host}:#{uri.port.to_s}",
|
6
|
+
:request_token_path => "",
|
7
|
+
:authorize_path => "",
|
8
|
+
:access_token_path => "" }
|
9
|
+
options = default_options.merge args[:oauth][:options] || { }
|
10
|
+
consumer = OAuth::Consumer.new(args[:oauth][:consumer_key], args[:oauth][:consumer_secret], options)
|
11
|
+
|
12
|
+
consumer.sign!(request)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
unless RestClient.before_execution_procs.include? RestClient::OAUTH_EXTENSION
|
18
|
+
RestClient.add_before_execution_proc &RestClient::OAUTH_EXTENSION
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe ApipieBindings::IndifferentHash do
|
4
|
+
|
5
|
+
let(:hash) { ApipieBindings::IndifferentHash.new({
|
6
|
+
"one" => 1,
|
7
|
+
:two => 2,
|
8
|
+
:nested => { "one" => 1, :two => 2},
|
9
|
+
:nested_array => [[{"one" => 1}]] })}
|
10
|
+
|
11
|
+
it "should allow access with symbol" do
|
12
|
+
hash[:one].must_equal 1
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should allow access with string" do
|
16
|
+
hash['two'].must_equal 2
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should allow access nested with symbol" do
|
20
|
+
hash['nested'][:one].must_equal 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should allow access nested in array with symbol" do
|
24
|
+
hash['nested_array'][0][0][:one].must_equal 1
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe ApipieBindings::Inflector do
|
4
|
+
|
5
|
+
it "should pluralize 'word'" do
|
6
|
+
ApipieBindings::Inflector.pluralize('word').must_equal 'words'
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should singularize 'words'" do
|
10
|
+
ApipieBindings::Inflector.singularize('words').must_equal 'word'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should pluralize 'gpg_key'" do
|
14
|
+
ApipieBindings::Inflector.pluralize('gpg_key').must_equal 'gpg_keys'
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/test/unit/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apipie-bindings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Bačovský
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: i18n
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - '>='
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: awesome_print
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - '>='
|
@@ -95,14 +95,19 @@ files:
|
|
95
95
|
- lib/apipie_bindings/action.rb
|
96
96
|
- lib/apipie_bindings/api.rb
|
97
97
|
- lib/apipie_bindings/example.rb
|
98
|
+
- lib/apipie_bindings/indifferent_hash.rb
|
99
|
+
- lib/apipie_bindings/inflector.rb
|
98
100
|
- lib/apipie_bindings/param.rb
|
99
101
|
- lib/apipie_bindings/resource.rb
|
102
|
+
- lib/apipie_bindings/rest_client_oauth.rb
|
100
103
|
- lib/apipie_bindings/route.rb
|
101
104
|
- lib/apipie_bindings/version.rb
|
102
105
|
- test/unit/action_test.rb
|
103
106
|
- test/unit/api_test.rb
|
104
107
|
- test/unit/data/architecture.json
|
105
108
|
- test/unit/example_test.rb
|
109
|
+
- test/unit/indifferent_hash_test.rb
|
110
|
+
- test/unit/inflector_test.rb
|
106
111
|
- test/unit/main_test.rb
|
107
112
|
- test/unit/param_test.rb
|
108
113
|
- test/unit/resource_test.rb
|
@@ -137,9 +142,11 @@ test_files:
|
|
137
142
|
- test/unit/api_test.rb
|
138
143
|
- test/unit/data/architecture.json
|
139
144
|
- test/unit/example_test.rb
|
145
|
+
- test/unit/indifferent_hash_test.rb
|
146
|
+
- test/unit/inflector_test.rb
|
140
147
|
- test/unit/main_test.rb
|
141
148
|
- test/unit/param_test.rb
|
142
149
|
- test/unit/resource_test.rb
|
143
150
|
- test/unit/route_test.rb
|
144
151
|
- test/unit/test_helper.rb
|
145
|
-
has_rdoc:
|
152
|
+
has_rdoc: yard
|