bug_bunny 4.4.2 → 4.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f78de682c42ac5bcc4e0fbf14a7f03873e69459e32d5b1e20432c7e1c0871a7c
4
- data.tar.gz: 0b4a97ff9cdaa0eba4e869f00eb759595e4adfe7b7b4e2626afa01e734d252ef
3
+ metadata.gz: 027ba35b634991e2d41e8e80250b7c03e1dd3c60265eed0787f9d2e513911276
4
+ data.tar.gz: deb6f54612ca89aa583482a8e7fba8d3df60db3b4bebeb7454b47d561e4b5d0e
5
5
  SHA512:
6
- metadata.gz: ac04317d1875384da9d685fb353b68a9cbbdfaecbca4c0944a13576162f8dfbde469692c9b72e86d649886bc808647d08e68d7c82bed15de2026c5bc46418b0d
7
- data.tar.gz: a9ca7fd494102230ea3fbe9d85a757c5291e7a87cbbccae5d8649c84a8d48f913d3b38b576751494683c495e471850e3925b54a9f4856f1c473ad4aeb6fcec90
6
+ metadata.gz: d30777e78f9e82f984537d775a65a9b0dfada3b408d716fdb61e11d9464c24cfed58710fffaca2e355429955a9db733d79a8a7c470ce39171a5dafe5be1c7762
7
+ data.tar.gz: e35937729acad3ee114e63cefd998c609171e3244b1cd5469dacf9626a732871ee4c687be8beb8f8016b4a5245e6d8a80ef52c44007dd9404b645ea0954a6063
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.5.0] - 2026-03-25
4
+
5
+ ### ✨ New Features & DX
6
+ * **Controller Header API:** Se introdujo el método `headers` en `BugBunny::Controller` para permitir una manipulación intuitiva de las cabeceras de respuesta AMQP, siguiendo el patrón familiar de Rails.
7
+ * Ejemplo: `headers['X-Custom'] = 'Value'`.
8
+ * **Observability Refinement:** Finalización de la migración al patrón de observabilidad estándar con nombres de eventos `clase.evento` en todos los componentes.
9
+
10
+ ## [4.4.2] - 2026-03-25
11
+
12
+
13
+ ### ✨ New Features
14
+ * **Request#params:** Se agregó el atributo `params` al objeto `Request` para enviar query params de forma declarativa, al estilo Faraday. Los params se serializan como query string (`Rack::Utils.build_nested_query`) y viajan en el header AMQP `type`, que es el que usa el consumer para rutear al controlador. La `routing_key` del exchange no se ve afectada.
15
+ * **Resource.where con params:** `Resource.where` ahora usa internamente `req.params` en lugar de construir la URL manualmente, unificando el comportamiento con el cliente directo.
16
+
17
+ ### 🐛 Bug Fixes
18
+ * **Session#exchange:** El `name` y `type` del exchange se convierten a `String` via `.to_s` antes de pasarlos a Bunny, evitando `NoMethodError: undefined method 'gsub' for an instance of Symbol` al configurar exchanges con Symbols.
19
+ * **Configuration:** Se corrigió el namespace por defecto de controladores de `'Rabbit::Controllers'` a `'BugBunny::Controllers'`.
20
+
3
21
  ## [4.4.2] - 2026-03-25
4
22
 
5
23
  ### 📈 Observability & Standards Final Polish
data/README.md CHANGED
@@ -89,6 +89,13 @@ end
89
89
  node = RemoteNode.find('node-123')
90
90
  node.status = 'active'
91
91
  node.save # Realiza un PUT a inventory_exchange con routing_key 'nodes.node-123'
