machineshop 0.0.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|