bug_bunny 3.0.0 → 3.0.1
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/CHANGELOG.md +15 -0
- data/README.md +142 -100
- data/lib/bug_bunny/client.rb +22 -39
- data/lib/bug_bunny/consumer.rb +65 -55
- data/lib/bug_bunny/request.rb +30 -70
- data/lib/bug_bunny/resource.rb +82 -229
- data/lib/bug_bunny/version.rb +1 -1
- metadata +2 -2
data/lib/bug_bunny/resource.rb
CHANGED
|
@@ -4,24 +4,20 @@ require 'active_support/core_ext/string/inflections'
|
|
|
4
4
|
require 'uri'
|
|
5
5
|
|
|
6
6
|
module BugBunny
|
|
7
|
-
# Clase base para modelos remotos que implementan
|
|
7
|
+
# Clase base para modelos remotos que implementan **Active Record over AMQP (RESTful)**.
|
|
8
8
|
#
|
|
9
|
-
# Esta clase
|
|
10
|
-
#
|
|
11
|
-
# facilita la integración con APIs externas que no siguen convenciones de Rails (ej: Docker API en PascalCase).
|
|
9
|
+
# Esta clase transforma operaciones CRUD estándar en peticiones RPC utilizando
|
|
10
|
+
# verbos HTTP semánticos (GET, POST, PUT, DELETE) transportados sobre headers AMQP.
|
|
12
11
|
#
|
|
13
|
-
# @example
|
|
14
|
-
# class
|
|
15
|
-
# self.exchange = '
|
|
16
|
-
#
|
|
17
|
-
# # Atributos accesibles dinámicamente: node.Hostname, node.Status
|
|
12
|
+
# @example
|
|
13
|
+
# class User < BugBunny::Resource
|
|
14
|
+
# self.exchange = 'app.topic'
|
|
15
|
+
# self.resource_name = 'users'
|
|
18
16
|
# end
|
|
19
17
|
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
# self.routing_key = 'manager_queue' # Todo viaja a esta cola
|
|
24
|
-
# end
|
|
18
|
+
# User.create(name: 'Gaby') # Envía POST 'users'
|
|
19
|
+
# u = User.find(1) # Envía GET 'users/1'
|
|
20
|
+
# u.destroy # Envía DELETE 'users/1'
|
|
25
21
|
class Resource
|
|
26
22
|
include ActiveModel::API
|
|
27
23
|
include ActiveModel::Dirty
|
|
@@ -30,83 +26,61 @@ module BugBunny
|
|
|
30
26
|
|
|
31
27
|
define_model_callbacks :save, :create, :update, :destroy
|
|
32
28
|
|
|
33
|
-
# @return [ActiveSupport::HashWithIndifferentAccess] Almacén de los datos crudos del recurso.
|
|
34
|
-
# @note Se llama remote_attributes para evitar conflictos con ActiveModel::AttributeSet.
|
|
35
29
|
attr_reader :remote_attributes
|
|
36
|
-
|
|
37
|
-
# @return [Boolean] Estado de persistencia del objeto (true si existe en remoto).
|
|
38
30
|
attr_accessor :persisted
|
|
39
31
|
|
|
40
32
|
class << self
|
|
41
|
-
# @!group Configuración
|
|
42
|
-
|
|
43
33
|
attr_writer :connection_pool, :exchange, :exchange_type, :resource_name, :routing_key
|
|
44
34
|
|
|
45
35
|
# Resuelve la configuración buscando en la jerarquía de clases.
|
|
46
|
-
#
|
|
47
|
-
# Prioridad de resolución:
|
|
48
|
-
# 1. Override temporal (Thread-local via `.with`).
|
|
49
|
-
# 2. Configuración de la clase actual.
|
|
50
|
-
# 3. Configuración de la clase padre (Herencia).
|
|
51
|
-
#
|
|
52
|
-
# @param key [Symbol] Clave única para el almacenamiento thread-local.
|
|
53
|
-
# @param instance_var [Symbol] Variable de instancia a buscar (ej: :@connection_pool).
|
|
54
|
-
# @return [Object, nil] El valor configurado o nil.
|
|
55
36
|
# @api private
|
|
56
37
|
def resolve_config(key, instance_var)
|
|
57
38
|
thread_key = "bb_#{object_id}_#{key}"
|
|
58
39
|
return Thread.current[thread_key] if Thread.current.key?(thread_key)
|
|
59
|
-
|
|
60
40
|
target = self
|
|
61
41
|
while target <= BugBunny::Resource
|
|
62
42
|
value = target.instance_variable_get(instance_var)
|
|
63
|
-
|
|
64
|
-
return value.respond_to?(:call) ? value.call : value
|
|
65
|
-
end
|
|
43
|
+
return value.respond_to?(:call) ? value.call : value unless value.nil?
|
|
66
44
|
target = target.superclass
|
|
67
45
|
end
|
|
68
46
|
nil
|
|
69
47
|
end
|
|
70
48
|
|
|
71
|
-
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
end
|
|
49
|
+
def connection_pool; resolve_config(:pool, :@connection_pool); end
|
|
50
|
+
def current_exchange; resolve_config(:exchange, :@exchange) || raise(ArgumentError, "Exchange not defined"); end
|
|
51
|
+
def current_exchange_type; resolve_config(:exchange_type, :@exchange_type) || 'direct'; end
|
|
75
52
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def current_exchange
|
|
79
|
-
resolve_config(:exchange, :@exchange) || raise(ArgumentError, "Exchange not defined for #{name}")
|
|
53
|
+
def resource_name
|
|
54
|
+
resolve_config(:resource_name, :@resource_name) || name.demodulize.underscore.pluralize
|
|
80
55
|
end
|
|
81
56
|
|
|
82
|
-
#
|
|
83
|
-
def
|
|
84
|
-
|
|
57
|
+
# Define middlewares para el cliente de este recurso.
|
|
58
|
+
def client_middleware(&block)
|
|
59
|
+
@client_middleware_stack ||= []
|
|
60
|
+
@client_middleware_stack << block
|
|
85
61
|
end
|
|
86
62
|
|
|
87
|
-
#
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
63
|
+
# @api private
|
|
64
|
+
def resolve_middleware_stack
|
|
65
|
+
stack = []
|
|
66
|
+
target = self
|
|
67
|
+
while target <= BugBunny::Resource
|
|
68
|
+
middlewares = target.instance_variable_get(:@client_middleware_stack)
|
|
69
|
+
stack.unshift(*middlewares) if middlewares
|
|
70
|
+
target = target.superclass
|
|
71
|
+
end
|
|
72
|
+
stack
|
|
92
73
|
end
|
|
93
74
|
|
|
94
|
-
# Instancia el cliente RPC utilizando el pool configurado.
|
|
95
|
-
# @return [BugBunny::Client]
|
|
96
75
|
def bug_bunny_client
|
|
97
76
|
pool = connection_pool
|
|
98
77
|
raise BugBunny::Error, "Connection pool missing for #{name}" unless pool
|
|
99
|
-
|
|
78
|
+
|
|
79
|
+
BugBunny::Client.new(pool: pool) do |conn|
|
|
80
|
+
resolve_middleware_stack.each { |block| block.call(conn) }
|
|
81
|
+
end
|
|
100
82
|
end
|
|
101
83
|
|
|
102
|
-
# Permite ejecutar un bloque con una configuración temporal (Thread-Safe).
|
|
103
|
-
# Útil para cambiar de exchange, routing key o pool en tiempo de ejecución.
|
|
104
|
-
#
|
|
105
|
-
# @param exchange [String] Override del exchange.
|
|
106
|
-
# @param routing_key [String] Override forzado de la routing key.
|
|
107
|
-
# @param pool [ConnectionPool] Override del pool.
|
|
108
|
-
# @yield Bloque de código donde aplica la configuración.
|
|
109
|
-
# @return [Object] El resultado del bloque o un Proxy si no hay bloque.
|
|
110
84
|
def with(exchange: nil, routing_key: nil, exchange_type: nil, pool: nil)
|
|
111
85
|
keys = { exchange: "bb_#{object_id}_exchange", exchange_type: "bb_#{object_id}_exchange_type", pool: "bb_#{object_id}_pool", routing_key: "bb_#{object_id}_routing_key" }
|
|
112
86
|
old_values = {}
|
|
@@ -115,90 +89,42 @@ module BugBunny
|
|
|
115
89
|
Thread.current[keys[:exchange_type]] = exchange_type if exchange_type
|
|
116
90
|
Thread.current[keys[:pool]] = pool if pool
|
|
117
91
|
Thread.current[keys[:routing_key]] = routing_key if routing_key
|
|
118
|
-
|
|
119
92
|
if block_given?
|
|
120
93
|
begin; yield; ensure; keys.each { |k, v| Thread.current[v] = old_values[k] }; end
|
|
121
94
|
else
|
|
122
95
|
ScopeProxy.new(self, keys, old_values)
|
|
123
96
|
end
|
|
124
97
|
end
|
|
125
|
-
|
|
126
|
-
# @api private
|
|
98
|
+
|
|
127
99
|
class ScopeProxy < BasicObject
|
|
128
|
-
def initialize(target, keys, old_values)
|
|
129
|
-
|
|
130
|
-
@keys = keys
|
|
131
|
-
@old_values = old_values
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def method_missing(method, *args, &block)
|
|
135
|
-
@target.public_send(method, *args, &block)
|
|
136
|
-
ensure
|
|
137
|
-
@keys.each { |k, v| ::Thread.current[v] = @old_values[k] }
|
|
138
|
-
end
|
|
100
|
+
def initialize(target, keys, old_values); @target = target; @keys = keys; @old_values = old_values; end
|
|
101
|
+
def method_missing(method, *args, &block); @target.public_send(method, *args, &block); ensure; @keys.each { |k, v| ::Thread.current[v] = @old_values[k] }; end
|
|
139
102
|
end
|
|
140
103
|
|
|
141
|
-
# Calcula la Routing Key
|
|
142
|
-
#
|
|
143
|
-
|
|
144
|
-
# @param id [String, nil] El ID del recurso (opcional).
|
|
145
|
-
# @return [String] La routing key calculada.
|
|
146
|
-
def calculate_routing_key(action, id = nil)
|
|
104
|
+
# Calcula la Routing Key.
|
|
105
|
+
# @note En REST, por defecto es el resource_name (Topic 'users'), pero puede ser forzada.
|
|
106
|
+
def calculate_routing_key(id = nil)
|
|
147
107
|
manual_rk = Thread.current["bb_#{object_id}_routing_key"]
|
|
148
108
|
return manual_rk if manual_rk
|
|
149
|
-
|
|
150
109
|
static_rk = resolve_config(:routing_key, :@routing_key)
|
|
151
110
|
return static_rk if static_rk.present?
|
|
152
|
-
|
|
153
|
-
key = "#{resource_name}.#{action}"
|
|
154
|
-
key = "#{key}.#{id}" if id
|
|
155
|
-
key
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# @!group Acciones CRUD
|
|
159
|
-
|
|
160
|
-
def index_action
|
|
161
|
-
:index
|
|
111
|
+
resource_name
|
|
162
112
|
end
|
|
163
113
|
|
|
164
|
-
|
|
165
|
-
:show
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def create_action
|
|
169
|
-
:create
|
|
170
|
-
end
|
|
114
|
+
# @!group Acciones CRUD RESTful
|
|
171
115
|
|
|
172
|
-
|
|
173
|
-
:update
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
def destroy_action
|
|
177
|
-
:destroy
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# Busca recursos que coincidan con los filtros dados.
|
|
181
|
-
# Envía una petición con header type: `resource/index?query_params`.
|
|
116
|
+
# GET resource?query
|
|
182
117
|
#
|
|
183
|
-
# @param filters [Hash]
|
|
184
|
-
# @return [Array<Resource>] Lista de objetos instanciados.
|
|
118
|
+
# @param filters [Hash] Parámetros de consulta (Query params).
|
|
185
119
|
def where(filters = {})
|
|
186
|
-
rk = calculate_routing_key
|
|
187
|
-
path =
|
|
120
|
+
rk = calculate_routing_key
|
|
121
|
+
path = resource_name
|
|
122
|
+
path += "?#{URI.encode_www_form(filters)}" if filters.present?
|
|
188
123
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
type_header = "#{path}?#{query_string}"
|
|
192
|
-
else
|
|
193
|
-
type_header = path
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
response = bug_bunny_client.request(type_header, exchange: current_exchange, exchange_type: current_exchange_type) do |req|
|
|
197
|
-
req.routing_key = rk
|
|
198
|
-
end
|
|
124
|
+
# REST: GET collection
|
|
125
|
+
response = bug_bunny_client.request(path, method: :get, exchange: current_exchange, exchange_type: current_exchange_type, routing_key: rk)
|
|
199
126
|
|
|
200
127
|
return [] unless response['body'].is_a?(Array)
|
|
201
|
-
|
|
202
128
|
response['body'].map do |attrs|
|
|
203
129
|
inst = new(attrs)
|
|
204
130
|
inst.persisted = true
|
|
@@ -207,27 +133,20 @@ module BugBunny
|
|
|
207
133
|
end
|
|
208
134
|
end
|
|
209
135
|
|
|
210
|
-
|
|
211
|
-
# @return [Array<Resource>]
|
|
212
|
-
def all
|
|
213
|
-
where({})
|
|
214
|
-
end
|
|
136
|
+
def all; where({}); end
|
|
215
137
|
|
|
216
|
-
#
|
|
217
|
-
# Envía una petición con header type: `resource/show/:id`.
|
|
138
|
+
# GET resource/id
|
|
218
139
|
#
|
|
219
140
|
# @param id [String, Integer] ID del recurso.
|
|
220
|
-
# @return [Resource, nil] El recurso encontrado o nil si retorna 404.
|
|
221
141
|
def find(id)
|
|
222
|
-
rk = calculate_routing_key(
|
|
223
|
-
|
|
142
|
+
rk = calculate_routing_key(id)
|
|
143
|
+
path = "#{resource_name}/#{id}"
|
|
224
144
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
end
|
|
145
|
+
# REST: GET member
|
|
146
|
+
response = bug_bunny_client.request(path, method: :get, exchange: current_exchange, exchange_type: current_exchange_type, routing_key: rk)
|
|
228
147
|
|
|
229
148
|
return nil if response.nil? || response['status'] == 404
|
|
230
|
-
|
|
149
|
+
|
|
231
150
|
attributes = response['body']
|
|
232
151
|
return nil unless attributes.is_a?(Hash)
|
|
233
152
|
|
|
@@ -237,9 +156,6 @@ module BugBunny
|
|
|
237
156
|
instance
|
|
238
157
|
end
|
|
239
158
|
|
|
240
|
-
# Crea un nuevo recurso y lo persiste remotamente.
|
|
241
|
-
# @param payload [Hash] Atributos iniciales.
|
|
242
|
-
# @return [Resource] La instancia creada (persisted? será true si tuvo éxito).
|
|
243
159
|
def create(payload)
|
|
244
160
|
instance = new(payload)
|
|
245
161
|
instance.save
|
|
@@ -248,141 +164,84 @@ module BugBunny
|
|
|
248
164
|
end
|
|
249
165
|
|
|
250
166
|
# @!group Instancia
|
|
251
|
-
def current_exchange
|
|
252
|
-
self.class.current_exchange
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
def current_exchange_type
|
|
256
|
-
self.class.current_exchange_type
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def calculate_routing_key(action, id=nil)
|
|
260
|
-
self.class.calculate_routing_key(action, id)
|
|
261
|
-
end
|
|
262
167
|
|
|
263
|
-
def
|
|
264
|
-
|
|
265
|
-
end
|
|
168
|
+
def current_exchange; self.class.current_exchange; end
|
|
169
|
+
def current_exchange_type; self.class.current_exchange_type; end
|
|
170
|
+
def calculate_routing_key(id=nil); self.class.calculate_routing_key(id); end
|
|
171
|
+
def bug_bunny_client; self.class.bug_bunny_client; end
|
|
266
172
|
|
|
267
|
-
# Inicializa una nueva instancia del recurso.
|
|
268
|
-
# @param attributes [Hash] Atributos iniciales (snake_case o PascalCase).
|
|
269
173
|
def initialize(attributes = {})
|
|
270
174
|
@remote_attributes = {}.with_indifferent_access
|
|
271
175
|
@persisted = false
|
|
272
176
|
assign_attributes(attributes)
|
|
273
|
-
super()
|
|
177
|
+
super()
|
|
274
178
|
end
|
|
275
179
|
|
|
276
|
-
|
|
277
|
-
def persisted?
|
|
278
|
-
!!@persisted
|
|
279
|
-
end
|
|
180
|
+
def persisted?; !!@persisted; end
|
|
280
181
|
|
|
281
|
-
# Asigna atributos masivamente. Utiliza los setters dinámicos.
|
|
282
|
-
# @param new_attributes [Hash] Atributos a asignar.
|
|
283
182
|
def assign_attributes(new_attributes)
|
|
284
183
|
return if new_attributes.nil?
|
|
285
|
-
|
|
286
|
-
new_attributes.each do |k, v|
|
|
287
|
-
public_send("#{k}=", v)
|
|
288
|
-
end
|
|
184
|
+
new_attributes.each { |k, v| public_send("#{k}=", v) }
|
|
289
185
|
end
|
|
290
|
-
|
|
291
|
-
# Actualiza los atributos y guarda el registro.
|
|
292
|
-
# @param attributes [Hash] Nuevos valores.
|
|
293
|
-
# @return [Boolean] Resultado de save.
|
|
186
|
+
|
|
294
187
|
def update(attributes)
|
|
295
188
|
assign_attributes(attributes)
|
|
296
189
|
save
|
|
297
190
|
end
|
|
298
191
|
|
|
299
|
-
# Calcula el payload JSON a enviar.
|
|
300
|
-
# Si hay cambios (Dirty Tracking), envía solo los cambios.
|
|
301
|
-
# Si es nuevo, envía todo excepto los IDs internos.
|
|
302
|
-
# @return [Hash] Payload.
|
|
303
192
|
def changes_to_send
|
|
304
193
|
return changes.transform_values(&:last) unless changes.empty?
|
|
305
|
-
|
|
306
194
|
@remote_attributes.except('id', 'ID', 'Id', '_id')
|
|
307
195
|
end
|
|
308
196
|
|
|
309
|
-
#
|
|
310
|
-
|
|
311
|
-
# Intercepta llamadas a métodos desconocidos para leer/escribir en @remote_attributes.
|
|
312
|
-
# Permite acceder a propiedades como `node.Hostname` o `node.Spec` dinámicamente.
|
|
197
|
+
# Magic Methods para atributos dinámicos
|
|
313
198
|
def method_missing(method_name, *args, &block)
|
|
314
199
|
attribute_name = method_name.to_s
|
|
315
|
-
|
|
316
200
|
if attribute_name.end_with?('=')
|
|
317
|
-
# Setter: node.Status = 'active'
|
|
318
201
|
key = attribute_name.chop
|
|
319
202
|
val = args.first
|
|
320
|
-
|
|
321
|
-
# Dirty Tracking manual
|
|
322
203
|
attribute_will_change!(key) unless @remote_attributes[key] == val
|
|
323
|
-
|
|
324
204
|
@remote_attributes[key] = val
|
|
325
205
|
else
|
|
326
|
-
|
|
327
|
-
if @remote_attributes.key?(attribute_name)
|
|
328
|
-
@remote_attributes[attribute_name]
|
|
329
|
-
else
|
|
330
|
-
super
|
|
331
|
-
end
|
|
206
|
+
@remote_attributes.key?(attribute_name) ? @remote_attributes[attribute_name] : super
|
|
332
207
|
end
|
|
333
208
|
end
|
|
334
209
|
|
|
335
|
-
# @api private
|
|
336
210
|
def respond_to_missing?(method_name, include_private = false)
|
|
337
211
|
@remote_attributes.key?(method_name.to_s.sub(/=$/, '')) || super
|
|
338
212
|
end
|
|
339
213
|
|
|
340
|
-
# Retorna el ID del recurso buscando en variantes comunes (id, ID, Id, _id).
|
|
341
|
-
# @return [String, Integer, nil]
|
|
342
214
|
def id
|
|
343
215
|
@remote_attributes['id'] || @remote_attributes['ID'] || @remote_attributes['Id'] || @remote_attributes['_id']
|
|
344
216
|
end
|
|
345
217
|
|
|
346
|
-
# Asigna el ID manualmente.
|
|
347
|
-
# @param value [Object] Nuevo ID.
|
|
348
218
|
def id=(value)
|
|
349
219
|
@remote_attributes['id'] = value
|
|
350
220
|
end
|
|
351
221
|
|
|
352
|
-
# Método requerido por ActiveModel::Validations para leer atributos.
|
|
353
|
-
# @param attr [Symbol] Nombre del atributo.
|
|
354
|
-
# @return [Object] Valor del atributo.
|
|
355
|
-
# @api private
|
|
356
222
|
def read_attribute_for_validation(attr)
|
|
357
223
|
@remote_attributes[attr.to_s]
|
|
358
224
|
end
|
|
359
225
|
|
|
360
|
-
# @!group Persistencia
|
|
226
|
+
# @!group Persistencia RESTful
|
|
361
227
|
|
|
362
|
-
# Guarda el
|
|
363
|
-
#
|
|
364
|
-
# * Create: POST a `resource/create`
|
|
365
|
-
# * Update: POST a `resource/update/:id`
|
|
366
|
-
#
|
|
367
|
-
# @return [Boolean] true si fue exitoso, false si hubo error de validación o red.
|
|
228
|
+
# Guarda el registro (POST si es nuevo, PUT si existe).
|
|
368
229
|
def save
|
|
369
230
|
return false unless valid?
|
|
370
231
|
|
|
371
232
|
run_callbacks(:save) do
|
|
372
233
|
is_new = !persisted?
|
|
373
|
-
|
|
374
|
-
|
|
234
|
+
rk = calculate_routing_key(id)
|
|
235
|
+
|
|
236
|
+
# Mapeo a verbos HTTP usando client.request(method: ...)
|
|
375
237
|
if is_new
|
|
376
|
-
|
|
377
|
-
|
|
238
|
+
# REST: POST resource (Create)
|
|
239
|
+
path = self.class.resource_name
|
|
240
|
+
response = bug_bunny_client.request(path, method: :post, exchange: current_exchange, exchange_type: current_exchange_type, routing_key: rk, body: changes_to_send)
|
|
378
241
|
else
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
response = bug_bunny_client.request(type_header, exchange: current_exchange, exchange_type: current_exchange_type) do |req|
|
|
384
|
-
req.routing_key = rk
|
|
385
|
-
req.body = changes_to_send
|
|
242
|
+
# REST: PUT resource/id (Update)
|
|
243
|
+
path = "#{self.class.resource_name}/#{id}"
|
|
244
|
+
response = bug_bunny_client.request(path, method: :put, exchange: current_exchange, exchange_type: current_exchange_type, routing_key: rk, body: changes_to_send)
|
|
386
245
|
end
|
|
387
246
|
|
|
388
247
|
handle_save_response(response)
|
|
@@ -392,19 +251,16 @@ module BugBunny
|
|
|
392
251
|
false
|
|
393
252
|
end
|
|
394
253
|
|
|
395
|
-
# Elimina el
|
|
396
|
-
# Envía petición a `resource/destroy/:id`.
|
|
397
|
-
# @return [Boolean] true si fue eliminado exitosamente.
|
|
254
|
+
# Elimina el registro (DELETE).
|
|
398
255
|
def destroy
|
|
399
256
|
return false unless persisted?
|
|
400
257
|
|
|
401
258
|
run_callbacks(:destroy) do
|
|
402
|
-
|
|
403
|
-
|
|
259
|
+
# REST: DELETE resource/id
|
|
260
|
+
path = "#{self.class.resource_name}/#{id}"
|
|
261
|
+
rk = calculate_routing_key(id)
|
|
404
262
|
|
|
405
|
-
bug_bunny_client.request(
|
|
406
|
-
req.routing_key = rk
|
|
407
|
-
end
|
|
263
|
+
bug_bunny_client.request(path, method: :delete, exchange: current_exchange, exchange_type: current_exchange_type, routing_key: rk)
|
|
408
264
|
|
|
409
265
|
self.persisted = false
|
|
410
266
|
end
|
|
@@ -415,7 +271,6 @@ module BugBunny
|
|
|
415
271
|
|
|
416
272
|
private
|
|
417
273
|
|
|
418
|
-
# Procesa la respuesta exitosa del servidor RPC.
|
|
419
274
|
def handle_save_response(response)
|
|
420
275
|
if response['status'] == 422
|
|
421
276
|
raise BugBunny::UnprocessableEntity.new(response['body']['errors'] || response['body'])
|
|
@@ -431,10 +286,8 @@ module BugBunny
|
|
|
431
286
|
true
|
|
432
287
|
end
|
|
433
288
|
|
|
434
|
-
# Carga errores remotos en el objeto local ActiveModel::Errors.
|
|
435
289
|
def load_remote_rabbit_errors(errors_hash)
|
|
436
290
|
return if errors_hash.nil?
|
|
437
|
-
|
|
438
291
|
if errors_hash.is_a?(String)
|
|
439
292
|
errors.add(:base, errors_hash)
|
|
440
293
|
else
|
data/lib/bug_bunny/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bug_bunny
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- gabix
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bunny
|