keener 0.1.0
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 +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +6 -0
- data/keener.gemspec +32 -0
- data/lib/keener/api.rb +189 -0
- data/lib/keener/config.rb +9 -0
- data/lib/keener/connection.rb +35 -0
- data/lib/keener/errors.rb +7 -0
- data/lib/keener/query.rb +70 -0
- data/lib/keener/resource.rb +51 -0
- data/lib/keener/response.rb +28 -0
- data/lib/keener/version.rb +3 -0
- data/lib/keener.rb +18 -0
- data/spec/adapters_spec.rb +34 -0
- data/spec/config_spec.rb +7 -0
- data/spec/fixtures/vcr_cassettes/count/grouped.yml +51 -0
- data/spec/fixtures/vcr_cassettes/count/no_options.yml +42 -0
- data/spec/fixtures/vcr_cassettes/count_unique.yml +42 -0
- data/spec/fixtures/vcr_cassettes/events.yml +45 -0
- data/spec/fixtures/vcr_cassettes/project.yml +51 -0
- data/spec/fixtures/vcr_cassettes/projects.yml +52 -0
- data/spec/integration/api_spec.rb +75 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/shared_examples.rb +55 -0
- metadata +266 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Mateo Murphy
|
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,32 @@
|
|
1
|
+
# Keener
|
2
|
+
|
3
|
+
[](https://travis-ci.org/mateomurphy/keener)
|
4
|
+
[](https://gemnasium.com/mateomurphy/keener)
|
5
|
+
|
6
|
+
Unofficial gem for accessing the keen api, based on [Faraday](https://github.com/lostisland/faraday).
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'keener'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install keener
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
See http://www.rubydoc.info/github/mateomurphy/keener/master/frames, especially the Keener::Api module
|
25
|
+
|
26
|
+
## Contributing
|
27
|
+
|
28
|
+
1. Fork it
|
29
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
30
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
31
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
32
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/keener.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'keener/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "keener"
|
8
|
+
gem.version = Keener::VERSION
|
9
|
+
gem.authors = ["Mateo Murphy"]
|
10
|
+
gem.email = ["mateo.murphy@gmail.com"]
|
11
|
+
gem.description = %q{Unofficial gem for accessing keen.io}
|
12
|
+
gem.summary = %q{An unofficial gem for accessing keen.io}
|
13
|
+
gem.homepage = "https://github.com/mateomurphy/keener"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency 'faraday', "~> 0.8.5"
|
21
|
+
gem.add_dependency 'faraday_middleware', '~> 0.9.0'
|
22
|
+
gem.add_dependency 'hashie', '~> 1.2.0'
|
23
|
+
|
24
|
+
gem.add_development_dependency "em-synchrony", "~> 1.0.3"
|
25
|
+
gem.add_development_dependency "em-http-request", "~> 1.0.3"
|
26
|
+
gem.add_development_dependency "typhoeus"
|
27
|
+
gem.add_development_dependency "rspec", "~> 2.12"
|
28
|
+
gem.add_development_dependency "vcr", "~> 2.4.0"
|
29
|
+
gem.add_development_dependency 'rake'
|
30
|
+
gem.add_development_dependency 'yard'
|
31
|
+
gem.add_development_dependency 'redcarpet'
|
32
|
+
end
|
data/lib/keener/api.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
module Keener
|
2
|
+
|
3
|
+
# Implements direct access to the api
|
4
|
+
#
|
5
|
+
# See https://keen.io/docs/api/reference/ for detailed info
|
6
|
+
module Api
|
7
|
+
# GET returns the average across all numeric values for the target property in the event
|
8
|
+
# collection matching the given criteria. Non-numeric values are ignored.
|
9
|
+
#
|
10
|
+
# @return [Resource]
|
11
|
+
def average(project_id, event_collection, target_property, options = {})
|
12
|
+
options[:event_collection] = event_collection
|
13
|
+
options[:target_property] = target_property
|
14
|
+
|
15
|
+
resource "projects/#{project_id}/queries/average", options
|
16
|
+
end
|
17
|
+
|
18
|
+
# GET returns the number of resources in the event collection matching the given criteria.
|
19
|
+
#
|
20
|
+
# @return [Resource]
|
21
|
+
def count(project_id, event_collection, options = {})
|
22
|
+
options[:event_collection] = event_collection
|
23
|
+
|
24
|
+
resource "projects/#{project_id}/queries/count", options
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET returns the number of UNIQUE resources in the event collection matching the given criteria.
|
28
|
+
#
|
29
|
+
# @return [Resource]
|
30
|
+
def count_unique(project_id, event_collection, target_property, options = {})
|
31
|
+
options[:event_collection] = event_collection
|
32
|
+
options[:target_property] = target_property
|
33
|
+
|
34
|
+
resource "projects/#{project_id}/queries/count_unique", options
|
35
|
+
end
|
36
|
+
|
37
|
+
# GET returns the available child resources.
|
38
|
+
#
|
39
|
+
# @return [Resource]
|
40
|
+
def discovery
|
41
|
+
resource ''
|
42
|
+
end
|
43
|
+
|
44
|
+
# GET returns available schema information for this event collection,
|
45
|
+
# including properties and their type. It also returns links to sub-resources.
|
46
|
+
#
|
47
|
+
# POST is for inserting one event at a time in a single request. Examples below.
|
48
|
+
#
|
49
|
+
# DELETE is for deleting the entire event collection. This is irreversible and will only work for collections under 10k events.
|
50
|
+
#
|
51
|
+
# @return [Resource]
|
52
|
+
def event_collection(project_id, event_collection)
|
53
|
+
resource "projects/#{project_id}/events/#{event_collection}"
|
54
|
+
end
|
55
|
+
|
56
|
+
# GET returns schema information for all the event collections in this project,
|
57
|
+
# including properties and their type.
|
58
|
+
#
|
59
|
+
# POST is for inserting multiple events in one or more collections, in a single request.
|
60
|
+
#
|
61
|
+
# @return [Resource]
|
62
|
+
def event_collections(project_id)
|
63
|
+
resource "projects/#{project_id}/events"
|
64
|
+
end
|
65
|
+
|
66
|
+
# GET creates an extraction request for full-form event data with all property values.
|
67
|
+
# If the query string parameter email is specified, then the extraction will be processed
|
68
|
+
# asynchronously and an e-mail will be sent to the specified address when it completes.
|
69
|
+
# The email will include a link to a downloadable CSV file.
|
70
|
+
# If email is omitted, then the extraction will be processed in-line and results will be returned in the GET request.
|
71
|
+
#
|
72
|
+
# @return [Resource]
|
73
|
+
def extraction(project_id, options = {})
|
74
|
+
resource "projects/#{project_id}/queries/extraction", options
|
75
|
+
end
|
76
|
+
|
77
|
+
# Funnels count relevant events in succession.
|
78
|
+
#
|
79
|
+
# @return [Resource]
|
80
|
+
def funnel(project_id, options = {})
|
81
|
+
resource "projects/#{project_id}/queries/funnel", options
|
82
|
+
end
|
83
|
+
|
84
|
+
# GET returns the maximum numeric value for the target property in the event collection
|
85
|
+
# matching the given criteria. Non-numeric values are ignored.
|
86
|
+
#
|
87
|
+
# @return [Resource]
|
88
|
+
def maximum(project_id, event_collection, target_property, options = {})
|
89
|
+
options[:event_collection] = event_collection
|
90
|
+
options[:target_property] = target_property
|
91
|
+
|
92
|
+
resource "projects/#{project_id}/queries/maximum", options
|
93
|
+
end
|
94
|
+
|
95
|
+
# GET returns the minimum numeric value for the target property in the event collection
|
96
|
+
# matching the given criteria. Non-numeric values are ignored.
|
97
|
+
#
|
98
|
+
# @return [Resource]
|
99
|
+
def minimum(project_id, event_collection, target_property, options = {})
|
100
|
+
options[:event_collection] = event_collection
|
101
|
+
options[:target_property] = target_property
|
102
|
+
|
103
|
+
resource "projects/#{project_id}/queries/minimum", options
|
104
|
+
end
|
105
|
+
|
106
|
+
# GET Returns detailed information about the specific project.
|
107
|
+
#
|
108
|
+
# @return [Resource]
|
109
|
+
def project(project_id)
|
110
|
+
resource "projects/#{project_id}"
|
111
|
+
end
|
112
|
+
|
113
|
+
# GET Returns the projects accessible to the API user.
|
114
|
+
#
|
115
|
+
# @return [Resource]
|
116
|
+
def projects
|
117
|
+
resource 'projects'
|
118
|
+
end
|
119
|
+
|
120
|
+
# GET returns the property name, type, and a link to sub-resources.
|
121
|
+
#
|
122
|
+
# DELETE is for removing a property and deleting all values stored with that property name.
|
123
|
+
#
|
124
|
+
# @return [Resource]
|
125
|
+
def property(project_id, event_collection, property_name)
|
126
|
+
resource "projects/#{project_id}/events/#{event_collection}/properties/#{property_name}"
|
127
|
+
end
|
128
|
+
|
129
|
+
# GET returns the list of available queries.
|
130
|
+
#
|
131
|
+
# @return [Resource]
|
132
|
+
def queries(project_id)
|
133
|
+
resource "projects/#{project_id}/queries"
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns a resource object for the given url and options
|
137
|
+
#
|
138
|
+
# @return [Resource]
|
139
|
+
def resource(url, options = {})
|
140
|
+
Resource.new(url, options)
|
141
|
+
end
|
142
|
+
|
143
|
+
# GET returns information about the specified Saved Query and includes links to child-resources.
|
144
|
+
#
|
145
|
+
# PUT either inserts a new Saved Query if it doesn’t already exist, or updates an existing Saved Query if it does exist.
|
146
|
+
#
|
147
|
+
# DELETE just plain old deletes the Saved Query.
|
148
|
+
#
|
149
|
+
# @return [Resource]
|
150
|
+
def saved_query(project_id, saved_query_name, options)
|
151
|
+
resource "projects/#{project_id}/saved_queries/#{saved_query_name}", options
|
152
|
+
end
|
153
|
+
|
154
|
+
# GET returns the results of the specified Saved Query.
|
155
|
+
#
|
156
|
+
# @return [Resource]
|
157
|
+
def saved_query_result(project_id, saved_query_name)
|
158
|
+
resource "projects/#{project_id}/saved_queries/#{saved_query_name}/result"
|
159
|
+
end
|
160
|
+
|
161
|
+
# GET returns all the available Saved Queries for the specified project as well as links to child-resources.
|
162
|
+
#
|
163
|
+
# @return [Resource]
|
164
|
+
def saved_queries(project_id)
|
165
|
+
resource "projects/#{project_id}/saved_queries", options
|
166
|
+
end
|
167
|
+
|
168
|
+
# GET returns a list of UNIQUE resources in the event collection matching the given criteria.
|
169
|
+
#
|
170
|
+
# @return [Resource]
|
171
|
+
def select_unique(project_id, event_collection, target_property, options = {})
|
172
|
+
options[:event_collection] = event_collection
|
173
|
+
options[:target_property] = target_property
|
174
|
+
|
175
|
+
resource "projects/#{project_id}/queries/select_unique", options
|
176
|
+
end
|
177
|
+
|
178
|
+
# GET returns the sum of all numeric values for the target property in the
|
179
|
+
# event collection matching the given criteria. Non-numeric values are ignored.
|
180
|
+
#
|
181
|
+
# @return [Resource]
|
182
|
+
def sum(project_id, event_collection, target_property, options = {})
|
183
|
+
options[:event_collection] = event_collection
|
184
|
+
options[:target_property] = target_property
|
185
|
+
|
186
|
+
resource "projects/#{project_id}/queries/sum", options
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Keener
|
2
|
+
module Connection
|
3
|
+
def url
|
4
|
+
if Keener.use_ssl
|
5
|
+
'https://api.keen.io'
|
6
|
+
else
|
7
|
+
'http://api.keen.io'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def connection
|
12
|
+
@connection ||= ::Faraday.new(:url => url, :ssl => ssl_config) do |config|
|
13
|
+
config.headers['Authorization'] = Keener.api_key
|
14
|
+
config.headers['Content-Type'] = 'application/json'
|
15
|
+
|
16
|
+
config.use Response::Middleware
|
17
|
+
config.response :json
|
18
|
+
config.response :logger if Keener.log_responses
|
19
|
+
|
20
|
+
#config.use :instrumentation
|
21
|
+
config.adapter Keener.adapter || ::Faraday.default_adapter
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset_connection
|
26
|
+
@connection = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def in_parallel(manager = nil, &block)
|
30
|
+
connection.in_parallel(manager) do
|
31
|
+
block.call(self)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/keener/query.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Keener
|
2
|
+
class Query
|
3
|
+
def initialize(project_id, event_collection, options = {})
|
4
|
+
@project_id = project_id
|
5
|
+
@event_collection = event_collection
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Metric < Query
|
11
|
+
def add_filter(property, operator, value)
|
12
|
+
@options[:filters] ||= []
|
13
|
+
@options[:filters] << {
|
14
|
+
:property_name => property,
|
15
|
+
:operator => operator,
|
16
|
+
:property_value => value
|
17
|
+
}
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def interval(interval)
|
22
|
+
@options[:interval] = interval
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def timeframe(timeframe)
|
27
|
+
@options[:timeframe] = timeframe
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def group_by(group_by)
|
32
|
+
@options[:group_by] = group_by
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def count
|
37
|
+
Keened.count(@project_id, @event_collection, @options).get
|
38
|
+
end
|
39
|
+
|
40
|
+
def count_unique(target_property)
|
41
|
+
Keened.count_unique(@project_id, @event_collection, target_property, @options).get
|
42
|
+
end
|
43
|
+
|
44
|
+
def minimum(target_property)
|
45
|
+
Keened.minimum(@project_id, @event_collection, target_property, @options).get
|
46
|
+
end
|
47
|
+
|
48
|
+
def maximum(target_property)
|
49
|
+
Keened.maximum(@project_id, @event_collection, target_property, @options).get
|
50
|
+
end
|
51
|
+
|
52
|
+
def sum(target_property)
|
53
|
+
Keened.sum(@project_id, @event_collection, target_property, @options).get
|
54
|
+
end
|
55
|
+
|
56
|
+
def average(target_property)
|
57
|
+
Keened.average(@project_id, @event_collection, target_property, @options).get
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#TODO implement
|
62
|
+
class Funnel < Query
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
#TODO implement
|
67
|
+
class Step < Query
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Keener
|
2
|
+
# This class represents an API resource and supports methods for making calls on it
|
3
|
+
class Resource
|
4
|
+
attr_reader :url, :options
|
5
|
+
|
6
|
+
def initialize(url = '', options = {})
|
7
|
+
@url = url
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
# Performs a get request on the given resource. A block passed will be used as an on_complete callback
|
12
|
+
#
|
13
|
+
# @return [Hashie::Mash] An object representing the result of the request
|
14
|
+
def get(&block)
|
15
|
+
handle_response Keener.connection.get("#{version}/#{url}", options), &block
|
16
|
+
end
|
17
|
+
|
18
|
+
# Performs a head request on the given resource
|
19
|
+
#
|
20
|
+
# @return [Faraday::Response] A faraday response object
|
21
|
+
def head
|
22
|
+
Keener.connection.head("#{version}/#{url}", options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Checks the given body to see if it's an error object and raises it if it is
|
26
|
+
def check_for_errors(body)
|
27
|
+
raise body if body.is_a?(Error)
|
28
|
+
body
|
29
|
+
end
|
30
|
+
|
31
|
+
# Handles a faraday response, checking if it's an error, and setting up a callback with the passed block
|
32
|
+
def handle_response(response, &block)
|
33
|
+
if response.finished?
|
34
|
+
response = check_for_errors(response.body)
|
35
|
+
end
|
36
|
+
|
37
|
+
if block
|
38
|
+
response.on_complete do |env|
|
39
|
+
block.call(env[:body])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
response
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the Keen API version to use for requests
|
47
|
+
def version
|
48
|
+
'3.0'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'hashie/mash'
|
2
|
+
|
3
|
+
module Keener
|
4
|
+
class Response
|
5
|
+
class Middleware < ::Faraday::Response::Middleware
|
6
|
+
def check_for_errors(body)
|
7
|
+
if body.respond_to?(:error_code)
|
8
|
+
Error.const_get(body.error_code).new(body.message)
|
9
|
+
else
|
10
|
+
body
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse(body)
|
15
|
+
case body
|
16
|
+
when Hash
|
17
|
+
check_for_errors(::Hashie::Mash.new(body))
|
18
|
+
when Array
|
19
|
+
body.map { |item| parse(item) }
|
20
|
+
else
|
21
|
+
body
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/lib/keener.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'keener/version'
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
|
6
|
+
require 'keener/config'
|
7
|
+
require 'keener/response'
|
8
|
+
require 'keener/connection'
|
9
|
+
require 'keener/resource'
|
10
|
+
require 'keener/errors'
|
11
|
+
require 'keener/api'
|
12
|
+
require 'keener/query'
|
13
|
+
|
14
|
+
module Keener
|
15
|
+
extend Api
|
16
|
+
extend Config
|
17
|
+
extend Connection
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'adapters' do
|
4
|
+
describe 'em-http' do
|
5
|
+
before :all do
|
6
|
+
Keener.reset_connection
|
7
|
+
Keener.adapter = :em_http
|
8
|
+
end
|
9
|
+
|
10
|
+
it_behaves_like "a sync adapter"
|
11
|
+
it_behaves_like "an async adapter"
|
12
|
+
it_behaves_like "a parallel adapter"
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'em-synchrony' do
|
16
|
+
before :all do
|
17
|
+
Keener.reset_connection
|
18
|
+
Keener.adapter = :em_synchrony
|
19
|
+
end
|
20
|
+
|
21
|
+
it_behaves_like "a sync adapter"
|
22
|
+
it_behaves_like "a parallel adapter"
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'typhoeus' do
|
26
|
+
before :all do
|
27
|
+
Keener.reset_connection
|
28
|
+
Keener.adapter = :typhoeus
|
29
|
+
end
|
30
|
+
|
31
|
+
it_behaves_like "a sync adapter"
|
32
|
+
it_behaves_like "a parallel adapter"
|
33
|
+
end
|
34
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://api.keen.io/3.0/projects/50e8d5f43843316b28000001/queries/count?group_by=character&event_collection=votes
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Authorization:
|
11
|
+
- b82b029917fa49af84a5827a43e537a7
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message:
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Thu, 07 Feb 2013 18:39:38 GMT
|
19
|
+
content-type:
|
20
|
+
- application/json
|
21
|
+
connection:
|
22
|
+
- close
|
23
|
+
content-length:
|
24
|
+
- '597'
|
25
|
+
expires:
|
26
|
+
- Thu, 07 Feb 2013 18:39:38 GMT
|
27
|
+
server:
|
28
|
+
- TornadoServer/2.4.1
|
29
|
+
etag:
|
30
|
+
- ! '"4a71bc462e514e53611cd6f04711fe4d1f68693a"'
|
31
|
+
cache-control:
|
32
|
+
- private, max-age=0, s-maxage=0
|
33
|
+
access-control-allow-origin:
|
34
|
+
- ! '*'
|
35
|
+
access-control-allow-headers:
|
36
|
+
- origin, content-type, accept, authorization, user-agent
|
37
|
+
body:
|
38
|
+
encoding: US-ASCII
|
39
|
+
string: ! "{\n \"result\": [\n {\n \"character\": \"Troi\", \n \"result\":
|
40
|
+
101\n }, \n {\n \"character\": \"LaForge\", \n \"result\":
|
41
|
+
571\n }, \n {\n \"character\": \"No answer\", \n \"result\":
|
42
|
+
397\n }, \n {\n \"character\": \"Crusher\", \n \"result\":
|
43
|
+
200\n }, \n {\n \"character\": \"Replicator\", \n \"result\":
|
44
|
+
171\n }, \n {\n \"character\": \"Worf\", \n \"result\": 330\n
|
45
|
+
\ }, \n {\n \"character\": \"Riker\", \n \"result\": 280\n
|
46
|
+
\ }, \n {\n \"character\": \"Data\", \n \"result\": 342\n },
|
47
|
+
\n {\n \"character\": \"Picard\", \n \"result\": 365\n }\n
|
48
|
+
\ ]\n}"
|
49
|
+
http_version:
|
50
|
+
recorded_at: Thu, 07 Feb 2013 18:39:38 GMT
|
51
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,42 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://api.keen.io/3.0/projects/50e8d5f43843316b28000001/queries/count?event_collection=votes
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Authorization:
|
11
|
+
- b82b029917fa49af84a5827a43e537a7
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message:
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Thu, 07 Feb 2013 18:39:38 GMT
|
19
|
+
content-type:
|
20
|
+
- application/json
|
21
|
+
connection:
|
22
|
+
- close
|
23
|
+
content-length:
|
24
|
+
- '20'
|
25
|
+
expires:
|
26
|
+
- Thu, 07 Feb 2013 18:39:38 GMT
|
27
|
+
server:
|
28
|
+
- TornadoServer/2.4.1
|
29
|
+
etag:
|
30
|
+
- ! '"09d8b72d478662bc62110091a94b0191b8133575"'
|
31
|
+
cache-control:
|
32
|
+
- private, max-age=0, s-maxage=0
|
33
|
+
access-control-allow-origin:
|
34
|
+
- ! '*'
|
35
|
+
access-control-allow-headers:
|
36
|
+
- origin, content-type, accept, authorization, user-agent
|
37
|
+
body:
|
38
|
+
encoding: US-ASCII
|
39
|
+
string: ! "{\n \"result\": 2757\n}"
|
40
|
+
http_version:
|
41
|
+
recorded_at: Thu, 07 Feb 2013 18:39:38 GMT
|
42
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,42 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://api.keen.io/3.0/projects/50e8d5f43843316b28000001/queries/count_unique?event_collection=votes&target_property=character
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Authorization:
|
11
|
+
- b82b029917fa49af84a5827a43e537a7
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message:
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Thu, 07 Feb 2013 18:24:12 GMT
|
19
|
+
content-type:
|
20
|
+
- application/json
|
21
|
+
connection:
|
22
|
+
- close
|
23
|
+
content-length:
|
24
|
+
- '17'
|
25
|
+
expires:
|
26
|
+
- Thu, 07 Feb 2013 18:24:12 GMT
|
27
|
+
server:
|
28
|
+
- TornadoServer/2.4.1
|
29
|
+
etag:
|
30
|
+
- ! '"07466cb5e5c2fa78072724132267ff0967888ade"'
|
31
|
+
cache-control:
|
32
|
+
- private, max-age=0, s-maxage=0
|
33
|
+
access-control-allow-origin:
|
34
|
+
- ! '*'
|
35
|
+
access-control-allow-headers:
|
36
|
+
- origin, content-type, accept, authorization, user-agent
|
37
|
+
body:
|
38
|
+
encoding: US-ASCII
|
39
|
+
string: ! "{\n \"result\": 9\n}"
|
40
|
+
http_version:
|
41
|
+
recorded_at: Thu, 07 Feb 2013 18:24:12 GMT
|
42
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,45 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://api.keen.io/3.0/projects/50e8d5f43843316b28000001/events
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Authorization:
|
11
|
+
- b82b029917fa49af84a5827a43e537a7
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message:
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Thu, 07 Feb 2013 18:07:17 GMT
|
19
|
+
content-type:
|
20
|
+
- application/json
|
21
|
+
connection:
|
22
|
+
- close
|
23
|
+
content-length:
|
24
|
+
- '229'
|
25
|
+
expires:
|
26
|
+
- Thu, 07 Feb 2013 18:07:16 GMT
|
27
|
+
server:
|
28
|
+
- TornadoServer/2.4.1
|
29
|
+
etag:
|
30
|
+
- ! '"9ea36ba679175b5949aca20923f1880f41c72528"'
|
31
|
+
cache-control:
|
32
|
+
- private, max-age=0, s-maxage=0
|
33
|
+
access-control-allow-origin:
|
34
|
+
- ! '*'
|
35
|
+
access-control-allow-headers:
|
36
|
+
- origin, content-type, accept, authorization, user-agent
|
37
|
+
body:
|
38
|
+
encoding: US-ASCII
|
39
|
+
string: ! "[\n {\n \"name\": \"votes\", \n \"properties\": {\n \"character\":
|
40
|
+
\"string\", \n \"keen.created_at\": \"datetime\", \n \"keen.timestamp\":
|
41
|
+
\"datetime\"\n }, \n \"url\": \"/3.0/projects/50e8d5f43843316b28000001/events/votes\"\n
|
42
|
+
\ }\n]"
|
43
|
+
http_version:
|
44
|
+
recorded_at: Thu, 07 Feb 2013 18:07:17 GMT
|
45
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,51 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://api.keen.io/3.0/projects/50e8d5f43843316b28000001
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Authorization:
|
11
|
+
- b82b029917fa49af84a5827a43e537a7
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message:
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Thu, 07 Feb 2013 18:16:37 GMT
|
19
|
+
content-type:
|
20
|
+
- application/json
|
21
|
+
connection:
|
22
|
+
- close
|
23
|
+
content-length:
|
24
|
+
- '718'
|
25
|
+
expires:
|
26
|
+
- Thu, 07 Feb 2013 18:16:36 GMT
|
27
|
+
server:
|
28
|
+
- TornadoServer/2.4.1
|
29
|
+
etag:
|
30
|
+
- ! '"0b93639278b4fbbc87a2ca117e3f58cf638385eb"'
|
31
|
+
cache-control:
|
32
|
+
- private, max-age=0, s-maxage=0
|
33
|
+
access-control-allow-origin:
|
34
|
+
- ! '*'
|
35
|
+
access-control-allow-headers:
|
36
|
+
- origin, content-type, accept, authorization, user-agent
|
37
|
+
body:
|
38
|
+
encoding: US-ASCII
|
39
|
+
string: ! "{\n \"api_key\": \"b82b029917fa49af84a5827a43e537a7\", \n \"events\":
|
40
|
+
[\n {\n \"name\": \"votes\", \n \"url\": \"/3.0/projects/50e8d5f43843316b28000001/votes\"\n
|
41
|
+
\ }\n ], \n \"events_url\": \"/3.0/projects/50e8d5f43843316b28000001/events\",
|
42
|
+
\n \"id\": \"50e8d5f43843316b28000001\", \n \"name\": \"RubyExampleApp\",
|
43
|
+
\n \"organization_id\": \"505e1a90897a2c2fbf000000\", \n \"partners_url\":
|
44
|
+
\"/3.0/projects/50e8d5f43843316b28000001/partners\", \n \"queries_url\":
|
45
|
+
\"/3.0/projects/50e8d5f43843316b28000001/queries\", \n \"saved_queries\":
|
46
|
+
[], \n \"saved_queries_url\": \"/3.0/projects/50e8d5f43843316b28000001/saved_queries\",
|
47
|
+
\n \"settings\": {\n \"analysis_limit\": 100, \n \"event_limit\": 10000\n
|
48
|
+
\ }, \n \"url\": \"/3.0/projects/50e8d5f43843316b28000001\"\n}"
|
49
|
+
http_version:
|
50
|
+
recorded_at: Thu, 07 Feb 2013 18:16:37 GMT
|
51
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://api.keen.io/3.0/projects
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Authorization:
|
11
|
+
- b82b029917fa49af84a5827a43e537a7
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message:
|
16
|
+
headers:
|
17
|
+
date:
|
18
|
+
- Thu, 07 Feb 2013 18:04:31 GMT
|
19
|
+
content-type:
|
20
|
+
- application/json
|
21
|
+
connection:
|
22
|
+
- close
|
23
|
+
content-length:
|
24
|
+
- '766'
|
25
|
+
expires:
|
26
|
+
- Thu, 07 Feb 2013 18:04:31 GMT
|
27
|
+
server:
|
28
|
+
- TornadoServer/2.4.1
|
29
|
+
etag:
|
30
|
+
- ! '"a8a0a1a620dc6345a3c77036f100da54dd5eb7e3"'
|
31
|
+
cache-control:
|
32
|
+
- private, max-age=0, s-maxage=0
|
33
|
+
access-control-allow-origin:
|
34
|
+
- ! '*'
|
35
|
+
access-control-allow-headers:
|
36
|
+
- origin, content-type, accept, authorization, user-agent
|
37
|
+
body:
|
38
|
+
encoding: US-ASCII
|
39
|
+
string: ! "[\n {\n \"api_key\": \"b82b029917fa49af84a5827a43e537a7\", \n
|
40
|
+
\ \"events\": [\n {\n \"name\": \"votes\", \n \"url\":
|
41
|
+
\"/3.0/projects/50e8d5f43843316b28000001/votes\"\n }\n ], \n \"events_url\":
|
42
|
+
\"/3.0/projects/50e8d5f43843316b28000001/events\", \n \"id\": \"50e8d5f43843316b28000001\",
|
43
|
+
\n \"name\": \"RubyExampleApp\", \n \"organization_id\": \"505e1a90897a2c2fbf000000\",
|
44
|
+
\n \"partners_url\": \"/3.0/projects/50e8d5f43843316b28000001/partners\",
|
45
|
+
\n \"queries_url\": \"/3.0/projects/50e8d5f43843316b28000001/queries\",
|
46
|
+
\n \"saved_queries\": [], \n \"saved_queries_url\": \"/3.0/projects/50e8d5f43843316b28000001/saved_queries\",
|
47
|
+
\n \"settings\": {\n \"analysis_limit\": 100, \n \"event_limit\":
|
48
|
+
10000\n }, \n \"url\": \"/3.0/projects/50e8d5f43843316b28000001\"\n
|
49
|
+
\ }\n]"
|
50
|
+
http_version:
|
51
|
+
recorded_at: Thu, 07 Feb 2013 18:04:31 GMT
|
52
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Keener::Api do
|
4
|
+
before :all do
|
5
|
+
Keener.reset_connection
|
6
|
+
Keener.adapter = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'errors' do
|
10
|
+
it 'raises a not found error' do
|
11
|
+
expect { Keener.project('xxx').get }.to raise_error(Keener::Error::ResourceNotFoundError)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.count' do
|
16
|
+
context 'without options', :vcr => { :cassette_name => 'count/no_options' } do
|
17
|
+
subject :count do
|
18
|
+
Keener.count(PROJECT_ID, COLLECTION_NAME).get
|
19
|
+
end
|
20
|
+
|
21
|
+
its (:result) { should eq(2757) }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'grouped by character', :vcr => { :cassette_name => 'count/grouped' } do
|
25
|
+
subject :count do
|
26
|
+
Keener.count(PROJECT_ID, COLLECTION_NAME, :group_by => 'character').get.result.first
|
27
|
+
end
|
28
|
+
|
29
|
+
its (:character) { should eq('Troi') }
|
30
|
+
its (:result) { should eq(101) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.count_unique', :vcr => { :cassette_name => 'count_unique' } do
|
35
|
+
subject :count_unique do
|
36
|
+
Keener.count_unique(PROJECT_ID, COLLECTION_NAME, 'character').get
|
37
|
+
end
|
38
|
+
|
39
|
+
its (:result) { should eq(9) }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '.event_collections', :vcr => { :cassette_name => 'events' } do
|
43
|
+
subject :events do
|
44
|
+
Keener.event_collections(PROJECT_ID).get
|
45
|
+
end
|
46
|
+
|
47
|
+
its (:count) { should eq(1)}
|
48
|
+
|
49
|
+
it 'returns votes' do
|
50
|
+
events.first.name.should eq('votes')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '.project', :vcr => { :cassette_name => 'project' } do
|
55
|
+
subject :project do
|
56
|
+
Keener.project(PROJECT_ID).get
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns the right project id' do
|
60
|
+
project.id.should eq(PROJECT_ID)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '.projects', :vcr => { :cassette_name => 'projects' } do
|
65
|
+
subject :projects do
|
66
|
+
Keener.projects.get
|
67
|
+
end
|
68
|
+
|
69
|
+
its (:count) { should eq(1)}
|
70
|
+
|
71
|
+
it 'returns the right project id' do
|
72
|
+
projects.first.id.should eq(PROJECT_ID)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'keener'
|
2
|
+
require 'vcr'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'typhoeus'
|
5
|
+
require 'typhoeus/adapters/faraday'
|
6
|
+
|
7
|
+
|
8
|
+
# Integration test data
|
9
|
+
PROJECT_ID = "50e8d5f43843316b28000001"
|
10
|
+
API_KEY = "b82b029917fa49af84a5827a43e537a7"
|
11
|
+
COLLECTION_NAME = "votes"
|
12
|
+
|
13
|
+
Keener.api_key = API_KEY
|
14
|
+
|
15
|
+
VCR.configure do |c|
|
16
|
+
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
17
|
+
c.hook_into :faraday
|
18
|
+
c.configure_rspec_metadata!
|
19
|
+
|
20
|
+
# Async tests don't work with vcr
|
21
|
+
c.allow_http_connections_when_no_cassette = true
|
22
|
+
end
|
23
|
+
|
24
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
25
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
26
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
27
|
+
# loaded once.
|
28
|
+
#
|
29
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
30
|
+
RSpec.configure do |config|
|
31
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
32
|
+
config.run_all_when_everything_filtered = true
|
33
|
+
#config.filter_run :focus
|
34
|
+
|
35
|
+
# Run specs in random order to surface order dependencies. If you find an
|
36
|
+
# order dependency and want to debug it, you can fix the order by providing
|
37
|
+
# the seed, which is printed after each run.
|
38
|
+
# --seed 1234
|
39
|
+
config.order = 'random'
|
40
|
+
end
|
41
|
+
|
42
|
+
Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
shared_examples 'a sync adapter' do
|
2
|
+
it 'makes a blocking request' do
|
3
|
+
Keener.projects.get.first.id.should eq(PROJECT_ID)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
shared_examples 'an async adapter' do
|
8
|
+
it 'calls a passed block' do
|
9
|
+
EventMachine.run do
|
10
|
+
Keener.projects.get { |response|
|
11
|
+
response.first.id.should eq(PROJECT_ID)
|
12
|
+
EventMachine.stop
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns a response' do
|
18
|
+
EventMachine.run do
|
19
|
+
Keener.projects.get.on_complete { |env|
|
20
|
+
env[:body].first.id.should eq(PROJECT_ID)
|
21
|
+
EventMachine.stop
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns a body containing a ResourceNotFoundError' do
|
27
|
+
EventMachine.run do
|
28
|
+
Keener.project('xxx').get.on_complete { |env|
|
29
|
+
env[:body].should be_a(Keener::Error::ResourceNotFoundError)
|
30
|
+
EventMachine.stop
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
shared_examples 'a parallel adapter' do
|
37
|
+
subject :responses do
|
38
|
+
responses = []
|
39
|
+
|
40
|
+
Keener.in_parallel do |k|
|
41
|
+
responses << k.count(PROJECT_ID, COLLECTION_NAME).get
|
42
|
+
responses << k.count_unique(PROJECT_ID, COLLECTION_NAME, 'character').get
|
43
|
+
end
|
44
|
+
|
45
|
+
responses
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'return the count' do
|
49
|
+
responses.first.body.result.should eq(2757)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns the unique count' do
|
53
|
+
responses.last.body.result.should eq(9)
|
54
|
+
end
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: keener
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mateo Murphy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: faraday
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.8.5
|
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.8.5
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: faraday_middleware
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.9.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.9.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: hashie
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.2.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: 1.2.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: em-synchrony
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.0.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.0.3
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: em-http-request
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.0.3
|
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: 1.0.3
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: typhoeus
|
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: rspec
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.12'
|
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: '2.12'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: vcr
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 2.4.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: 2.4.0
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: rake
|
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
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: yard
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: redcarpet
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
type: :development
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
description: Unofficial gem for accessing keen.io
|
191
|
+
email:
|
192
|
+
- mateo.murphy@gmail.com
|
193
|
+
executables: []
|
194
|
+
extensions: []
|
195
|
+
extra_rdoc_files: []
|
196
|
+
files:
|
197
|
+
- .gitignore
|
198
|
+
- .rspec
|
199
|
+
- Gemfile
|
200
|
+
- LICENSE.txt
|
201
|
+
- README.md
|
202
|
+
- Rakefile
|
203
|
+
- keener.gemspec
|
204
|
+
- lib/keener.rb
|
205
|
+
- lib/keener/api.rb
|
206
|
+
- lib/keener/config.rb
|
207
|
+
- lib/keener/connection.rb
|
208
|
+
- lib/keener/errors.rb
|
209
|
+
- lib/keener/query.rb
|
210
|
+
- lib/keener/resource.rb
|
211
|
+
- lib/keener/response.rb
|
212
|
+
- lib/keener/version.rb
|
213
|
+
- spec/adapters_spec.rb
|
214
|
+
- spec/config_spec.rb
|
215
|
+
- spec/fixtures/vcr_cassettes/count/grouped.yml
|
216
|
+
- spec/fixtures/vcr_cassettes/count/no_options.yml
|
217
|
+
- spec/fixtures/vcr_cassettes/count_unique.yml
|
218
|
+
- spec/fixtures/vcr_cassettes/events.yml
|
219
|
+
- spec/fixtures/vcr_cassettes/project.yml
|
220
|
+
- spec/fixtures/vcr_cassettes/projects.yml
|
221
|
+
- spec/integration/api_spec.rb
|
222
|
+
- spec/spec_helper.rb
|
223
|
+
- spec/support/shared_examples.rb
|
224
|
+
homepage: https://github.com/mateomurphy/keener
|
225
|
+
licenses: []
|
226
|
+
post_install_message:
|
227
|
+
rdoc_options: []
|
228
|
+
require_paths:
|
229
|
+
- lib
|
230
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
231
|
+
none: false
|
232
|
+
requirements:
|
233
|
+
- - ! '>='
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
version: '0'
|
236
|
+
segments:
|
237
|
+
- 0
|
238
|
+
hash: 134372974807999632
|
239
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
240
|
+
none: false
|
241
|
+
requirements:
|
242
|
+
- - ! '>='
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
version: '0'
|
245
|
+
segments:
|
246
|
+
- 0
|
247
|
+
hash: 134372974807999632
|
248
|
+
requirements: []
|
249
|
+
rubyforge_project:
|
250
|
+
rubygems_version: 1.8.24
|
251
|
+
signing_key:
|
252
|
+
specification_version: 3
|
253
|
+
summary: An unofficial gem for accessing keen.io
|
254
|
+
test_files:
|
255
|
+
- spec/adapters_spec.rb
|
256
|
+
- spec/config_spec.rb
|
257
|
+
- spec/fixtures/vcr_cassettes/count/grouped.yml
|
258
|
+
- spec/fixtures/vcr_cassettes/count/no_options.yml
|
259
|
+
- spec/fixtures/vcr_cassettes/count_unique.yml
|
260
|
+
- spec/fixtures/vcr_cassettes/events.yml
|
261
|
+
- spec/fixtures/vcr_cassettes/project.yml
|
262
|
+
- spec/fixtures/vcr_cassettes/projects.yml
|
263
|
+
- spec/integration/api_spec.rb
|
264
|
+
- spec/spec_helper.rb
|
265
|
+
- spec/support/shared_examples.rb
|
266
|
+
has_rdoc:
|