logical_model 0.4.10 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +17 -2
- data/VERSION +1 -1
- data/client.rb +10 -4
- data/lib/logical_model.rb +23 -481
- data/lib/logical_model/api_key.rb +41 -0
- data/lib/logical_model/attributes.rb +57 -0
- data/lib/logical_model/has_many_keys.rb +53 -47
- data/lib/logical_model/rest_actions.rb +410 -0
- data/lib/logical_model/safe_log.rb +61 -0
- data/lib/logical_model/url_helper.rb +78 -0
- data/logical_model.gemspec +7 -4
- data/spec/client_spec.rb +129 -39
- metadata +8 -5
- data/lib/safe_log.rb +0 -11
- data/lib/ssl_support.rb +0 -39
@@ -0,0 +1,41 @@
|
|
1
|
+
class LogicalModel
|
2
|
+
module ApiKey
|
3
|
+
def self.included(base)
|
4
|
+
base.send(:extend, ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
attr_accessor :api_key, :api_key_name, :use_api_key
|
9
|
+
|
10
|
+
# Set api_key
|
11
|
+
# @param name [Symbol] name for api_key. Eg: app_key, token, etc.
|
12
|
+
# @param value [String] value of key. Eg: 1o2u3hqkfd, secret, etc.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# class Client < LogicalModel
|
16
|
+
# set_api_key(:token, 'asdfasdf')
|
17
|
+
# ...
|
18
|
+
# end
|
19
|
+
def set_api_key(name,value)
|
20
|
+
@use_api_key = true
|
21
|
+
@api_key_name = name
|
22
|
+
@api_key = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def use_api_key
|
26
|
+
@use_api_key ||= false
|
27
|
+
end
|
28
|
+
|
29
|
+
# if needed will merge api_key into given hash
|
30
|
+
# returns merged hash
|
31
|
+
def merge_key(params = {})
|
32
|
+
if self.use_api_key
|
33
|
+
params.merge({self.api_key_name => self.api_key})
|
34
|
+
else
|
35
|
+
params
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class LogicalModel
|
2
|
+
module Attributes
|
3
|
+
# TODO replace this module with ActvieAttr ?
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
base.send(:extend, ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module InstanceMethods
|
10
|
+
|
11
|
+
def attributes=(attrs)
|
12
|
+
sanitize_for_mass_assignment(attrs).each{|k,v| send("#{k}=",v) if respond_to?("#{k}=")}
|
13
|
+
end
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
attrs = self.class.attribute_keys.inject(ActiveSupport::HashWithIndifferentAccess.new) do |result,key|
|
17
|
+
result[key] = read_attribute_for_validation(key)
|
18
|
+
result
|
19
|
+
end
|
20
|
+
|
21
|
+
unless self.class.has_many_keys.blank?
|
22
|
+
self.class.has_many_keys.inject(attrs) do |result,key|
|
23
|
+
result["#{key}_attributes"] = send(key).map {|a| a.attributes}
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
attrs.reject {|key, value| key == "_id" && value.blank?}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
|
33
|
+
# declares an attribute.
|
34
|
+
# @param name [Symbol]
|
35
|
+
# @example
|
36
|
+
# class Client < LogicalModel
|
37
|
+
# attribute :att_name
|
38
|
+
# end
|
39
|
+
def attribute(name)
|
40
|
+
@attribute_keys = [] if @attribute_keys.nil?
|
41
|
+
@attribute_keys << name
|
42
|
+
attr_accessor name
|
43
|
+
end
|
44
|
+
|
45
|
+
# overrides attributes with given keys.
|
46
|
+
# @param keys [Array<Symbol>]
|
47
|
+
def attribute_keys=(keys)
|
48
|
+
@attribute_keys = keys
|
49
|
+
attr_accessor *keys
|
50
|
+
end
|
51
|
+
|
52
|
+
def attribute_keys
|
53
|
+
@attribute_keys
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,69 +1,75 @@
|
|
1
1
|
class LogicalModel
|
2
2
|
module HasManyKeys
|
3
3
|
|
4
|
-
def
|
5
|
-
|
6
|
-
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:extend, ClassMethods)
|
6
|
+
end
|
7
7
|
|
8
|
-
|
8
|
+
module ClassMethods
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
instance_variable_set("@#{association}", [])
|
14
|
-
end
|
10
|
+
def has_many_keys=(keys)
|
11
|
+
@has_many_keys = keys
|
12
|
+
attr_accessor *keys
|
15
13
|
|
16
|
-
|
17
|
-
end
|
14
|
+
keys.each do |association|
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
if attr_params["_type"].present?
|
24
|
-
attr_class = attr_params.delete("_type").to_s.constantize
|
25
|
-
else
|
26
|
-
attr_class = association.to_s.singularize.camelize.constantize
|
16
|
+
# return empty array or @association variable for each association
|
17
|
+
define_method association do
|
18
|
+
if instance_variable_get("@#{association}").blank?
|
19
|
+
instance_variable_set("@#{association}", [])
|
27
20
|
end
|
28
|
-
collection << attr_class.new(attr_params)
|
29
|
-
end
|
30
|
-
instance_variable_set("@#{association}", collection)
|
31
|
-
end
|
32
21
|
|
33
|
-
|
34
|
-
if attr_params["_type"].present?
|
35
|
-
clazz = attr_params.delete(:_type).constantize
|
36
|
-
else
|
37
|
-
clazz = association.to_s.singularize.camelize.constantize
|
22
|
+
instance_variable_get("@#{association}")
|
38
23
|
end
|
39
24
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
25
|
+
# this method loads the contact attributes recieved by logical model from the service
|
26
|
+
define_method "#{association}=" do |params|
|
27
|
+
collection = []
|
28
|
+
params.each do |attr_params|
|
29
|
+
if attr_params["_type"].present?
|
30
|
+
attr_class = attr_params.delete("_type").to_s.constantize
|
31
|
+
else
|
32
|
+
attr_class = association.to_s.singularize.camelize.constantize
|
33
|
+
end
|
34
|
+
collection << attr_class.new(attr_params)
|
35
|
+
end
|
36
|
+
instance_variable_set("@#{association}", collection)
|
37
|
+
end
|
46
38
|
|
47
|
-
|
48
|
-
define_method "#{association}_attributes=" do |key_attributes|
|
49
|
-
array = []
|
50
|
-
key_attributes.each do |attr_params|
|
51
|
-
attr_params.to_hash.symbolize_keys!
|
39
|
+
define_method "new_#{association.to_s.singularize}" do |attr_params|
|
52
40
|
if attr_params["_type"].present?
|
53
|
-
|
41
|
+
clazz = attr_params.delete(:_type).constantize
|
54
42
|
else
|
55
|
-
|
43
|
+
clazz = association.to_s.singularize.camelize.constantize
|
56
44
|
end
|
57
|
-
|
45
|
+
|
46
|
+
return unless clazz
|
47
|
+
|
48
|
+
temp_object = clazz.new(attr_params.merge({"#{self.json_root}_id" => self.id}))
|
49
|
+
eval(association.to_s) << temp_object
|
50
|
+
temp_object
|
51
|
+
end
|
52
|
+
|
53
|
+
# this method loads the contact attributes from the html form (using nested resources conventions)
|
54
|
+
define_method "#{association}_attributes=" do |key_attributes|
|
55
|
+
array = []
|
56
|
+
key_attributes.each do |attr_params|
|
57
|
+
attr_params.to_hash.symbolize_keys!
|
58
|
+
if attr_params["_type"].present?
|
59
|
+
attr_class = attr_params.delete("_type").to_s.constantize
|
60
|
+
else
|
61
|
+
attr_class = association.to_s.singularize.camelize.constantize
|
62
|
+
end
|
63
|
+
array << attr_class.new(attr_params)
|
64
|
+
end
|
65
|
+
instance_variable_set("@#{association}", array)
|
58
66
|
end
|
59
|
-
instance_variable_set("@#{association}", array)
|
60
67
|
end
|
61
68
|
end
|
62
|
-
end
|
63
69
|
|
64
|
-
|
65
|
-
|
70
|
+
def has_many_keys
|
71
|
+
@has_many_keys
|
72
|
+
end
|
66
73
|
end
|
67
|
-
|
68
74
|
end
|
69
75
|
end
|
@@ -0,0 +1,410 @@
|
|
1
|
+
class LogicalModel
|
2
|
+
module RESTActions
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
base.send(:extend, ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module InstanceMethods
|
10
|
+
|
11
|
+
def create(params={})
|
12
|
+
run_callbacks :save do
|
13
|
+
run_callbacks :create do
|
14
|
+
_create(params)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def save
|
20
|
+
run_callbacks :save do
|
21
|
+
run_callbacks new_record?? :create : :update do
|
22
|
+
_save
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy(params={})
|
28
|
+
run_callbacks :destroy do
|
29
|
+
_destroy(params)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param params [Hash] parameters to be sent to service
|
34
|
+
def update(params)
|
35
|
+
run_callbacks :save do
|
36
|
+
run_callbacks :update do
|
37
|
+
_update(params)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# creates model.
|
45
|
+
#
|
46
|
+
# returns:
|
47
|
+
# @return false if model invalid
|
48
|
+
# @return nil if there was a connection problem
|
49
|
+
# @return created model ID if successfull
|
50
|
+
#
|
51
|
+
# @example Usage:
|
52
|
+
# @person = Person.new(params[:person])
|
53
|
+
# @person.create( non_attribute_param: "value" )
|
54
|
+
def _create(params = {})
|
55
|
+
return false unless valid?
|
56
|
+
|
57
|
+
params = { self.json_root => self.attributes }.merge(params)
|
58
|
+
params = self.class.merge_key(params)
|
59
|
+
|
60
|
+
response = nil
|
61
|
+
Timeout::timeout(self.class.timeout/1000) do
|
62
|
+
response = Typhoeus::Request.post( self.class.resource_uri, :body => params, :timeout => self.class.timeout )
|
63
|
+
end
|
64
|
+
self.last_response_code = response.code
|
65
|
+
if response.code == 201 || response.code == 202
|
66
|
+
log_ok(response)
|
67
|
+
if self.respond_to?('id=')
|
68
|
+
self.id = ActiveSupport::JSON.decode(response.body)["id"]
|
69
|
+
else
|
70
|
+
true
|
71
|
+
end
|
72
|
+
elsif response.code == 400
|
73
|
+
log_failed(response)
|
74
|
+
ws_errors = ActiveSupport::JSON.decode(response.body)["errors"]
|
75
|
+
ws_errors.each_key do |k|
|
76
|
+
self.errors.add k, ws_errors[k]
|
77
|
+
end
|
78
|
+
return false
|
79
|
+
else
|
80
|
+
log_failed(response)
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
rescue Timeout::Error
|
84
|
+
self.class.logger.warn "timeout"
|
85
|
+
return nil
|
86
|
+
end
|
87
|
+
|
88
|
+
# Updates Objects attributes, this will only send attributes passed as arguments
|
89
|
+
#
|
90
|
+
#
|
91
|
+
# Returns false if Object#valid? is false.
|
92
|
+
# Returns updated object if successfull.
|
93
|
+
# Returns nil if update failed
|
94
|
+
#
|
95
|
+
# Usage:
|
96
|
+
# @person.update(params[:person])
|
97
|
+
def _update(params)
|
98
|
+
|
99
|
+
self.attributes = params[self.json_root]
|
100
|
+
|
101
|
+
return false unless valid?
|
102
|
+
|
103
|
+
params = self.class.merge_key(params)
|
104
|
+
|
105
|
+
response = nil
|
106
|
+
Timeout::timeout(self.class.timeout/1000) do
|
107
|
+
response = Typhoeus::Request.put( self.class.resource_uri(id),
|
108
|
+
:params => params,
|
109
|
+
:timeout => self.class.timeout )
|
110
|
+
end
|
111
|
+
|
112
|
+
if response.code == 200
|
113
|
+
log_ok(response)
|
114
|
+
return self
|
115
|
+
else
|
116
|
+
log_failed(response)
|
117
|
+
return nil
|
118
|
+
end
|
119
|
+
|
120
|
+
rescue Timeout::Error
|
121
|
+
self.class.logger.warn("request timed out")
|
122
|
+
return nil
|
123
|
+
end
|
124
|
+
|
125
|
+
# Saves Objects attributes
|
126
|
+
#
|
127
|
+
#
|
128
|
+
# Returns false if Object#valid? is false.
|
129
|
+
# Returns updated object if successfull.
|
130
|
+
# Returns nil if update failed
|
131
|
+
#
|
132
|
+
# Usage:
|
133
|
+
# @person.save
|
134
|
+
def _save
|
135
|
+
self.attributes = attributes
|
136
|
+
|
137
|
+
return false unless valid?
|
138
|
+
|
139
|
+
sending_params = self.attributes
|
140
|
+
sending_params.delete(:id)
|
141
|
+
|
142
|
+
params = { self.json_root => sending_params }
|
143
|
+
params = self.class.merge_key(params)
|
144
|
+
response = nil
|
145
|
+
Timeout::timeout(self.class.timeout/1000) do
|
146
|
+
response = Typhoeus::Request.put( self.class.resource_uri(id), :params => params, :timeout => self.class.timeout )
|
147
|
+
end
|
148
|
+
if response.code == 200
|
149
|
+
log_ok(response)
|
150
|
+
return self
|
151
|
+
else
|
152
|
+
log_failed(response)
|
153
|
+
return nil
|
154
|
+
end
|
155
|
+
rescue Timeout::Error
|
156
|
+
self.class.logger.warn "timeout"
|
157
|
+
return nil
|
158
|
+
end
|
159
|
+
|
160
|
+
# Destroy object
|
161
|
+
#
|
162
|
+
# Usage:
|
163
|
+
# @person.destroy
|
164
|
+
def _destroy(params={})
|
165
|
+
self.class.delete(self.id,params)
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
module ClassMethods
|
171
|
+
|
172
|
+
attr_accessor :enable_delete_multiple
|
173
|
+
|
174
|
+
# ============================================================================================================
|
175
|
+
# Following methods are API specific.
|
176
|
+
# They assume we are using a RESTfull API.
|
177
|
+
# for get, put, delete :id is expected
|
178
|
+
# for post, put attributes are excepted under class_name directly. eg. put( {:id => 1, :class_name => {:attr => "new value for attr"}} )
|
179
|
+
#
|
180
|
+
# On error (400) a "errors" is expected.
|
181
|
+
# ============================================================================================================
|
182
|
+
|
183
|
+
# Asynchronic Pagination
|
184
|
+
# This pagination won't block excecution waiting for result, pagination will be enqueued in Objectr#hydra.
|
185
|
+
#
|
186
|
+
# Parameters:
|
187
|
+
# @param options [Hash].
|
188
|
+
# Valid options are:
|
189
|
+
# * :page - indicated what page to return. Defaults to 1.
|
190
|
+
# * :per_page - indicates how many records to be returned per page. Defauls to 20
|
191
|
+
# * all other options will be sent in :params to WebService
|
192
|
+
#
|
193
|
+
# Usage:
|
194
|
+
# Person.async_paginate(:page => params[:page]){|i| result = i}
|
195
|
+
def async_paginate(options={})
|
196
|
+
options[:page] ||= 1
|
197
|
+
options[:per_page] ||= 20
|
198
|
+
|
199
|
+
options = self.merge_key(options)
|
200
|
+
|
201
|
+
request = Typhoeus::Request.new(resource_uri, :params => options)
|
202
|
+
request.on_complete do |response|
|
203
|
+
if response.code >= 200 && response.code < 400
|
204
|
+
log_ok(response)
|
205
|
+
|
206
|
+
result_set = self.from_json(response.body)
|
207
|
+
|
208
|
+
# this paginate is will_paginate's Array pagination
|
209
|
+
collection = Kaminari.paginate_array(
|
210
|
+
result_set[:collection],
|
211
|
+
{
|
212
|
+
:total_count=>result_set[:total],
|
213
|
+
:limit => options[:per_page],
|
214
|
+
:offset => options[:per_page] * ([options[:page], 1].max - 1)
|
215
|
+
}
|
216
|
+
)
|
217
|
+
|
218
|
+
yield collection
|
219
|
+
else
|
220
|
+
log_failed(response)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
self.hydra.queue(request)
|
224
|
+
end
|
225
|
+
|
226
|
+
#synchronic pagination
|
227
|
+
def paginate(options={})
|
228
|
+
result = nil
|
229
|
+
self.retries.times do
|
230
|
+
begin
|
231
|
+
async_paginate(options){|i| result = i}
|
232
|
+
Timeout::timeout(self.timeout/1000) do
|
233
|
+
self.hydra.run
|
234
|
+
end
|
235
|
+
break unless result.nil?
|
236
|
+
rescue Timeout::Error
|
237
|
+
self.logger.warn("timeout")
|
238
|
+
result = nil
|
239
|
+
end
|
240
|
+
end
|
241
|
+
result
|
242
|
+
end
|
243
|
+
|
244
|
+
# Asynchronic Count
|
245
|
+
# This count won't block excecution waiting for result, count will be enqueued in Objectr#hydra.
|
246
|
+
#
|
247
|
+
# Parameters:
|
248
|
+
# @param options [Hash].
|
249
|
+
# Valid options are:
|
250
|
+
# @option options [Integer] :page - indicated what page to return. Defaults to 1.
|
251
|
+
# @option options [Integer] :per_page - indicates how many records to be returned per page. Defauls to 20
|
252
|
+
# @option options [Hash] all other options will be forwarded in :params to WebService
|
253
|
+
#
|
254
|
+
# @example 'Count bobs'
|
255
|
+
# Person.async_count(:when => {:name => 'bob'}}){|i| result = i}
|
256
|
+
def async_count(options={})
|
257
|
+
options[:page] = 1
|
258
|
+
options[:per_page] = 1
|
259
|
+
|
260
|
+
options = self.merge_key(options)
|
261
|
+
|
262
|
+
request = Typhoeus::Request.new(resource_uri, :params => options)
|
263
|
+
request.on_complete do |response|
|
264
|
+
if response.code >= 200 && response.code < 400
|
265
|
+
log_ok(response)
|
266
|
+
|
267
|
+
result_set = self.from_json(response.body)
|
268
|
+
|
269
|
+
yield result_set[:total]
|
270
|
+
else
|
271
|
+
log_failed(response)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
self.hydra.queue(request)
|
275
|
+
end
|
276
|
+
|
277
|
+
# synchronic count
|
278
|
+
def count(options={})
|
279
|
+
result = nil
|
280
|
+
async_count(options){|i| result = i}
|
281
|
+
Timeout::timeout(self.timeout/1000) do
|
282
|
+
self.hydra.run
|
283
|
+
end
|
284
|
+
result
|
285
|
+
rescue Timeout::Error
|
286
|
+
self.logger.warn("timeout")
|
287
|
+
return nil
|
288
|
+
end
|
289
|
+
|
290
|
+
# Asynchronic Find
|
291
|
+
# This find won't block excecution waiting for result, excecution will be enqueued in Objectr#hydra.
|
292
|
+
#
|
293
|
+
# Parameters:
|
294
|
+
# - id, id of object to find
|
295
|
+
# @param [String/Integer] id
|
296
|
+
# @param [Hash] params
|
297
|
+
#
|
298
|
+
# Usage:
|
299
|
+
# Person.async_find(params[:id])
|
300
|
+
def async_find(id, params = {})
|
301
|
+
params = self.merge_key(params)
|
302
|
+
request = Typhoeus::Request.new( resource_uri(id), :params => params )
|
303
|
+
|
304
|
+
request.on_complete do |response|
|
305
|
+
if response.code >= 200 && response.code < 400
|
306
|
+
log_ok(response)
|
307
|
+
yield self.new.from_json(response.body) # this from_json is defined in ActiveModel::Serializers::JSON
|
308
|
+
else
|
309
|
+
log_failed(response)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
self.hydra.queue(request)
|
314
|
+
end
|
315
|
+
|
316
|
+
# synchronic find
|
317
|
+
def find(id, params = {})
|
318
|
+
result = nil
|
319
|
+
async_find(id, params){|i| result = i}
|
320
|
+
Timeout::timeout(self.timeout/1000) do
|
321
|
+
self.hydra.run
|
322
|
+
end
|
323
|
+
result
|
324
|
+
rescue Timeout::Error
|
325
|
+
self.logger.warn("timeout")
|
326
|
+
return nil
|
327
|
+
end
|
328
|
+
|
329
|
+
# Deletes Object#id
|
330
|
+
#
|
331
|
+
# Returns nil if delete failed
|
332
|
+
#
|
333
|
+
# @param [String] id - id of contact to be deleted
|
334
|
+
# @param [Hash] params - other params to be sent to WS on request
|
335
|
+
#
|
336
|
+
# Usage:
|
337
|
+
# Person.delete(params[:id])
|
338
|
+
def delete(id, params={})
|
339
|
+
|
340
|
+
params = self.merge_key(params)
|
341
|
+
|
342
|
+
response = nil
|
343
|
+
Timeout::timeout(self.timeout/1000) do
|
344
|
+
response = Typhoeus::Request.delete( self.resource_uri(id),
|
345
|
+
:params => params,
|
346
|
+
:timeout => self.timeout
|
347
|
+
)
|
348
|
+
end
|
349
|
+
if response.code == 200
|
350
|
+
log_ok(response)
|
351
|
+
return self
|
352
|
+
else
|
353
|
+
log_failed(response)
|
354
|
+
return nil
|
355
|
+
end
|
356
|
+
rescue Timeout::Error
|
357
|
+
self.logger.warn "timeout"
|
358
|
+
return nil
|
359
|
+
end
|
360
|
+
|
361
|
+
# Deletes all Objects matching given ids
|
362
|
+
#
|
363
|
+
# This method will make a DELETE request to resource_uri/destroy_multiple
|
364
|
+
#
|
365
|
+
# Returns nil if delete failed
|
366
|
+
#
|
367
|
+
# @param [Array] ids - ids of contacts to be deleted
|
368
|
+
# @param [Hash] params - other params to be sent to WS on request
|
369
|
+
#
|
370
|
+
# Usage:
|
371
|
+
# Person.delete_multiple([1,2,4,5,6])
|
372
|
+
def delete_multiple(ids, params={})
|
373
|
+
raise "not-enabled" unless self.delete_multiple_enabled?
|
374
|
+
|
375
|
+
params = self.merge_key(params)
|
376
|
+
params = params.merge({:ids => ids})
|
377
|
+
|
378
|
+
response = nil
|
379
|
+
Timeout::timeout(self.timeout/1000) do
|
380
|
+
response = Typhoeus::Request.delete( self.resource_uri+"/destroy_multiple",
|
381
|
+
:params => params,
|
382
|
+
:timeout => self.timeout
|
383
|
+
)
|
384
|
+
end
|
385
|
+
if response.code == 200
|
386
|
+
log_ok(response)
|
387
|
+
return self
|
388
|
+
else
|
389
|
+
log_failed(response)
|
390
|
+
return nil
|
391
|
+
end
|
392
|
+
rescue Timeout::Error
|
393
|
+
self.logger.warn "timeout"
|
394
|
+
return nil
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
##
|
400
|
+
# Will parse JSON string and initialize classes for all hashes in json_string[collection].
|
401
|
+
#
|
402
|
+
# @param json_string [JSON String] This JSON should have format: {collection: [...], total: X}
|
403
|
+
#
|
404
|
+
def self.from_json(json_string)
|
405
|
+
parsed = ActiveSupport::JSON.decode(json_string)
|
406
|
+
collection = parsed["collection"].map{|i|self.new(i)}
|
407
|
+
return { :collection => collection, :total => parsed["total"].to_i }
|
408
|
+
end
|
409
|
+
|
410
|
+
end
|