intellisense-ruby 0.6.5
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/Gemfile +2 -0
- data/Gemfile.lock +49 -0
- data/README.md +33 -0
- data/Rakefile +7 -0
- data/intellisense-ruby-0.6.4.gem +0 -0
- data/intellisense-ruby.gemspec +25 -0
- data/intellisense-ruby.sublime-project +8 -0
- data/intellisense-ruby.sublime-workspace +2398 -0
- data/lib/intellisense-ruby/client.rb +269 -0
- data/lib/intellisense-ruby/consumer.rb +106 -0
- data/lib/intellisense-ruby/defaults.rb +19 -0
- data/lib/intellisense-ruby/json.rb +27 -0
- data/lib/intellisense-ruby/request.rb +53 -0
- data/lib/intellisense-ruby/response.rb +17 -0
- data/lib/intellisense-ruby/sqs_publisher.rb +53 -0
- data/lib/intellisense-ruby/version.rb +3 -0
- data/lib/intellisense-ruby.rb +50 -0
- data/spec/client_spec.rb +118 -0
- data/spec/consumer_spec.rb +88 -0
- data/spec/module_spec.rb +81 -0
- data/spec/spec_helper.rb +55 -0
- data/spec/sqs_publisher_spec.rb +28 -0
- metadata +190 -0
@@ -0,0 +1,269 @@
|
|
1
|
+
|
2
|
+
require 'time'
|
3
|
+
require 'thread'
|
4
|
+
require 'intellisense-ruby/defaults'
|
5
|
+
require 'intellisense-ruby/consumer'
|
6
|
+
require 'intellisense-ruby/request'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
module IntellisenseRuby
|
10
|
+
|
11
|
+
class Client
|
12
|
+
|
13
|
+
# public: Creates a new client
|
14
|
+
#
|
15
|
+
# options - Hash
|
16
|
+
# :secret - String of your project's secret
|
17
|
+
# :max_queue_size - Fixnum of the max calls to remain queued (optional)
|
18
|
+
# :on_error - Proc which handles error calls from the API
|
19
|
+
def initialize(options = {})
|
20
|
+
|
21
|
+
@queue = Queue.new
|
22
|
+
@secret = options[:secret]
|
23
|
+
@max_queue_size = options[:max_queue_size] || IntellisenseRuby::Defaults::Queue::MAX_SIZE
|
24
|
+
|
25
|
+
check_api_key
|
26
|
+
|
27
|
+
@consumer = IntellisenseRuby::Consumer.new(@queue, @secret, options)
|
28
|
+
@thread = Thread.new { @consumer.run }
|
29
|
+
|
30
|
+
@logger = options[:logger]
|
31
|
+
log('DEBUG: ############## SENSOR initialized!')
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# public: describe entities in the graph
|
36
|
+
#
|
37
|
+
# entity - Hash
|
38
|
+
# :type - type of entity (program, course, user, etc.)
|
39
|
+
# :entity_id - entity Id
|
40
|
+
# :properties - Hash of entity properties (optional, but recommended)
|
41
|
+
# :timestamp - Time of when the event occurred. (optional)
|
42
|
+
#
|
43
|
+
#
|
44
|
+
def describe(entity)
|
45
|
+
|
46
|
+
log('DEBUG: ############## describing entity' + entity.to_s)
|
47
|
+
|
48
|
+
check_api_key
|
49
|
+
|
50
|
+
type = entity[:type]
|
51
|
+
entity_id = entity[:entity_id].to_s
|
52
|
+
properties = entity[:properties] || {}
|
53
|
+
timestamp = entity[:timestamp] || Time.new
|
54
|
+
|
55
|
+
check_timestamp(timestamp)
|
56
|
+
|
57
|
+
if type.nil? || type.empty?
|
58
|
+
fail ArgumentError, 'Must supply type as a non-empty string'
|
59
|
+
end
|
60
|
+
|
61
|
+
if entity_id.nil? || entity_id.empty?
|
62
|
+
fail ArgumentError, 'Must supply entity_id as a non-empty string'
|
63
|
+
end
|
64
|
+
|
65
|
+
fail ArgumentError, 'Properties must be a Hash' unless properties.is_a? Hash
|
66
|
+
|
67
|
+
enqueue({ type: type,
|
68
|
+
entityId: entity_id,
|
69
|
+
properties: properties,
|
70
|
+
timestamp: timestamp.iso8601,
|
71
|
+
action: 'describe'})
|
72
|
+
end
|
73
|
+
|
74
|
+
# public: describe entities in the graph
|
75
|
+
#
|
76
|
+
# entity - Hash
|
77
|
+
# :type - type of entity (program, course, user, etc.)
|
78
|
+
# :id - entity Id
|
79
|
+
# :properties - Hash of entity properties (optional, but recommended)
|
80
|
+
# :timestamp - Time of when the event occurred. (optional)
|
81
|
+
#
|
82
|
+
#
|
83
|
+
def track(learning_event)
|
84
|
+
|
85
|
+
log('DEBUG: ############## recording learning event!')
|
86
|
+
|
87
|
+
check_api_key
|
88
|
+
|
89
|
+
type = options[:type]
|
90
|
+
entity_id = options[:entity_id].to_s
|
91
|
+
properties = options[:properties] || {}
|
92
|
+
timestamp = options[:timestamp] || Time.new
|
93
|
+
|
94
|
+
check_timestamp(timestamp)
|
95
|
+
|
96
|
+
if type.nil? || type.empty?
|
97
|
+
fail ArgumentError, 'Must supply type as a non-empty string'
|
98
|
+
end
|
99
|
+
|
100
|
+
fail ArgumentError, 'Properties must be a Hash' unless properties.is_a? Hash
|
101
|
+
|
102
|
+
enqueue({ type: type,
|
103
|
+
entityId: entity_id,
|
104
|
+
properties: properties,
|
105
|
+
timestamp: timestamp.iso8601,
|
106
|
+
action: 'measure'})
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# public: Synchronously waits until the consumer has flushed the queue.
|
111
|
+
# Use only for scripts which are not long-running, and will
|
112
|
+
# specifically exit
|
113
|
+
#
|
114
|
+
def flush
|
115
|
+
while !@queue.empty? || @consumer.is_requesting?
|
116
|
+
sleep(0.1)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# public: Tracks an event
|
121
|
+
#
|
122
|
+
# options - Hash
|
123
|
+
# :event - String of event name.
|
124
|
+
# :user_id - String of the user id.
|
125
|
+
# :properties - Hash of event properties. (optional)
|
126
|
+
# :timestamp - Time of when the event occurred. (optional)
|
127
|
+
# :context - Hash of context. (optional)
|
128
|
+
def track(options)
|
129
|
+
|
130
|
+
check_api_key
|
131
|
+
|
132
|
+
event = options[:event]
|
133
|
+
user_id = options[:user_id].to_s
|
134
|
+
properties = options[:properties] || {}
|
135
|
+
timestamp = options[:timestamp] || Time.new
|
136
|
+
context = options[:context] || {}
|
137
|
+
|
138
|
+
ensure_user(user_id)
|
139
|
+
check_timestamp(timestamp)
|
140
|
+
|
141
|
+
if event.nil? || event.empty?
|
142
|
+
fail ArgumentError, 'Must supply event as a non-empty string'
|
143
|
+
end
|
144
|
+
|
145
|
+
fail ArgumentError, 'Properties must be a Hash' unless properties.is_a? Hash
|
146
|
+
|
147
|
+
add_context(context)
|
148
|
+
|
149
|
+
enqueue({ event: event,
|
150
|
+
userId: user_id,
|
151
|
+
context: context,
|
152
|
+
properties: properties,
|
153
|
+
timestamp: timestamp.iso8601,
|
154
|
+
action: 'track' })
|
155
|
+
end
|
156
|
+
|
157
|
+
# public: Identifies a user
|
158
|
+
#
|
159
|
+
# options - Hash
|
160
|
+
# :user_id - String of the user id
|
161
|
+
# :traits - Hash of user traits. (optional)
|
162
|
+
# :timestamp - Time of when the event occurred. (optional)
|
163
|
+
# :context - Hash of context. (optional)
|
164
|
+
def identify(options)
|
165
|
+
|
166
|
+
check_api_key
|
167
|
+
|
168
|
+
user_id = options[:user_id].to_s
|
169
|
+
traits = options[:traits] || {}
|
170
|
+
timestamp = options[:timestamp] || Time.new
|
171
|
+
context = options[:context] || {}
|
172
|
+
|
173
|
+
ensure_user(user_id)
|
174
|
+
check_timestamp(timestamp)
|
175
|
+
|
176
|
+
fail ArgumentError, 'Must supply traits as a hash' unless traits.is_a? Hash
|
177
|
+
|
178
|
+
add_context(context)
|
179
|
+
|
180
|
+
enqueue({ userId: user_id,
|
181
|
+
context: context,
|
182
|
+
traits: traits,
|
183
|
+
timestamp: timestamp.iso8601,
|
184
|
+
action: 'identify' })
|
185
|
+
end
|
186
|
+
|
187
|
+
# public: Aliases a user from one id to another
|
188
|
+
#
|
189
|
+
# options - Hash
|
190
|
+
# :from - String of the id to alias from
|
191
|
+
# :to - String of the id to alias to
|
192
|
+
# :timestamp - Time of when the alias occured (optional)
|
193
|
+
# :context - Hash of context (optional)
|
194
|
+
def alias(options)
|
195
|
+
|
196
|
+
check_api_key
|
197
|
+
|
198
|
+
from = options[:from].to_s
|
199
|
+
to = options[:to].to_s
|
200
|
+
timestamp = options[:timestamp] || Time.new
|
201
|
+
context = options[:context] || {}
|
202
|
+
|
203
|
+
ensure_user(from)
|
204
|
+
ensure_user(to)
|
205
|
+
check_timestamp(timestamp)
|
206
|
+
|
207
|
+
add_context(context)
|
208
|
+
|
209
|
+
enqueue({ from: from,
|
210
|
+
to: to,
|
211
|
+
context: context,
|
212
|
+
timestamp: timestamp.iso8601,
|
213
|
+
action: 'alias' })
|
214
|
+
end
|
215
|
+
|
216
|
+
# public: Returns the number of queued messages
|
217
|
+
#
|
218
|
+
# returns Fixnum of messages in the queue
|
219
|
+
def queued_messages
|
220
|
+
@queue.length
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
# private: Enqueues the action.
|
226
|
+
#
|
227
|
+
# returns Boolean of whether the item was added to the queue.
|
228
|
+
def enqueue(action)
|
229
|
+
queue_full = @queue.length >= @max_queue_size
|
230
|
+
@queue << action.to_json unless queue_full
|
231
|
+
|
232
|
+
!queue_full
|
233
|
+
end
|
234
|
+
|
235
|
+
# private: Ensures that a user id was passed in.
|
236
|
+
#
|
237
|
+
# user_id - String of the user id
|
238
|
+
#
|
239
|
+
def ensure_user(user_id)
|
240
|
+
fail ArgumentError, 'Must supply a non-empty user_id' if user_id.empty?
|
241
|
+
end
|
242
|
+
|
243
|
+
# private: Adds contextual information to the call
|
244
|
+
#
|
245
|
+
# context - Hash of call context
|
246
|
+
def add_context(context)
|
247
|
+
context[:library] = 'intellisense-ruby'
|
248
|
+
end
|
249
|
+
|
250
|
+
# private: Checks that the secret is properly initialized
|
251
|
+
def check_api_key
|
252
|
+
fail 'Secret must be initialized' if @secret.nil?
|
253
|
+
end
|
254
|
+
|
255
|
+
# private: Checks the timstamp option to make sure it is a Time.
|
256
|
+
def check_timestamp(timestamp)
|
257
|
+
fail ArgumentError, 'Timestamp must be a Time' unless timestamp.is_a? Time
|
258
|
+
end
|
259
|
+
|
260
|
+
# private: log the requested message
|
261
|
+
def log(message)
|
262
|
+
if !@logger.nil?
|
263
|
+
@logger.debug(message)
|
264
|
+
else
|
265
|
+
puts message
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
|
2
|
+
require 'intellisense-ruby/defaults'
|
3
|
+
require 'intellisense-ruby/request'
|
4
|
+
require 'intellisense-ruby/sqs_publisher'
|
5
|
+
|
6
|
+
module IntellisenseRuby
|
7
|
+
|
8
|
+
class Consumer
|
9
|
+
|
10
|
+
# public: Creates a new consumer
|
11
|
+
#
|
12
|
+
# The consumer continuously takes messages off the queue
|
13
|
+
# and makes requests to the intellify api
|
14
|
+
#
|
15
|
+
# queue - Queue synchronized between client and consumer
|
16
|
+
# secret - String of the project's secret
|
17
|
+
# options - Hash of consumer options
|
18
|
+
# batch_size - Fixnum of how many items to send in a batch
|
19
|
+
# on_error - Proc of what to do on an error
|
20
|
+
#
|
21
|
+
def initialize(queue, secret, options = {})
|
22
|
+
@queue = queue
|
23
|
+
@secret = secret
|
24
|
+
@batch_size = options[:batch_size] || IntellisenseRuby::Defaults::Queue::BATCH_SIZE
|
25
|
+
@on_error = options[:on_error] || Proc.new { |status, error| }
|
26
|
+
@transport = options[:transport] || IntellisenseRuby::Defaults::Request::TRANSPORT
|
27
|
+
|
28
|
+
@current_batch = []
|
29
|
+
|
30
|
+
@mutex = Mutex.new
|
31
|
+
|
32
|
+
@logger = options[:logger]
|
33
|
+
log('DEBUG ############## SENSOR initialized! with transport ' + @transport)
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
# public: Continuously runs the loop to check for new events
|
38
|
+
#
|
39
|
+
def run
|
40
|
+
while true
|
41
|
+
flush
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# public: Flush some events from our queue
|
46
|
+
#
|
47
|
+
def flush
|
48
|
+
# Block until we have something to send
|
49
|
+
item = @queue.pop()
|
50
|
+
|
51
|
+
# Synchronize on additions to the current batch
|
52
|
+
@mutex.synchronize {
|
53
|
+
@current_batch << item
|
54
|
+
until @current_batch.length >= @batch_size || @queue.empty?
|
55
|
+
@current_batch << @queue.pop()
|
56
|
+
end
|
57
|
+
}
|
58
|
+
|
59
|
+
#log("about to send messages " + @current_batch)
|
60
|
+
|
61
|
+
case @transport
|
62
|
+
when 'http'
|
63
|
+
puts 'using http transport'
|
64
|
+
req = IntellisenseRuby::Request.new
|
65
|
+
res = req.post(@secret, @current_batch)
|
66
|
+
@on_error.call(res.status, res.error) unless res.status == 200
|
67
|
+
@mutex.synchronize {
|
68
|
+
@current_batch = []
|
69
|
+
}
|
70
|
+
when 'sqs'
|
71
|
+
log('DEBUG ############## SENSOR using SQS transport to send ' + @current_batch.to_s)
|
72
|
+
sqs = IntellisenseRuby::SQS_Publisher.new logger: @logger
|
73
|
+
sqs.send_message(@current_batch)
|
74
|
+
@mutex.synchronize {
|
75
|
+
@current_batch = []
|
76
|
+
}
|
77
|
+
else
|
78
|
+
# cannot do anything
|
79
|
+
puts 'UNKNOWN transport - error'
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# public: Check whether we have outstanding requests.
|
85
|
+
#
|
86
|
+
def is_requesting?
|
87
|
+
requesting = nil
|
88
|
+
@mutex.synchronize {
|
89
|
+
requesting = !@current_batch.empty?
|
90
|
+
}
|
91
|
+
requesting
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# private: log the requested message
|
97
|
+
def log(message)
|
98
|
+
if !@logger.nil?
|
99
|
+
@logger.debug(message)
|
100
|
+
else
|
101
|
+
puts message
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module IntellisenseRuby
|
3
|
+
module Defaults
|
4
|
+
|
5
|
+
module Request
|
6
|
+
TRANSPORT = 'http'
|
7
|
+
BASE_URL = 'http://www.intellifylearning.com/intellify' unless defined? IntellisenseRuby::Defaults::Request::BASE_URL
|
8
|
+
PATH = '/v1/import' unless defined? IntellisenseRuby::Defaults::Request::PATH
|
9
|
+
SSL = { verify: false } unless defined? IntellisenseRuby::Defaults::Request::SSL
|
10
|
+
HEADERS = { accept: 'application/json' } unless defined? IntellisenseRuby::Defaults::Request::HEADERS
|
11
|
+
end
|
12
|
+
|
13
|
+
module Queue
|
14
|
+
BATCH_SIZE = 100 unless defined? IntellisenseRuby::Defaults::Queue::BATCH_SIZE
|
15
|
+
MAX_SIZE = 10000 unless defined? IntellisenseRuby::Defaults::Queue::MAX_SIZE
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module IntellisenseRuby
|
4
|
+
|
5
|
+
#
|
6
|
+
# JSON Wrapper module using MultiJson 1.3
|
7
|
+
#
|
8
|
+
module JSON
|
9
|
+
if MultiJson.respond_to?(:dump)
|
10
|
+
def self.dump(*args)
|
11
|
+
MultiJson.dump(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load(*args)
|
15
|
+
MultiJson.load(*args)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
def self.dump(*args)
|
19
|
+
MultiJson.encode(*args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.load(*args)
|
23
|
+
MultiJson.decode(*args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
require 'intellisense-ruby/defaults'
|
3
|
+
require 'intellisense-ruby/response'
|
4
|
+
require 'intellisense-ruby/json'
|
5
|
+
require 'faraday'
|
6
|
+
require 'faraday_middleware'
|
7
|
+
|
8
|
+
module IntellisenseRuby
|
9
|
+
|
10
|
+
class Request
|
11
|
+
|
12
|
+
# public: Creates a new request object to send analytics batch
|
13
|
+
#
|
14
|
+
def initialize(options = {})
|
15
|
+
|
16
|
+
options[:url] ||= IntellisenseRuby::Defaults::Request::BASE_URL
|
17
|
+
options[:ssl] ||= IntellisenseRuby::Defaults::Request::SSL
|
18
|
+
options[:headers] ||= IntellisenseRuby::Defaults::Request::HEADERS
|
19
|
+
@path = options[:path] || IntellisenseRuby::Defaults::Request::PATH
|
20
|
+
|
21
|
+
@conn = Faraday.new(options) do |faraday|
|
22
|
+
faraday.request :json
|
23
|
+
faraday.response :json, :content_type => /\bjson$/
|
24
|
+
faraday.adapter Faraday.default_adapter
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# public: Posts the secret and batch of messages to the API.
|
29
|
+
#
|
30
|
+
# returns - Response of the status and error if it exists
|
31
|
+
def post(secret, batch)
|
32
|
+
|
33
|
+
status, error = nil, nil
|
34
|
+
|
35
|
+
begin
|
36
|
+
res = @conn.post do |req|
|
37
|
+
req.options[:timeout] = 8
|
38
|
+
req.options[:open_timeout] = 3
|
39
|
+
req.url(@path)
|
40
|
+
req.body = IntellisenseRuby::JSON::dump(secret: secret, batch: batch)
|
41
|
+
end
|
42
|
+
status = res.status
|
43
|
+
error = res.body["error"]
|
44
|
+
|
45
|
+
rescue Exception => err
|
46
|
+
status = -1
|
47
|
+
error = "Connection error: #{err}"
|
48
|
+
end
|
49
|
+
|
50
|
+
IntellisenseRuby::Response.new(status, error)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
module IntellisenseRuby
|
3
|
+
|
4
|
+
class Response
|
5
|
+
|
6
|
+
attr_reader :status
|
7
|
+
attr_reader :error
|
8
|
+
|
9
|
+
# public: Simple class to wrap responses from the API
|
10
|
+
#
|
11
|
+
#
|
12
|
+
def initialize(status = 200, error = nil)
|
13
|
+
@status = status
|
14
|
+
@error = error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'intellisense-ruby/defaults'
|
2
|
+
require 'intellisense-ruby/request'
|
3
|
+
require 'aws-sdk'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
module IntellisenseRuby
|
7
|
+
|
8
|
+
class SQS_Publisher
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
|
12
|
+
@sqs = AWS::SQS.new(
|
13
|
+
:access_key_id => 'AKIAJPYU646KQOWWZ4SA',
|
14
|
+
:secret_access_key => 'oxoHfy9nKZCrDbvWFj5Z25ADQOykD/8uTxj18N6g')
|
15
|
+
|
16
|
+
@sqs_queue = @sqs.queues['https://sqs.us-east-1.amazonaws.com/691677686063/yoda-events']
|
17
|
+
|
18
|
+
@logger = options[:logger]
|
19
|
+
log('DEBUG ############## SQS_Publisher created! with queue ' + @sqs_queue.to_s)
|
20
|
+
|
21
|
+
#queue_urls = @sqs.queues.collect(&:url)
|
22
|
+
#queue = @sqs.queues[queue_urls[0]]
|
23
|
+
#pp queue
|
24
|
+
# msg = queue.send_message("TEST")
|
25
|
+
# puts "Sent message: #{msg.id}"
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def send_message(message = {})
|
30
|
+
|
31
|
+
return false unless @sqs_queue
|
32
|
+
|
33
|
+
log('DEBUG ############## SQS_Publisher created! sending message ' + message.to_s)
|
34
|
+
|
35
|
+
val = message.to_s
|
36
|
+
msg = @sqs_queue.send_message(val)
|
37
|
+
puts "Sent message: #{msg.id}"
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
# private: log the requested message
|
43
|
+
def log(message)
|
44
|
+
if !@logger.nil?
|
45
|
+
@logger.debug(message)
|
46
|
+
else
|
47
|
+
puts message
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'intellisense-ruby/version'
|
2
|
+
require 'intellisense-ruby/client'
|
3
|
+
|
4
|
+
module IntellisenseRuby
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
# By default use a single client for the module
|
9
|
+
def init(options = {})
|
10
|
+
@client = IntellisenseRuby::Client.new options
|
11
|
+
end
|
12
|
+
|
13
|
+
def describe(entity)
|
14
|
+
return false unless @client
|
15
|
+
@client.describe entity
|
16
|
+
end
|
17
|
+
|
18
|
+
def track(learning_event)
|
19
|
+
return false unless @client
|
20
|
+
@client.measure event
|
21
|
+
end
|
22
|
+
|
23
|
+
def track(options)
|
24
|
+
return false unless @client
|
25
|
+
@client.track(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def identify(options)
|
29
|
+
return false unless @client
|
30
|
+
@client.identify(options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def alias(options)
|
34
|
+
return false unless @client
|
35
|
+
@client.alias(options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def flush
|
39
|
+
return false unless @client
|
40
|
+
@client.flush
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
extend ClassMethods
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
# Alias for IntellisenseRuby
|
50
|
+
Intellisense = IntellisenseRuby
|