92
+
93
+ # Búsqueda con filtros (query params)
94
+ # Los filtros se serializan como query string en el header 'type' del mensaje.
95
+ # El consumer los recibe en params[] igual que en Rails.
96
+ RemoteNode.all # GET nodes
97
+ RemoteNode.where(status: 'active') # GET nodes?status=active
98
+ RemoteNode.where(q: { cpu_cores: 4 }) # GET nodes?q[cpu_cores]=4
92
99
  ```
93
100
 
94
101
  ---
@@ -167,7 +174,18 @@ client.send('users/1') do |req|
167
174
  req.timeout = 5
168
175
  end
169
176
 
170
- # 3. Métodos de conveniencia (Atajos)
177
+ # 3. Query params (estilo Faraday)
178
+ # Usá req.params para enviar filtros. La gema los serializa como query string
179
+ # en el header 'type' del mensaje (que el consumer usa para rutear).
180
+ # La routing_key del exchange NO se ve afectada.
181
+ client.request('users') do |req|
182
+ req.method = :get
183
+ req.params = { q: { active: true }, page: 2 }
184
+ end
185
+ # Equivalente usando args:
186
+ client.request('users', method: :get, params: { q: { active: true }, page: 2 })
187
+
188
+ # 4. Métodos de conveniencia (Atajos)
171
189
  client.request('users/1') # Siempre :rpc
172
190
  client.publish('events', body: { type: 'click' }) # Siempre :publish
173
191
 
@@ -109,6 +109,7 @@ module BugBunny
109
109
  req.exchange_options = args[:exchange_options] if args[:exchange_options]
110
110
  req.queue_options = args[:queue_options] if args[:queue_options]
111
111
 
112
+ req.params = args[:params] if args[:params]
112
113
  req.headers.merge!(args[:headers]) if args[:headers]
113
114
 
114
115
  # 3. Configuración del usuario (bloque específico por request)
@@ -33,6 +33,7 @@ module BugBunny
33
33
  attribute :raw_string
34
34
 
35
35
  # @return [Hash] Headers de respuesta que serán enviados de vuelta en RPC.
36
+ # @deprecated Use {#response_headers} instead or the helper {#headers}.
36
37
  attr_reader :response_headers
37
38
 
38
39
  # @return [Hash, nil] Respuesta final renderizada.
@@ -40,6 +41,18 @@ module BugBunny
40
41
 
41
42
  # @!endgroup
42
43
 
44
+ # API de Cabeceras de Respuesta (Estilo Rails)
45
+ # Permite manipular fácilmente los headers AMQP que se enviarán de vuelta al cliente.
46
+ #
47
+ # @example
48
+ # headers['X-Custom-Header'] = 'Value'
49
+ # headers[:content_type] = 'application/pdf'
50
+ #
51
+ # @return [Hash] El Hash de cabeceras de respuesta.
52
+ def headers
53
+ @response_headers
54
+ end
55
+
43
56
 
44
57
  # ==========================================
45
58
  # INFRAESTRUCTURA DE FILTROS Y LOGS (HEREDABLES)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rack/utils'
4
+
3
5
  module BugBunny
4
6
  # Encapsula toda la información necesaria para realizar una petición o publicación.
5
7
  #
@@ -9,6 +11,7 @@ module BugBunny
9
11
  #
10
12
  # @attr body [Object] El cuerpo del mensaje (Hash, Array o String).
11
13
  # @attr headers [Hash] Cabeceras personalizadas (Headers AMQP).
14
+ # @attr params [Hash] Parámetros de query string (ej: { q: { foo: :bar } }).
12
15
  # @attr path [String] La ruta lógica del recurso (ej: 'users', 'users/123').
13
16
  # @attr method [Symbol, String] El verbo HTTP (:get, :post, :put, :delete). Default: :get.
14
17
  # @attr exchange [String] El nombre del Exchange destino.
@@ -22,6 +25,7 @@ module BugBunny
22
25
  class Request
23
26
  attr_accessor :body
24
27
  attr_accessor :headers
28
+ attr_accessor :params
25
29
  attr_accessor :path
26
30
  attr_accessor :method
27
31
  attr_accessor :exchange
@@ -46,6 +50,7 @@ module BugBunny
46
50
  @path = path
47
51
  @method = :get # Verbo por defecto
48
52
  @headers = {}
53
+ @params = {}
49
54
  @content_type = 'application/json'
50
55
  @timestamp = Time.now.to_i
51
56
  @persistent = false
@@ -56,10 +61,20 @@ module BugBunny
56
61
  @exchange_options = {}
57
62
  @queue_options = {}
58
63
  end
64
+ # Combina el path con los params como query string.
65
+ #
66
+ # @return [String] El path completo con query string si hay params, o solo el path.
67
+ def full_path
68
+ return path if params.nil? || params.empty?
69
+
70
+ "#{path}?#{Rack::Utils.build_nested_query(params)}"
71
+ end
72
+
59
73
  # Calcula la Routing Key final que se usará en RabbitMQ.
60
74
  #
61
75
  # Principio: "Convention over Configuration".
62
76
  # Si no se define una `routing_key` manual, se asume que el `path` actúa como tal.
77
+ # Los params NO afectan la routing key — son metadata de la petición, no del enrutamiento del exchange.
63
78
  #
64
79
  # @return [String] La routing key definitiva.
65
80
  def final_routing_key
@@ -67,11 +82,11 @@ module BugBunny
67
82
  end
68
83
 
69
84
  # Calcula el valor para el header AMQP 'type'.
70
- # En esta arquitectura REST, el 'type' es la URL del recurso (el path).
85
+ # En esta arquitectura REST, el 'type' es la URL completa del recurso (path + query string).
71
86
  #
72
87
  # @return [String] El tipo de mensaje definitivo.
73
88
  def final_type
74
- type || path
89
+ type || full_path
75
90
  end
76
91
 
77
92
  # Genera el Hash de opciones limpio para la gema Bunny.
@@ -4,7 +4,6 @@ require 'active_model'
4
4
  require 'active_support/core_ext/string/inflections'
5
5
  require 'uri'
6
6
  require 'set' # Necesario para el tracking manual
7
- require 'rack/utils'
8
7
 
9
8
  module BugBunny
10
9
  # Clase base para modelos remotos que implementan **Active Record over AMQP (RESTful)**.
@@ -194,17 +193,16 @@ module BugBunny
194
193
  # @return [Array<BugBunny::Resource>]
195
194
  def where(filters = {})
196
195
  rk = calculate_routing_key
197
- path = resource_name
198
- path += "?#{Rack::Utils.build_nested_query(filters)}" if filters.present?
199
196
 
200
197
  response = bug_bunny_client.request(
201
- path,
198
+ resource_name,
202
199
  method: :get,
203
200
  exchange: current_exchange,
204
201
  exchange_type: current_exchange_type,
205
202
  routing_key: rk,
206
203
  exchange_options: current_exchange_options,
207
- queue_options: current_queue_options
204
+ queue_options: current_queue_options,
205
+ params: filters.presence || {}
208
206
  )
209
207
 
210
208
  return [] unless response['body'].is_a?(Array)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BugBunny
4
- VERSION = "4.4.2"
4
+ VERSION = "4.5.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bug_bunny
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.2
4
+ version: 4.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gabix