geotrigger 0.0.2
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 +3 -0
- data/Gemfile +4 -0
- data/README.md +4 -0
- data/geotrigger.gemspec +18 -0
- data/lib/ext/string.rb +26 -0
- data/lib/geotrigger.rb +23 -0
- data/lib/geotrigger/ago/session.rb +145 -0
- data/lib/geotrigger/application.rb +27 -0
- data/lib/geotrigger/device.rb +50 -0
- data/lib/geotrigger/model.rb +84 -0
- data/lib/geotrigger/session.rb +57 -0
- data/lib/geotrigger/tag.rb +47 -0
- data/lib/geotrigger/trigger.rb +45 -0
- data/lib/geotrigger/version.rb +3 -0
- data/spec/config.yml.example +3 -0
- data/spec/geotrigger/application_spec.rb +61 -0
- data/spec/geotrigger/device_spec.rb +81 -0
- data/spec/geotrigger/geotrigger_spec.rb +108 -0
- data/spec/geotrigger/tag_spec.rb +106 -0
- data/spec/geotrigger/trigger_spec.rb +88 -0
- data/spec/helper.rb +8 -0
- metadata +100 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 1681ff89f1fb5fa48cee8fb34b31de586e2ca57b
|
|
4
|
+
data.tar.gz: c4e1f585cc211d2a40e6ddadf9043ae36a831271
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a76125f1e937a2a6dffb38e98a966034adc6dab207743c1dc23b091897ec6f7d606ac1841c678a5922dcd0823c142a704ac0a2a56197d5f34b9ddc3fd29c8d2c
|
|
7
|
+
data.tar.gz: cdf2862f6dce564353b9f9f363729a504a75da4f1ae15c6557b1496103d44ac728f040cfe1e304da1eaa9dd1f2b1f845cace0641d3313697f470b8e3d7654f8b
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/geotrigger.gemspec
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require File.expand_path('../lib/geotrigger/version', __FILE__)
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |gem|
|
|
5
|
+
gem.authors = ["Kenichi Nakamura"]
|
|
6
|
+
gem.email = ["kenichi.nakamura@gmail.com"]
|
|
7
|
+
gem.description = gem.summary = "A small ruby client for Esri's Geotrigger service"
|
|
8
|
+
gem.homepage = "https://github.com/esripdx/geotrigger-ruby"
|
|
9
|
+
gem.files = `git ls-files | grep -Ev '^(myapp|examples)'`.split("\n")
|
|
10
|
+
gem.test_files = `git ls-files -- spec/*`.split("\n")
|
|
11
|
+
gem.name = "geotrigger"
|
|
12
|
+
gem.require_paths = ["lib"]
|
|
13
|
+
gem.version = Geotrigger::VERSION
|
|
14
|
+
gem.license = 'apache'
|
|
15
|
+
|
|
16
|
+
gem.add_dependency 'httpclient'
|
|
17
|
+
gem.add_development_dependency 'timecop'
|
|
18
|
+
end
|
data/lib/ext/string.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class String
|
|
2
|
+
|
|
3
|
+
alias_method :blank?, :empty?
|
|
4
|
+
|
|
5
|
+
# these are pretty much ripped from:
|
|
6
|
+
# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
|
|
7
|
+
#
|
|
8
|
+
def camelcase
|
|
9
|
+
string = self.sub(/^(?:(?=\b|[A-Z_])|\w)/) { $&.downcase }
|
|
10
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
|
11
|
+
string.gsub!('/', '::')
|
|
12
|
+
string
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def underscore
|
|
16
|
+
acronym_regex = /(?=a)b/
|
|
17
|
+
word = self.gsub('::', '/')
|
|
18
|
+
word.gsub!(/(?:([A-Za-z\d])|^)(#{acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
|
|
19
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
|
20
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
|
21
|
+
word.tr!("-", "_")
|
|
22
|
+
word.downcase!
|
|
23
|
+
word
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
data/lib/geotrigger.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
require 'httpclient'; class HTTPClient; def inspect; to_s; end; end
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Geotrigger
|
|
6
|
+
class AGOError < StandardError; end
|
|
7
|
+
class GeotriggerError < StandardError
|
|
8
|
+
attr_accessor :code, :headers, :message, :params
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
lib = File.expand_path '../..', __FILE__
|
|
13
|
+
$:.push lib unless $:.include? lib
|
|
14
|
+
require 'ext/string'
|
|
15
|
+
|
|
16
|
+
require 'geotrigger/ago/session'
|
|
17
|
+
require 'geotrigger/session'
|
|
18
|
+
require 'geotrigger/model'
|
|
19
|
+
|
|
20
|
+
require 'geotrigger/application'
|
|
21
|
+
require 'geotrigger/device'
|
|
22
|
+
require 'geotrigger/tag'
|
|
23
|
+
require 'geotrigger/trigger'
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
module Geotrigger
|
|
2
|
+
module AGO
|
|
3
|
+
class Session
|
|
4
|
+
extend ::Forwardable
|
|
5
|
+
def_delegators :@impl, :access_token, :access_token=, :ago_data, :device_data, :refresh_token
|
|
6
|
+
|
|
7
|
+
AGO_BASE_URL = (ENV.key?('AGO_BASE_URL') ?
|
|
8
|
+
(ENV['AGO_BASE_URL'] + '%s') :
|
|
9
|
+
'https://www.arcgis.com/sharing/%s').freeze
|
|
10
|
+
|
|
11
|
+
def initialize opts = {}
|
|
12
|
+
@hc = HTTPClient.new
|
|
13
|
+
@impl = case opts[:type] || :application
|
|
14
|
+
when :application
|
|
15
|
+
Application.new self, opts
|
|
16
|
+
when :device
|
|
17
|
+
Device.new self, opts
|
|
18
|
+
else
|
|
19
|
+
raise ArgumentError 'unknown type'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def type
|
|
24
|
+
case @impl
|
|
25
|
+
when Application
|
|
26
|
+
:application
|
|
27
|
+
when Device
|
|
28
|
+
:device
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# http the specified method to the specified path with the given params.
|
|
33
|
+
# json parse the response body or raise errors.
|
|
34
|
+
#
|
|
35
|
+
def hc meth, path, params
|
|
36
|
+
r = @hc.__send__ meth, AGO_BASE_URL % path, params.merge(f: 'json')
|
|
37
|
+
raise AGOError.new r.body unless r.status == 200
|
|
38
|
+
h = JSON.parse r.body
|
|
39
|
+
raise AGOError.new r.body if h['error']
|
|
40
|
+
h
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module ExpirySet
|
|
44
|
+
|
|
45
|
+
TOKEN_EXPIRY_BUFFER = 10
|
|
46
|
+
|
|
47
|
+
def wrap_token_retrieval &block
|
|
48
|
+
yield
|
|
49
|
+
expires_at = Time.now.to_i + @ago_data['expires_in']
|
|
50
|
+
@ago_data[:expires_at] = Time.at expires_at - TOKEN_EXPIRY_BUFFER
|
|
51
|
+
@ago_data
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class Application
|
|
57
|
+
include ExpirySet
|
|
58
|
+
extend ::Forwardable
|
|
59
|
+
def_delegator :@session, :hc
|
|
60
|
+
|
|
61
|
+
attr_reader :ago_data
|
|
62
|
+
|
|
63
|
+
def initialize session, opts = {}
|
|
64
|
+
@session, @client_id, @client_secret =
|
|
65
|
+
session, opts[:client_id], opts[:client_secret]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def access_token
|
|
69
|
+
fetch_access_token if @ago_data.nil? or
|
|
70
|
+
(not @ago_data[:expires_at].nil? and
|
|
71
|
+
Time.now >= @ago_data[:expires_at])
|
|
72
|
+
@ago_data['access_token']
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def fetch_access_token
|
|
78
|
+
wrap_token_retrieval do
|
|
79
|
+
@ago_data = hc :post, 'oauth2/token',
|
|
80
|
+
client_id: @client_id,
|
|
81
|
+
client_secret: @client_secret,
|
|
82
|
+
grant_type: 'client_credentials'
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class Device
|
|
89
|
+
include ExpirySet
|
|
90
|
+
extend Forwardable
|
|
91
|
+
def_delegator :@session, :hc
|
|
92
|
+
|
|
93
|
+
attr_accessor :refresh_token
|
|
94
|
+
attr_reader :ago_data
|
|
95
|
+
|
|
96
|
+
def initialize session, opts = {}
|
|
97
|
+
@session, @client_id, @refresh_token =
|
|
98
|
+
session, opts[:client_id], opts[:refresh_token]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def access_token
|
|
102
|
+
if @ago_data.nil?
|
|
103
|
+
if @refresh_token.nil?
|
|
104
|
+
register
|
|
105
|
+
else
|
|
106
|
+
refresh_access_token
|
|
107
|
+
end
|
|
108
|
+
elsif not @ago_data[:expires_at].nil? and Time.now >= @ago_data[:expires_at]
|
|
109
|
+
refresh_access_token
|
|
110
|
+
end
|
|
111
|
+
@ago_data['access_token']
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def device_data
|
|
115
|
+
@device_data ||= hc(:get, 'portals/self', token: access_token)['deviceInfo']
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
def register
|
|
121
|
+
wrap_token_retrieval do
|
|
122
|
+
data = hc :post, 'oauth2/registerDevice', client_id: @client_id, expiration: -1
|
|
123
|
+
@ago_data = {
|
|
124
|
+
'access_token' => data['deviceToken']['access_token'],
|
|
125
|
+
'expires_in' => data['deviceToken']['expires_in']
|
|
126
|
+
}
|
|
127
|
+
@device_data = data['device']
|
|
128
|
+
@refresh_token = data['deviceToken']['refresh_token']
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def refresh_access_token
|
|
133
|
+
wrap_token_retrieval do
|
|
134
|
+
@ago_data = hc :post, 'oauth2/token',
|
|
135
|
+
client_id: @client_id,
|
|
136
|
+
refresh_token: @refresh_token,
|
|
137
|
+
grant_type: 'refresh_token'
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Geotrigger
|
|
2
|
+
|
|
3
|
+
class Application < Model
|
|
4
|
+
|
|
5
|
+
def permissions
|
|
6
|
+
post 'application/permissions'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def permissions= perms
|
|
10
|
+
post 'application/permissions/update', perms
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def devices params = {}
|
|
14
|
+
post_list 'devices', params
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def tags params = {}
|
|
18
|
+
post_list 'tags', params
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def triggers params = {}
|
|
22
|
+
post_list 'triggers', params
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Geotrigger
|
|
2
|
+
|
|
3
|
+
class Device < Model
|
|
4
|
+
include Taggable
|
|
5
|
+
|
|
6
|
+
def initialize opts = {}
|
|
7
|
+
super opts
|
|
8
|
+
case session.type
|
|
9
|
+
when :application
|
|
10
|
+
if opts[:device_id] and @data.nil?
|
|
11
|
+
grok_self_from post('device/list', deviceIds: opts[:device_id]), opts[:device_id]
|
|
12
|
+
end
|
|
13
|
+
when :device
|
|
14
|
+
if @data.nil?
|
|
15
|
+
grok_self_from post('device/list'), opts[:device_id] || :first
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def default_tag
|
|
21
|
+
'device:%s' % deviceId
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def post_update
|
|
25
|
+
post_data = @data.dup
|
|
26
|
+
case @session.type
|
|
27
|
+
when :application
|
|
28
|
+
post_data['deviceIds'] = post_data.delete 'deviceId'
|
|
29
|
+
when :device
|
|
30
|
+
post_data.delete 'deviceId'
|
|
31
|
+
end
|
|
32
|
+
post_data.delete 'tags'
|
|
33
|
+
post_data.delete 'lastSeen'
|
|
34
|
+
|
|
35
|
+
grok_self_from post 'device/update', post_data
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
alias_method :save, :post_update
|
|
39
|
+
|
|
40
|
+
def grok_self_from data, id = nil
|
|
41
|
+
if id == :first
|
|
42
|
+
@data = data['devices'].first
|
|
43
|
+
else
|
|
44
|
+
@data = data['devices'].select {|t| t['deviceId'] == (id || @data['deviceId'])}.first
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module Geotrigger
|
|
2
|
+
|
|
3
|
+
class Model
|
|
4
|
+
|
|
5
|
+
class StateError < StandardError; end
|
|
6
|
+
|
|
7
|
+
extend Forwardable
|
|
8
|
+
def_delegator :@session, :post
|
|
9
|
+
|
|
10
|
+
attr_accessor :data
|
|
11
|
+
attr_reader :session
|
|
12
|
+
|
|
13
|
+
def self.from_api data, session
|
|
14
|
+
i = self.new session: session
|
|
15
|
+
i.data = data
|
|
16
|
+
return i
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize opts = {}
|
|
20
|
+
@session = opts[:session] || Session.new(opts)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def post_list models, params = {}, default_params = {}
|
|
24
|
+
model = models.sub /s$/, ''
|
|
25
|
+
params = default_params.merge params
|
|
26
|
+
post(model + '/list', params)[models].map do |data|
|
|
27
|
+
Geotrigger.const_get(model.capitalize).from_api data, @session
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def method_missing meth, *args
|
|
32
|
+
meth_s = meth.to_s
|
|
33
|
+
if meth_s =~ /=$/ and args.length == 1
|
|
34
|
+
key = meth_s.sub(/=$/,'').camelcase
|
|
35
|
+
if @data and @data.key? key
|
|
36
|
+
@data[key] = args[0]
|
|
37
|
+
else
|
|
38
|
+
super meth, *args
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
key = meth_s.camelcase
|
|
42
|
+
if @data and @data.key? key
|
|
43
|
+
@data[key]
|
|
44
|
+
else
|
|
45
|
+
super meth, *args
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def == obj
|
|
51
|
+
if Model === obj
|
|
52
|
+
self.data == obj.data
|
|
53
|
+
else
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
module Taggable
|
|
59
|
+
|
|
60
|
+
def tags params = {}
|
|
61
|
+
post_list 'tags', params, tags: @data['tags']
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def add_tags *names
|
|
65
|
+
@data['addTags'] = names.flatten
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def remove_tags *names
|
|
69
|
+
names = names.flatten
|
|
70
|
+
raise ArgumentError.new "default tag prohibited" if names.include? default_tag
|
|
71
|
+
@data['removeTags'] = names
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def tags= *names
|
|
75
|
+
names = names.flatten
|
|
76
|
+
raise ArgumentError.new "default tag required" unless names.include? default_tag
|
|
77
|
+
@data['setTags'] = names
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Geotrigger
|
|
2
|
+
|
|
3
|
+
class Session
|
|
4
|
+
extend Forwardable
|
|
5
|
+
def_delegator :@ago, :type
|
|
6
|
+
|
|
7
|
+
BASE_URL = (ENV.key?('GT_BASE_URL') ?
|
|
8
|
+
(ENV['GT_BASE_URL'] + '%s') :
|
|
9
|
+
'https://geotrigger.arcgis.com/%s').freeze
|
|
10
|
+
|
|
11
|
+
attr_writer :access_token
|
|
12
|
+
|
|
13
|
+
def initialize opts = {}
|
|
14
|
+
@ago = AGO::Session.new opts
|
|
15
|
+
@hc = HTTPClient.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def access_token
|
|
19
|
+
@access_token || @ago.access_token
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def headers
|
|
23
|
+
{
|
|
24
|
+
'Content-Type' => 'application/json',
|
|
25
|
+
'Authorization' => "Bearer #{access_token}"
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def post path, params = {}
|
|
30
|
+
r = @hc.post BASE_URL % path, params.to_json, headers
|
|
31
|
+
raise GeotriggerError.new r.body unless r.status == 200
|
|
32
|
+
h = JSON.parse r.body
|
|
33
|
+
raise_error h['error'] if h['error']
|
|
34
|
+
h
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def raise_error error
|
|
38
|
+
ge = GeotriggerError.new error['message']
|
|
39
|
+
ge.code = error['code']
|
|
40
|
+
ge.headers = error['headers']
|
|
41
|
+
ge.message = error['message']
|
|
42
|
+
ge.params = error['params']
|
|
43
|
+
jj error
|
|
44
|
+
raise ge
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def device?
|
|
48
|
+
type == :device
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def application?
|
|
52
|
+
type == :application
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Geotrigger
|
|
2
|
+
|
|
3
|
+
class Tag < Model
|
|
4
|
+
|
|
5
|
+
def self.create session, opts
|
|
6
|
+
t = ::Geotrigger::Tag.new session: session
|
|
7
|
+
t.data = opts
|
|
8
|
+
t.post_create
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def initialize opts = {}
|
|
12
|
+
super opts
|
|
13
|
+
if opts[:name] and @data.nil?
|
|
14
|
+
grok_self_from post('tag/list', tags: opts[:name]), opts[:name]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def triggers params = {}
|
|
19
|
+
post_list 'triggers', params, tags: name
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def devices params = {}
|
|
23
|
+
post_list 'devices', params, tags: name
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def post_create
|
|
27
|
+
post_data = @data.dup
|
|
28
|
+
grok_self_from post('tag/permissions', post_data), @data[:tags]
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def post_update
|
|
33
|
+
raise StateError.new 'device access_token prohibited' if @session.device?
|
|
34
|
+
post_data = @data.dup
|
|
35
|
+
post_data['tags'] = post_data.delete 'name'
|
|
36
|
+
grok_self_from post 'tag/permissions', post_data
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
alias_method :save, :post_update
|
|
40
|
+
|
|
41
|
+
def grok_self_from data, name = nil
|
|
42
|
+
@data = data['tags'].select {|t| t['name'] == (name || @data['name'])}.first
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Geotrigger
|
|
2
|
+
|
|
3
|
+
class Trigger < Model
|
|
4
|
+
include Taggable
|
|
5
|
+
|
|
6
|
+
def self.create session, opts
|
|
7
|
+
t = Trigger.new session: session
|
|
8
|
+
t.data = opts
|
|
9
|
+
t.post_create
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize opts = {}
|
|
13
|
+
super opts
|
|
14
|
+
if opts[:trigger_id] and @data.nil?
|
|
15
|
+
grok_self_from post('trigger/list', triggerIds: opts[:trigger_id]), opts[:trigger_id]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def default_tag
|
|
20
|
+
'trigger:%s' % triggerId
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def post_create
|
|
24
|
+
post_data = @data.dup
|
|
25
|
+
@data = post 'trigger/create', post_data
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def post_update opts = {}
|
|
30
|
+
post_data = @data.dup
|
|
31
|
+
post_data['triggerIds'] = post_data.delete 'triggerId'
|
|
32
|
+
post_data.delete 'tags'
|
|
33
|
+
|
|
34
|
+
grok_self_from post 'trigger/update', post_data.merge(opts)
|
|
35
|
+
self
|
|
36
|
+
end
|
|
37
|
+
alias_method :save, :post_update
|
|
38
|
+
|
|
39
|
+
def grok_self_from data, id = nil
|
|
40
|
+
@data = data['triggers'].select {|t| t['triggerId'] == (id || @data['triggerId'])}.first
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require_relative '../helper'
|
|
2
|
+
|
|
3
|
+
describe Geotrigger::Application do
|
|
4
|
+
|
|
5
|
+
PERMS = 'deviceList',
|
|
6
|
+
'deviceLocation',
|
|
7
|
+
'deviceTagging',
|
|
8
|
+
'deviceToken',
|
|
9
|
+
'discoverableDevice',
|
|
10
|
+
'discoverableApplication',
|
|
11
|
+
'triggerApply',
|
|
12
|
+
'triggerDelete',
|
|
13
|
+
'triggerHistory',
|
|
14
|
+
'triggerList',
|
|
15
|
+
'triggerUpdate'
|
|
16
|
+
|
|
17
|
+
let :app do
|
|
18
|
+
Geotrigger::Application.new client_id: CONF[:client_id],
|
|
19
|
+
client_secret: CONF[:client_secret]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'fetches permissions' do
|
|
23
|
+
ps = app.permissions
|
|
24
|
+
ps.should_not be nil
|
|
25
|
+
ps.should be_a Hash
|
|
26
|
+
ps.keys.should include *PERMS
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'sets permissions' do
|
|
30
|
+
PERMS.each do |p|
|
|
31
|
+
ps = app.permissions
|
|
32
|
+
_ps = ps.merge p => !ps[p]
|
|
33
|
+
app.permissions = _ps
|
|
34
|
+
__ps = app.permissions
|
|
35
|
+
__ps.should eq ps.merge(p => !ps[p])
|
|
36
|
+
app.permissions = ps
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'fetches devices' do
|
|
41
|
+
ds = app.devices
|
|
42
|
+
ds.should_not be nil
|
|
43
|
+
ds.should be_a Array
|
|
44
|
+
ds.first.should be_a Geotrigger::Device unless ds.empty?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'fetches tags' do
|
|
48
|
+
ts = app.tags
|
|
49
|
+
ts.should_not be nil
|
|
50
|
+
ts.should be_a Array
|
|
51
|
+
ts.first.should be_a Geotrigger::Tag unless ts.empty?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'fetches triggers' do
|
|
55
|
+
ts = app.triggers
|
|
56
|
+
ts.should_not be nil
|
|
57
|
+
ts.should be_a Array
|
|
58
|
+
ts.first.should be_a Geotrigger::Trigger unless ts.empty?
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require_relative '../helper'
|
|
2
|
+
|
|
3
|
+
describe Geotrigger::Device do
|
|
4
|
+
|
|
5
|
+
let :dev do
|
|
6
|
+
s = GT::AGO::Session.new client_id: CONF[:client_id],
|
|
7
|
+
type: :device
|
|
8
|
+
|
|
9
|
+
# can't use this because GT doesn't know it yet
|
|
10
|
+
#
|
|
11
|
+
ago_did = s.device_data['deviceId']
|
|
12
|
+
|
|
13
|
+
# make a call to GT so it learns of new device
|
|
14
|
+
#
|
|
15
|
+
at = s.access_token
|
|
16
|
+
r = HTTPClient.new.get Geotrigger::Session::BASE_URL % 'device/list',
|
|
17
|
+
nil,
|
|
18
|
+
'Authorization' => "Bearer #{at}"
|
|
19
|
+
|
|
20
|
+
gt_did = JSON.parse(r.body)['devices'][0]['deviceId']
|
|
21
|
+
|
|
22
|
+
# assert ids are the same
|
|
23
|
+
#
|
|
24
|
+
ago_did.should eq gt_did
|
|
25
|
+
|
|
26
|
+
GT::Device.new client_id: CONF[:client_id],
|
|
27
|
+
client_secret: CONF[:client_secret],
|
|
28
|
+
device_id: ago_did
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'fetches tags' do
|
|
32
|
+
ts = dev.tags
|
|
33
|
+
ts.should_not be nil
|
|
34
|
+
ts.should be_a Array
|
|
35
|
+
ts.first.should be_a GT::Tag
|
|
36
|
+
ts.first.name.should eq dev.default_tag
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'knows the default tag' do
|
|
40
|
+
dev.default_tag =~ /^device:\S+$/
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'updates' do
|
|
44
|
+
dev.properties = {'foo' => 'bar'}
|
|
45
|
+
dev.trackingProfile = 'adaptive'
|
|
46
|
+
dev.save
|
|
47
|
+
dev.properties.should eq({'foo' => 'bar'})
|
|
48
|
+
dev.trackingProfile.should eq 'adaptive'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'adds tags' do
|
|
52
|
+
ts = dev.tags
|
|
53
|
+
ts.length.should eq 1
|
|
54
|
+
dev.add_tags 'foo', 'bar'
|
|
55
|
+
dev.save
|
|
56
|
+
ts = dev.tags
|
|
57
|
+
ts.length.should eq 3
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'sets tags' do
|
|
61
|
+
ts = dev.tags
|
|
62
|
+
ts.length.should eq 1
|
|
63
|
+
dev.tags = dev.default_tag, 'fu', 'bat'
|
|
64
|
+
dev.save
|
|
65
|
+
ts = dev.tags
|
|
66
|
+
ts.length.should eq 3
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'removes tags' do
|
|
70
|
+
dev.tags = dev.default_tag, 'fizz', 'buzz'
|
|
71
|
+
dev.save
|
|
72
|
+
sleep 3
|
|
73
|
+
ts = dev.tags
|
|
74
|
+
ts.length.should eq 3
|
|
75
|
+
dev.remove_tags 'fizz', 'buzz'
|
|
76
|
+
dev.save
|
|
77
|
+
ts = dev.tags
|
|
78
|
+
ts.length.should eq 1
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require_relative '../helper'
|
|
2
|
+
|
|
3
|
+
describe Geotrigger::AGO::Session do
|
|
4
|
+
|
|
5
|
+
def session_should_be_ok agos
|
|
6
|
+
agos.access_token.should_not be nil
|
|
7
|
+
agos.ago_data.should_not be nil
|
|
8
|
+
agos.ago_data.keys.should include 'access_token', 'expires_in', :expires_at
|
|
9
|
+
(agos.ago_data[:expires_at] > Time.now).should be true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'fetches an access token for client credentials' do
|
|
13
|
+
session_should_be_ok Geotrigger::AGO::Session.new client_id: CONF[:client_id],
|
|
14
|
+
client_secret: CONF[:client_secret]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'fetches access and refresh tokens for client id' do
|
|
18
|
+
session_should_be_ok Geotrigger::AGO::Session.new client_id: CONF[:client_id],
|
|
19
|
+
type: :device
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'fetches access token for client id and refresh token' do
|
|
23
|
+
session_should_be_ok Geotrigger::AGO::Session.new client_id: CONF[:client_id],
|
|
24
|
+
refresh_token: CONF[:refresh_token],
|
|
25
|
+
type: :device
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'updates an expired access token with client credentials' do
|
|
29
|
+
agos = Geotrigger::AGO::Session.new client_id: CONF[:client_id],
|
|
30
|
+
client_secret: CONF[:client_secret]
|
|
31
|
+
at = agos.access_token
|
|
32
|
+
Timecop.travel agos.ago_data[:expires_at] do
|
|
33
|
+
_at = agos.access_token
|
|
34
|
+
session_should_be_ok agos
|
|
35
|
+
at.should_not eq _at
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'updates an expired access token without given refresh token' do
|
|
40
|
+
agos = Geotrigger::AGO::Session.new client_id: CONF[:client_id],
|
|
41
|
+
type: :device
|
|
42
|
+
at = agos.access_token
|
|
43
|
+
Timecop.travel agos.ago_data[:expires_at] do
|
|
44
|
+
_at = agos.access_token
|
|
45
|
+
session_should_be_ok agos
|
|
46
|
+
at.should_not eq _at
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'updates an expired access token given refresh token' do
|
|
51
|
+
agos = Geotrigger::AGO::Session.new client_id: CONF[:client_id],
|
|
52
|
+
refresh_token: CONF[:refresh_token],
|
|
53
|
+
type: :device
|
|
54
|
+
at = agos.access_token
|
|
55
|
+
Timecop.travel agos.ago_data[:expires_at] do
|
|
56
|
+
_at = agos.access_token
|
|
57
|
+
session_should_be_ok agos
|
|
58
|
+
at.should_not eq _at
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe Geotrigger::Session do
|
|
65
|
+
|
|
66
|
+
it 'fetches an access token for client credentials' do
|
|
67
|
+
s = Geotrigger::Session.new client_id: CONF[:client_id],
|
|
68
|
+
client_secret: CONF[:client_secret]
|
|
69
|
+
s.access_token.should_not be nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'fetches an access token for client id' do
|
|
73
|
+
s = Geotrigger::Session.new client_id: CONF[:client_id],
|
|
74
|
+
type: :device
|
|
75
|
+
s.access_token.should_not be nil
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'uses a given access token' do
|
|
79
|
+
s = Geotrigger::Session.new client_id: CONF[:client_id],
|
|
80
|
+
client_secret: CONF[:client_secret]
|
|
81
|
+
s.access_token = 'foo'
|
|
82
|
+
s.access_token.should eq 'foo'
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'uses a given refresh token' do
|
|
86
|
+
s = Geotrigger::Session.new client_id: CONF[:client_id],
|
|
87
|
+
refresh_token: CONF[:refresh_token],
|
|
88
|
+
type: :device
|
|
89
|
+
s.access_token.should_not be nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'knows what type it is' do
|
|
93
|
+
s = Geotrigger::Session.new client_id: CONF[:client_id],
|
|
94
|
+
client_secret: CONF[:client_secret]
|
|
95
|
+
s.application?.should be true
|
|
96
|
+
s.device?.should be false
|
|
97
|
+
s = Geotrigger::Session.new client_id: CONF[:client_id],
|
|
98
|
+
type: :device
|
|
99
|
+
s.application?.should be false
|
|
100
|
+
s.device?.should be true
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'raises errors correctly' do
|
|
104
|
+
s = Geotrigger::Session.new
|
|
105
|
+
->{ s.post 'application/permissions' }.should raise_error
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require_relative '../helper'
|
|
2
|
+
|
|
3
|
+
describe Geotrigger::Tag do
|
|
4
|
+
|
|
5
|
+
TAG_PERMS = 'deviceList',
|
|
6
|
+
'deviceLocation',
|
|
7
|
+
'deviceTagging',
|
|
8
|
+
'deviceToken',
|
|
9
|
+
'discoverable',
|
|
10
|
+
'triggerApply',
|
|
11
|
+
'triggerDelete',
|
|
12
|
+
'triggerHistory',
|
|
13
|
+
'triggerList',
|
|
14
|
+
'triggerUpdate'
|
|
15
|
+
|
|
16
|
+
let :session do
|
|
17
|
+
Geotrigger::Session.new client_id: CONF[:client_id],
|
|
18
|
+
client_secret: CONF[:client_secret]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
let :tag do
|
|
22
|
+
GT::Tag.create session, tags: "foo#{Time.now.to_i}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
let :dev do
|
|
26
|
+
s = GT::AGO::Session.new client_id: CONF[:client_id],
|
|
27
|
+
type: :device
|
|
28
|
+
|
|
29
|
+
# can't use this because GT doesn't know it yet
|
|
30
|
+
#
|
|
31
|
+
ago_did = s.device_data['deviceId']
|
|
32
|
+
|
|
33
|
+
# make a call to GT so it learns of new device
|
|
34
|
+
#
|
|
35
|
+
at = s.access_token
|
|
36
|
+
r = HTTPClient.new.get Geotrigger::Session::BASE_URL % 'device/list',
|
|
37
|
+
nil,
|
|
38
|
+
'Authorization' => "Bearer #{at}"
|
|
39
|
+
|
|
40
|
+
gt_did = JSON.parse(r.body)['devices'][0]['deviceId']
|
|
41
|
+
|
|
42
|
+
# assert ids are the same
|
|
43
|
+
#
|
|
44
|
+
ago_did.should eq gt_did
|
|
45
|
+
|
|
46
|
+
GT::Device.new client_id: CONF[:client_id],
|
|
47
|
+
client_secret: CONF[:client_secret],
|
|
48
|
+
device_id: ago_did
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
let :trigger_opts do
|
|
52
|
+
{
|
|
53
|
+
'condition' => {
|
|
54
|
+
'direction' => 'enter',
|
|
55
|
+
'geo' => {
|
|
56
|
+
'latitude' => 45.5165,
|
|
57
|
+
'longitude' => -122.6764,
|
|
58
|
+
'distance' => 100
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
'action' => {
|
|
62
|
+
'trackingProfile' => 'adaptive'
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
let :trigger do
|
|
68
|
+
GT::Trigger.create session, trigger_opts
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'creates a tag' do
|
|
72
|
+
t = tag
|
|
73
|
+
t.name.should match /^foo/
|
|
74
|
+
TAG_PERMS.each {|p| t.__send__(p).should_not be nil}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'fetches triggers' do
|
|
78
|
+
t = tag
|
|
79
|
+
trig = trigger
|
|
80
|
+
trig.add_tags t.name
|
|
81
|
+
trig.save
|
|
82
|
+
t.triggers.first.data.should eq trig.data
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'fetches devices' do
|
|
86
|
+
t = tag
|
|
87
|
+
d = dev
|
|
88
|
+
d.add_tags t.name
|
|
89
|
+
d.save
|
|
90
|
+
t.devices.first.device_id.should eq d.device_id
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'updates permissions' do
|
|
94
|
+
t = tag
|
|
95
|
+
t.name.should match /^foo/
|
|
96
|
+
t_data = t.data.dup
|
|
97
|
+
TAG_PERMS.each do |p|
|
|
98
|
+
t.data[p] = !t_data[p]
|
|
99
|
+
doid = t.data.object_id
|
|
100
|
+
t.save
|
|
101
|
+
t.data.object_id.should_not eq doid
|
|
102
|
+
t.data[p].should eq !t_data[p]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require_relative '../helper'
|
|
2
|
+
|
|
3
|
+
describe Geotrigger::Trigger do
|
|
4
|
+
|
|
5
|
+
let :session do
|
|
6
|
+
Geotrigger::Session.new client_id: CONF[:client_id],
|
|
7
|
+
client_secret: CONF[:client_secret]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let :opts do
|
|
11
|
+
{
|
|
12
|
+
'condition' => {
|
|
13
|
+
'direction' => 'enter',
|
|
14
|
+
'geo' => {
|
|
15
|
+
'latitude' => 45.5165,
|
|
16
|
+
'longitude' => -122.6764,
|
|
17
|
+
'distance' => 100
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
'action' => {
|
|
21
|
+
'trackingProfile' => 'adaptive'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
let :trigger do
|
|
27
|
+
GT::Trigger.create session, opts
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'should create a trigger' do
|
|
31
|
+
t = trigger
|
|
32
|
+
t.trigger_id.should_not be nil
|
|
33
|
+
t.condition.should eq opts['condition']
|
|
34
|
+
t.action.should eq opts['action']
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'fetches tags' do
|
|
38
|
+
ts = trigger.tags
|
|
39
|
+
ts.should_not be nil
|
|
40
|
+
ts.should be_a Array
|
|
41
|
+
ts.first.should be_a GT::Tag
|
|
42
|
+
ts.first.name.should eq trigger.default_tag
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'knows the default tag' do
|
|
46
|
+
trigger.default_tag =~ /^trigger:\S+$/
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'updates' do
|
|
50
|
+
trigger.properties = {'foo' => 'bar'}
|
|
51
|
+
trigger.action['trackingProfile'] = 'adaptive'
|
|
52
|
+
trigger.save
|
|
53
|
+
trigger.properties.should eq({'foo' => 'bar'})
|
|
54
|
+
trigger.action['trackingProfile'].should eq 'adaptive'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'adds tags' do
|
|
58
|
+
ts = trigger.tags
|
|
59
|
+
ts.length.should eq 1
|
|
60
|
+
trigger.add_tags 'foo', 'bar'
|
|
61
|
+
trigger.save
|
|
62
|
+
ts = trigger.tags
|
|
63
|
+
ts.length.should eq 3
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'sets tags' do
|
|
67
|
+
ts = trigger.tags
|
|
68
|
+
ts.length.should eq 1
|
|
69
|
+
trigger.tags = trigger.default_tag, 'fu', 'bat'
|
|
70
|
+
trigger.save
|
|
71
|
+
ts = trigger.tags
|
|
72
|
+
ts.length.should eq 3
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'removes tags' do
|
|
76
|
+
trigger.tags = trigger.default_tag, 'fizz', 'buzz'
|
|
77
|
+
trigger.save
|
|
78
|
+
sleep 3
|
|
79
|
+
ts = trigger.tags
|
|
80
|
+
ts.length.should eq 3
|
|
81
|
+
trigger.remove_tags 'fizz', 'buzz'
|
|
82
|
+
trigger.save
|
|
83
|
+
ts = trigger.tags
|
|
84
|
+
ts.length.should eq 1
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
end
|
data/spec/helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: geotrigger
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kenichi Nakamura
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2013-11-26 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: httpclient
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - '>='
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - '>='
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: timecop
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - '>='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
description: A small ruby client for Esri's Geotrigger service
|
|
42
|
+
email:
|
|
43
|
+
- kenichi.nakamura@gmail.com
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- .gitignore
|
|
49
|
+
- Gemfile
|
|
50
|
+
- README.md
|
|
51
|
+
- geotrigger.gemspec
|
|
52
|
+
- lib/ext/string.rb
|
|
53
|
+
- lib/geotrigger.rb
|
|
54
|
+
- lib/geotrigger/ago/session.rb
|
|
55
|
+
- lib/geotrigger/application.rb
|
|
56
|
+
- lib/geotrigger/device.rb
|
|
57
|
+
- lib/geotrigger/model.rb
|
|
58
|
+
- lib/geotrigger/session.rb
|
|
59
|
+
- lib/geotrigger/tag.rb
|
|
60
|
+
- lib/geotrigger/trigger.rb
|
|
61
|
+
- lib/geotrigger/version.rb
|
|
62
|
+
- spec/config.yml.example
|
|
63
|
+
- spec/geotrigger/application_spec.rb
|
|
64
|
+
- spec/geotrigger/device_spec.rb
|
|
65
|
+
- spec/geotrigger/geotrigger_spec.rb
|
|
66
|
+
- spec/geotrigger/tag_spec.rb
|
|
67
|
+
- spec/geotrigger/trigger_spec.rb
|
|
68
|
+
- spec/helper.rb
|
|
69
|
+
homepage: https://github.com/esripdx/geotrigger-ruby
|
|
70
|
+
licenses:
|
|
71
|
+
- apache
|
|
72
|
+
metadata: {}
|
|
73
|
+
post_install_message:
|
|
74
|
+
rdoc_options: []
|
|
75
|
+
require_paths:
|
|
76
|
+
- lib
|
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - '>='
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - '>='
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '0'
|
|
87
|
+
requirements: []
|
|
88
|
+
rubyforge_project:
|
|
89
|
+
rubygems_version: 2.0.3
|
|
90
|
+
signing_key:
|
|
91
|
+
specification_version: 4
|
|
92
|
+
summary: A small ruby client for Esri's Geotrigger service
|
|
93
|
+
test_files:
|
|
94
|
+
- spec/config.yml.example
|
|
95
|
+
- spec/geotrigger/application_spec.rb
|
|
96
|
+
- spec/geotrigger/device_spec.rb
|
|
97
|
+
- spec/geotrigger/geotrigger_spec.rb
|
|
98
|
+
- spec/geotrigger/tag_spec.rb
|
|
99
|
+
- spec/geotrigger/trigger_spec.rb
|
|
100
|
+
- spec/helper.rb
|