machineshop 0.0.4 → 1.0.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.
- checksums.yaml +4 -4
- data/Gemfile +3 -2
- data/lib/machineshop.rb +289 -53
- data/lib/machineshop/configuration.rb +1 -1
- data/lib/machineshop/data_source_types.rb +28 -0
- data/lib/machineshop/data_sources.rb +35 -0
- data/lib/machineshop/database.rb +34 -87
- data/lib/machineshop/errors/schema_error.rb +5 -0
- data/lib/machineshop/machineshop_object.rb +2 -1
- data/lib/machineshop/models/api_request.rb +27 -0
- data/lib/machineshop/models/people.rb +13 -0
- data/lib/machineshop/models/schema.rb +169 -0
- data/lib/machineshop/users.rb +43 -0
- data/lib/machineshop/util.rb +2 -1
- data/lib/machineshop/version.rb +1 -1
- data/machineshop.gemspec +16 -1
- data/spec/lib/customer_spec.rb +17 -39
- data/spec/lib/data_source.rb +136 -0
- data/spec/lib/data_source_type_spec.rb +77 -0
- data/spec/lib/database_spec.rb +43 -0
- data/spec/lib/device_instances.rb +10 -13
- data/spec/lib/device_spec.rb +13 -27
- data/spec/lib/mapping_spec.rb +3 -11
- data/spec/lib/meter_spec.rb +3 -8
- data/spec/lib/report_spec.rb +2 -8
- data/spec/lib/rule_spec.rb +37 -52
- data/spec/lib/test_spec.rb +47 -0
- data/spec/lib/user_spec.rb +4 -11
- data/spec/spec_helper.rb +0 -1
- metadata +49 -8
- data/Readme_old.bkmMd +0 -782
- data/spec/lib/api_calls_spec.rb +0 -624
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5398a18d7fa06b98439cd8fb269584d75470e086
|
4
|
+
data.tar.gz: 79a3b0359fd318cb575793e235b3c9d874e049ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91f0b27d60bc49ebd22a466b5522ecc449e0f3ab4d533c18d0c4a856fb69ba2e593c9938831efd16b0704ca16a37cda0452782ba0f048aaafeba707e470d2f10
|
7
|
+
data.tar.gz: 06609725eaf1067089ece7db9bbe045b11a13af8b821e86305bcc484749645730ba6688c2d35be197f595ea5fa2c0089617b7c1ec23ca269960a2c94642e4202
|
data/Gemfile
CHANGED
data/lib/machineshop.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require "machineshop/version"
|
2
2
|
|
3
|
+
# require 'awesome_print'
|
4
|
+
# require 'will_paginate'
|
5
|
+
|
3
6
|
require 'cgi'
|
4
7
|
require 'set'
|
5
8
|
require 'openssl'
|
@@ -11,7 +14,7 @@ require 'multi_json'
|
|
11
14
|
#configurations
|
12
15
|
require 'machineshop/configuration'
|
13
16
|
#database
|
14
|
-
|
17
|
+
require 'machineshop/database'
|
15
18
|
|
16
19
|
# API operations
|
17
20
|
require 'machineshop/api_operations/create'
|
@@ -24,6 +27,11 @@ require 'machineshop/api_operations/update'
|
|
24
27
|
require 'machineshop/machineshop_object'
|
25
28
|
require 'machineshop/api_resource'
|
26
29
|
require 'machineshop/device_instance'
|
30
|
+
|
31
|
+
require 'machineshop/data_sources'
|
32
|
+
require 'machineshop/data_source_types'
|
33
|
+
|
34
|
+
|
27
35
|
require 'machineshop/device'
|
28
36
|
require 'machineshop/machineshop_object'
|
29
37
|
require 'machineshop/mapping'
|
@@ -31,7 +39,8 @@ require 'machineshop/meter'
|
|
31
39
|
require 'machineshop/report'
|
32
40
|
require 'machineshop/customer'
|
33
41
|
require 'machineshop/rule'
|
34
|
-
require 'machineshop/user'
|
42
|
+
# require 'machineshop/user'
|
43
|
+
require 'machineshop/users'
|
35
44
|
require 'machineshop/utility'
|
36
45
|
require 'machineshop/json'
|
37
46
|
require 'machineshop/util'
|
@@ -43,14 +52,15 @@ require 'machineshop/errors/invalid_request_error'
|
|
43
52
|
require 'machineshop/errors/authentication_error'
|
44
53
|
require 'machineshop/errors/api_connection_error'
|
45
54
|
|
46
|
-
#
|
55
|
+
#Models
|
56
|
+
require 'machineshop/models/api_request'
|
57
|
+
# require 'machineshop/models/device_cache'
|
47
58
|
|
48
59
|
|
49
60
|
module MachineShop
|
50
61
|
class << self
|
51
62
|
# @@api_base_url = 'http://api.machineshop.io/api/v0'
|
52
|
-
@@api_base_url = 'http://stage.services.machineshop.io/api/
|
53
|
-
# @@api_base_url = 'https://services.machineshop.io/api/v0'
|
63
|
+
@@api_base_url = 'http://stage.services.machineshop.io/api/v1'
|
54
64
|
|
55
65
|
#configs starts
|
56
66
|
attr_writer :configuration
|
@@ -102,63 +112,81 @@ module MachineShop
|
|
102
112
|
end
|
103
113
|
|
104
114
|
def platform_request(url, auth_token, body_hash=nil, http_verb=:get )
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
if http_verb == :get
|
110
|
-
if (body_hash && !body_hash.empty?)
|
111
|
-
uri = Addressable::URI.new
|
112
|
-
uri.query_values = body_hash
|
113
|
-
api_uri += "?" + uri.query
|
114
|
-
end
|
115
|
+
rbody=nil
|
116
|
+
cachedContent = :true
|
117
|
+
# ApiRequest.cache(url,MachineShop.configuration.expiry_time)
|
118
|
+
if http_verb==:get
|
115
119
|
|
116
|
-
|
117
|
-
|
118
|
-
:url => api_uri,
|
119
|
-
:headers => headers,
|
120
|
-
:open_timeout => 30,
|
121
|
-
:timeout => 80
|
122
|
-
}
|
120
|
+
if db_connected?
|
121
|
+
ApiRequest.cache(url, auth_token, MachineShop.configuration.expiry_time) do
|
123
122
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
:headers => headers,
|
129
|
-
:open_timeout => 30,
|
130
|
-
:payload => MachineShop::JSON.dump(body_hash),
|
131
|
-
:timeout => 80
|
132
|
-
}
|
123
|
+
rbody = get_from_cache(url,body_hash,auth_token)
|
124
|
+
rcode="200"
|
125
|
+
end
|
126
|
+
end
|
133
127
|
|
134
128
|
end
|
129
|
+
if (rbody.nil? || rbody.empty?)
|
130
|
+
cachedContent=:false
|
131
|
+
opts = nil
|
132
|
+
api_uri = api_base_url + url
|
133
|
+
headers = self.headers(auth_token)
|
134
|
+
if http_verb == :get
|
135
|
+
if (body_hash && !body_hash.empty?)
|
136
|
+
uri = Addressable::URI.new
|
137
|
+
uri.query_values = body_hash
|
138
|
+
api_uri += "?" + uri.query
|
139
|
+
end
|
140
|
+
|
141
|
+
opts = {
|
142
|
+
:method => :get,
|
143
|
+
:url => api_uri,
|
144
|
+
:headers => headers,
|
145
|
+
:open_timeout => 30,
|
146
|
+
:timeout => 80
|
147
|
+
}
|
135
148
|
|
136
|
-
puts "request params: #{opts} "
|
137
|
-
|
138
|
-
begin
|
139
|
-
response = execute_request(opts)
|
140
|
-
rescue SocketError => e
|
141
|
-
self.handle_restclient_error(e)
|
142
|
-
rescue NoMethodError => e
|
143
|
-
# Work around RestClient bug
|
144
|
-
if e.message =~ /\WRequestFailed\W/
|
145
|
-
e = APIConnectionError.new('Unexpected HTTP response code')
|
146
|
-
self.handle_restclient_error(e)
|
147
149
|
else
|
148
|
-
|
150
|
+
opts = {
|
151
|
+
:method => http_verb,
|
152
|
+
:url => api_uri,
|
153
|
+
:headers => headers,
|
154
|
+
:open_timeout => 30,
|
155
|
+
:payload => MachineShop::JSON.dump(body_hash),
|
156
|
+
:timeout => 80
|
157
|
+
}
|
158
|
+
|
149
159
|
end
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
160
|
+
|
161
|
+
begin
|
162
|
+
response = execute_request(opts)
|
163
|
+
|
164
|
+
rescue SocketError => e
|
165
|
+
self.handle_restclient_error(e)
|
166
|
+
rescue NoMethodError => e
|
167
|
+
# Work around RestClient bug
|
168
|
+
if e.message =~ /\WRequestFailed\W/
|
169
|
+
e = APIConnectionError.new('Unexpected HTTP response code')
|
170
|
+
self.handle_restclient_error(e)
|
171
|
+
else
|
172
|
+
raise
|
173
|
+
end
|
174
|
+
rescue RestClient::ExceptionWithResponse => e
|
175
|
+
if rcode = e.http_code and rbody = e.http_body
|
176
|
+
self.handle_api_error(rcode, rbody)
|
177
|
+
else
|
178
|
+
self.handle_restclient_error(e)
|
179
|
+
end
|
180
|
+
rescue RestClient::Exception, Errno::ECONNREFUSED => e
|
154
181
|
self.handle_restclient_error(e)
|
155
182
|
end
|
156
|
-
|
157
|
-
|
183
|
+
|
184
|
+
rbody = response.body
|
185
|
+
rcode = response.code
|
158
186
|
end
|
159
187
|
|
160
|
-
|
161
|
-
|
188
|
+
|
189
|
+
|
162
190
|
|
163
191
|
begin
|
164
192
|
# Would use :symbolize_names => true, but apparently there is
|
@@ -166,7 +194,7 @@ module MachineShop
|
|
166
194
|
resp = MachineShop::JSON.load(rbody)
|
167
195
|
resp ||= {}
|
168
196
|
resp = Util.symbolize_names(resp)
|
169
|
-
|
197
|
+
save_into_cache(url,resp,auth_token) if (http_verb == :get && cachedContent==:false)
|
170
198
|
resp.merge!({:http_code => rcode}) if resp.is_a?(Hash)
|
171
199
|
return resp
|
172
200
|
rescue MultiJson::DecodeError
|
@@ -225,11 +253,219 @@ module MachineShop
|
|
225
253
|
message = "Unexpected error communicating with MachineShop"
|
226
254
|
end
|
227
255
|
message += "\n\n(Network error: #{e.message})"
|
228
|
-
# puts "error message string : #{message}"
|
229
256
|
raise APIConnectionError.new(message)
|
230
257
|
end
|
231
258
|
|
232
259
|
|
260
|
+
# Check if the class with the variable exists
|
261
|
+
def class_exists?(class_name)
|
262
|
+
klass = class_name.constantize
|
263
|
+
return klass.is_a?(Class)
|
264
|
+
rescue NameError =>e
|
265
|
+
return false
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
#get the classname from url and get the record if exists
|
270
|
+
|
271
|
+
#Check if db_connected
|
272
|
+
def db_connected?
|
273
|
+
db_connected = true
|
274
|
+
begin
|
275
|
+
MachineShop::Database.new
|
276
|
+
rescue DatabaseError =>e
|
277
|
+
db_connected= false
|
278
|
+
rescue SchemaError =>e
|
279
|
+
# db_connected=true
|
280
|
+
end
|
281
|
+
|
282
|
+
db_connected
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
def save_into_cache(url, data,auth_token)
|
287
|
+
if db_connected?
|
288
|
+
|
289
|
+
id=nil
|
290
|
+
splitted = url.split('/')
|
291
|
+
klass = splitted[-1]
|
292
|
+
if /[0-9]/.match(klass)
|
293
|
+
id=splitted[-1]
|
294
|
+
if splitted[-3]=="rule"
|
295
|
+
klass="rule"
|
296
|
+
else
|
297
|
+
klass = splitted[-2]
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
klass = klass.capitalize+"Cache"
|
302
|
+
modelClass ||= (Object.const_set klass, Class.new(ActiveRecord::Base))
|
303
|
+
modelClass.inheritance_column = :_type_disabled
|
304
|
+
#Because 'type' is reserved for storing the class in case of inheritance and our array has "TYPE" key
|
305
|
+
|
306
|
+
if ActiveRecord::Base.connection.table_exists? CGI.escape(klass.pluralize.underscore)
|
307
|
+
if data.class ==Hash
|
308
|
+
|
309
|
+
findId = data[:_id] || data["_id"]
|
310
|
+
@activeObject = modelClass.find_by(_id: findId) || modelClass.new
|
311
|
+
|
312
|
+
data.each do |k,v|
|
313
|
+
|
314
|
+
val=nil
|
315
|
+
if v.class==Array
|
316
|
+
val = v.to_json
|
317
|
+
elsif v.class==Hash
|
318
|
+
val = v.to_json
|
319
|
+
else
|
320
|
+
val=v
|
321
|
+
end
|
322
|
+
if @activeObject.has_attribute?(k)
|
323
|
+
@activeObject.send("#{k}=",val)
|
324
|
+
end
|
325
|
+
@activeObject.save
|
326
|
+
end
|
327
|
+
|
328
|
+
|
329
|
+
else
|
330
|
+
data.each do |data_arr|
|
331
|
+
if data_arr
|
332
|
+
if data_arr.first.class==String && data_arr.class==Array
|
333
|
+
@activeObject = modelClass.find_by(rule_condition: data_arr.select{|k| k.include?("rule_condition")}) || modelClass.new
|
334
|
+
data_arr.each do |k|
|
335
|
+
if k.include?("rule_condition")
|
336
|
+
@activeObject.rule_condition = k
|
337
|
+
else
|
338
|
+
@activeObject.rule_description=k
|
339
|
+
end
|
340
|
+
end
|
341
|
+
else
|
342
|
+
if data_arr.class!=String
|
343
|
+
findId = data_arr[:_id] || data_arr["_id"]
|
344
|
+
@activeObject = modelClass.find_by(_id: findId) || modelClass.new
|
345
|
+
data_arr.each do |k,v|
|
346
|
+
val=nil
|
347
|
+
if v.class==Array
|
348
|
+
val = v.to_json
|
349
|
+
elsif v.class==Hash
|
350
|
+
val = v.to_json
|
351
|
+
else
|
352
|
+
val=v
|
353
|
+
end
|
354
|
+
|
355
|
+
#check if the database has the particular field to store
|
356
|
+
if @activeObject.has_attribute?(k)
|
357
|
+
@activeObject.send("#{k}=",val)
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
@activeObject.send("auth_token=",auth_token)
|
365
|
+
@activeObject.save
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
|
373
|
+
|
374
|
+
|
375
|
+
def get_from_cache(url, body_hash,auth_token)
|
376
|
+
result =Array.new
|
377
|
+
if db_connected?
|
378
|
+
|
379
|
+
id=nil
|
380
|
+
splitted = url.split('/')
|
381
|
+
klass = splitted[-1]
|
382
|
+
|
383
|
+
|
384
|
+
if /[0-9]/.match(klass)
|
385
|
+
id=splitted[-1]
|
386
|
+
|
387
|
+
if splitted[-3]=="rule"
|
388
|
+
klass="rule"
|
389
|
+
else
|
390
|
+
klass = splitted[-2]
|
391
|
+
end
|
392
|
+
|
393
|
+
end
|
394
|
+
|
395
|
+
klass = klass.capitalize+"Cache"
|
396
|
+
|
397
|
+
modelClass = Object.const_set klass, Class.new(ActiveRecord::Base)
|
398
|
+
modelClass.inheritance_column = :_type_disabled
|
399
|
+
|
400
|
+
data_exist=false
|
401
|
+
if ActiveRecord::Base.connection.table_exists? CGI.escape(klass.pluralize.underscore)
|
402
|
+
resp= nil
|
403
|
+
if id
|
404
|
+
resp = modelClass.find_by(_id: id, auth_token: auth_token)
|
405
|
+
data_exist=true if resp
|
406
|
+
else
|
407
|
+
# pagination = body_hash.select{|k| k==:per_page || k==:page} if body_hash
|
408
|
+
resp = modelClass.where(parse_query_string(body_hash,auth_token))
|
409
|
+
data_exist = true if resp.exists?
|
410
|
+
end
|
411
|
+
|
412
|
+
if data_exist
|
413
|
+
if(klass.include?("rule_condition"))
|
414
|
+
resp.each do |rTemp|
|
415
|
+
temp = Array.new
|
416
|
+
temp.push rTemp["rule_description"]
|
417
|
+
temp.push rTemp["rule_condition"]
|
418
|
+
result << temp
|
419
|
+
end
|
420
|
+
result = result.to_json(:except=>[:id]) if result
|
421
|
+
else
|
422
|
+
result = resp.to_json(:except=>[:id]) if resp
|
423
|
+
end
|
424
|
+
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
return result
|
429
|
+
end
|
430
|
+
|
431
|
+
QUERY_STRING_BLACKLIST = [
|
432
|
+
'page',
|
433
|
+
'per_page'
|
434
|
+
]
|
435
|
+
|
436
|
+
def parse_query_string(query_params,auth_token)
|
437
|
+
|
438
|
+
search_parms = {}
|
439
|
+
if query_params
|
440
|
+
params = Hash[query_params.map{ |k, v| [k.to_s, v] }]
|
441
|
+
operators = ["gt", "gte", "lt", "lte"]
|
442
|
+
|
443
|
+
xs = params.reject { |k,_| QUERY_STRING_BLACKLIST.include?(k) }
|
444
|
+
xs.each do |key,value|
|
445
|
+
tokens = key.split('_')
|
446
|
+
if tokens.nil? || tokens.length == 1
|
447
|
+
search_parms[key] = value
|
448
|
+
else
|
449
|
+
token_length = tokens[tokens.length-1].length-1
|
450
|
+
if operators.include?(tokens[tokens.length-1])
|
451
|
+
operator = "$" + tokens[tokens.length-1]
|
452
|
+
new_key = key[0,key.length-token_length-2].to_sym
|
453
|
+
search_parms[new_key] = { operator => value }
|
454
|
+
elsif tokens[tokens.length-1] == "between" && value.split("_").length > 1
|
455
|
+
new_key = key[0,key.length-token_length-2].to_sym
|
456
|
+
vals = value.split("_")
|
457
|
+
search_parms[new_key] = {"$gte" => vals[0], "$lte" => vals[1]}
|
458
|
+
else
|
459
|
+
search_parms[key] = value
|
460
|
+
end
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
#append auth_token = auth_token part as well
|
465
|
+
search_parms['auth_token']=auth_token
|
466
|
+
search_parms
|
467
|
+
end
|
468
|
+
|
233
469
|
|
234
470
|
end
|
235
471
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module MachineShop
|
2
|
+
class DataSourceTypes < APIResource
|
3
|
+
include MachineShop::APIOperations::List
|
4
|
+
include MachineShop::APIOperations::Create
|
5
|
+
include MachineShop::APIOperations::Delete
|
6
|
+
|
7
|
+
|
8
|
+
def create_data_source(params)
|
9
|
+
params.merge!({:data_source_type => self.id})
|
10
|
+
DataSources.create(params, @auth_token)
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_email_data_source(params)
|
14
|
+
params.merge!({:data_source_type => self.id})
|
15
|
+
MachineShop.post(email_data_source_url, @auth_token, params)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def self.url
|
20
|
+
'/platform/data_source_types'
|
21
|
+
end
|
22
|
+
|
23
|
+
def email_data_source_url
|
24
|
+
'/platform/email_data_sources'
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|