flu-rails 1.2.0 → 8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95ccc91aa5396a70d42d46300b5d7fc48321a3c3d3bea32e77d88b0b4a542e35
4
- data.tar.gz: e71784f540b50b412469fb10af164b30942d29190fe2a9e9d7b0725a41b713bd
3
+ metadata.gz: a35d15acbcbab2206e789f346ef7c97cd92d4cdc9bed53fe6fb0025256fec3b6
4
+ data.tar.gz: 5114f719bf9565182eada52d5ccd3c3a1e219ad2bc26e41c288ee7ff0ab58573
5
5
  SHA512:
6
- metadata.gz: e85087d058f0ce9e3cb32c7e7a3dc97471f158b9c973f491a66ccdb33f47f84c78cc78a364a16b3345dd0f036e57a1c686495c57ae2eb60e7decdb153c2a0e9f
7
- data.tar.gz: a15ad5ed11e2c3a2a3cade60e643b4b21b5583196d3c52429b2ae09fdec8445f7ab282f013899218add3c95af4b9a655331fe8a24b9565ab408d969cc8e5fffb
6
+ metadata.gz: a26ad7a3c9274ac803f842b509dcd81eebbc735812347c4473432cbbcb016355c6d7bc7440fe95070f4e53e708d8617849fad2a8c72ffb2443c64445682e2e5f
7
+ data.tar.gz: 9364931b1ee248a8a43b18089149ba1db00bc4e91fcbd9a7325cae5e7f009493ff9a5ae3b3226d52bf794e17c85d05503811421850a9793f948912a2f5e82b5b
data/CHANGELOG.md CHANGED
@@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ### [8.0.0] - 2026-07-31
9
+
10
+ **Fixed**
11
+
12
+ * Fix tracking a controller request raising `ActionController::UnfilteredParameters`. Controller params
13
+ reach `EventFactory` as unpermitted `ActionController::Parameters`, on which `to_h` raises
14
+ (Rails >= 5.1). The unsafe hash is now used, which is what a read-only tracker needs. This broke
15
+ `track_requests` entirely, and went unnoticed because its specs are disabled (`xit`).
16
+ * Fix `Flu.init` raising `configuration.application_name must not be nil` on a stock Rails application.
17
+
18
+ **Changed**
19
+
20
+ * **Breaking**: `flu-rails` now supports Rails 8 exclusively.
21
+ * Drop the pre-Rails-8 compatibility shims that this makes dead code:
22
+ * `flu_changes_depending_on_active_record_version`
23
+ * the `Zeitwerk::Loader.eager_load_all` fallback in `Util::ExportService`
24
+ * Restore `activesupport` as a runtime dependency
25
+ * Require the ActiveSupport core extensions that are actually used
26
+
27
+ **Publishing**
28
+
29
+ * Add a `Rakefile` (`bundler/gem_tasks` + an `rspec` task), so that `rake release` builds, tags and publishes the gem. `rake` becomes a development dependency.
30
+ * Add `.github/workflows/release.yml`: pushing a `v*` tag checks that the tag matches `Flu::VERSION`,
31
+ runs the specs, then builds and pushes the gem through RubyGems' Trusted Publishing. No RubyGems
32
+ API key is stored in the repository — a short-lived GitHub OIDC token is exchanged for a scoped
33
+ RubyGems credential.
34
+
35
+ **Verified**
36
+
37
+ * Verified against Rails 8.1 on a real application: railtie boot, `ActiveRecord` and
38
+ `ActionController::Base`/`API` tracking through the full Rack stack, request id propagation from a
39
+ controller into its entity-change events, uploaded file mapping and user-agent rejection — with
40
+ every framework deprecator set to `:raise`. No deprecation is triggered.
41
+
8
42
  ### [1.2.0] - 2026-07-31
9
43
 
10
44
  * Declare `required_ruby_version` as `>= 3.2`
data/MIT-LICENSE CHANGED
@@ -1,20 +1,21 @@
1
- Copyright 2018
1
+ MIT License
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
3
+ Copyright (c) 2026 Commuty SA
10
4
 
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
13
11
 
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -16,7 +16,7 @@ For now, events are generated from:
16
16
  Add the gem to your project's Gemfile:
17
17
 
18
18
  ```ruby
19
- gem "flu-rails", git: "https://github.com/crepesourcing/flu-rails.git"
19
+ gem "flu-rails"
20
20
  ```
21
21
 
22
22
  Then, create an initializer into your Rails app (`config/initializers/flu-rails.rb`)
@@ -38,20 +38,16 @@ Each configuration is detailed below.
38
38
  ## Requirements
39
39
 
40
40
  * Ruby >= 3.2 (tested against 3.2, 3.3 and 3.4)
41
- * Tested with Rails 8 (`activerecord` and `actionpack`)
41
+ * Rails 8 only (`activerecord`, `actionpack` and `activesupport` are runtime dependencies,
42
+ constrained to `~> 8.0`). `flu-rails` extends `ActiveRecord::Base` and `ActionController::Base`, so it requires Rails.
42
43
  * Tested with RabbitMQ 3.5.8
43
44
 
44
45
  ## Usage
45
46
 
46
47
  ### Start up
47
48
 
48
- If your application does not include `Railties`, `flu-rails` can be started as followed:
49
- ```
50
- Flu.init
51
- Flu.start
52
- ```
53
-
54
- `flu-rails` startup waits until its RabbitMQ exchange is connected.
49
+ `flu-rails` starts automatically through its `Railtie`: there is nothing to call by hand.
50
+ Its startup waits until its RabbitMQ exchange is connected.
55
51
 
56
52
  ### Track changes on an ActiveRecord model
57
53
 
@@ -90,7 +86,7 @@ For instance:
90
86
 
91
87
  ### Track requests to a Rails Controller action
92
88
 
93
- All subclasses of `ActionController::Base` or `ActionController::API` (Rails 5) that call `track_requests` are "tracked". _E.g._:
89
+ All subclasses of `ActionController::Base` or `ActionController::API` that call `track_requests` are "tracked". _E.g._:
94
90
 
95
91
  ```ruby
96
92
  class ApplicationController < ActionController::Base
@@ -167,7 +163,7 @@ All options have a default value. However, all of them can be changed in your in
167
163
  | `auto_connect_to_exchange` | `true`| Boolean | Optional | Thanks to `Railties`, `flu-rails` starts automatically when the Rails app boots. However, this can be useful to not connect RabbitMQ at start up. To do so, set `auto_connect_to_exchange` to `false`. | `false` |
168
164
  | `default_ignored_model_changes` | `[:password, :password_confirmation, :created_at, :updated_at]` | Boolean | Optional | By default, all these attributes will be ignored from model changes when creating an event. For instance, this means that timestamp fields (`created_at` and `updated_at`) are not monitored when they change. | `[]` |
169
165
  | `default_ignored_request_params` | `[:password, :password_confirmation, :controller, :action]` | Boolean | Optional | By default, all these parameters will be ignored from controller request's `params` when creating an event. | `false` |
170
- | `application_name` | `Rails.application.class.parent_name.to_s.camelize` | String | Required | Is used as `emitter` for each event created by `flu-rails`, if not overriden by the `track_met`. | `my_app` |
166
+ | `application_name` | `Rails.application.class.module_parent_name`, resolved on startup | String | Required | Is used as `emitter` for each event created by `flu-rails`, if not overriden by the `track_met`. | `my_app` |
171
167
  | `bunny_options` | `{}` | Hash of symbols | Optional | Additional options to add when connecting the RabbitMQ broker. This overrides the existing options with the same name. | `{ verify_peer: true }` |
172
168
 
173
169
  ## How to execute tests
@@ -270,3 +266,23 @@ For instance, calling the action `destroy` of `CountryController` will emit this
270
266
  ## Side-notes
271
267
 
272
268
  * `assocations` node contains `belongs_to` associations only.
269
+
270
+
271
+ ## How to release a new version
272
+
273
+ Releases are published to [RubyGems](https://rubygems.org/gems/flu-rails) by GitHub Actions
274
+ (`.github/workflows/release.yml`), through [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/):
275
+ no API key is stored in this repository, the workflow exchanges a short-lived GitHub OIDC token for a
276
+ scoped RubyGems credential.
277
+
278
+ 1. Update `Flu::VERSION` in `lib/flu-rails/version.rb` and the `CHANGELOG.md`
279
+ 2. Commit and push these changes to `master`
280
+ 3. Tag the commit and push the tag:
281
+
282
+ ```
283
+ $ git tag -a v8.0.0 -m "Version 8.0.0"
284
+ $ git push origin v8.0.0
285
+ ```
286
+
287
+ The workflow then checks that the tag matches `Flu::VERSION`, runs the tests, builds the gem
288
+ and pushes it. It only publishes tags starting with `v`.
@@ -1,3 +1,6 @@
1
+ require "active_support/core_ext/string/inflections"
2
+ require "active_support/core_ext/time/zones"
3
+
1
4
  module Flu
2
5
  class ActionControllerExtender
3
6
  def self.extend_controllers(event_factory, event_publisher, logger)
@@ -1,3 +1,5 @@
1
+ require "active_support/core_ext/object/try"
2
+
1
3
  module Flu
2
4
  class ActiveRecordExtender
3
5
  def self.extend_models(event_factory, event_publisher)
@@ -8,8 +10,8 @@ module Flu
8
10
  self.flu_ignored_model_changes = options.fetch(:ignored_model_changes, []).map(&:to_s)
9
11
  self.flu_overriden_emitter_lambda = options.fetch(:emitter, nil)
10
12
 
11
- after_create { flu_track_entity_change(:create, flu_changes_depending_on_active_record_version, event_factory) }
12
- after_update { flu_track_entity_change(:update, flu_changes_depending_on_active_record_version, event_factory) }
13
+ after_create { flu_track_entity_change(:create, saved_changes, event_factory) }
14
+ after_update { flu_track_entity_change(:update, saved_changes, event_factory) }
13
15
  after_destroy { flu_track_entity_change(:destroy, { "id" => [id, nil] }, event_factory) }
14
16
  after_commit { flu_commit_changes(event_factory, event_publisher) }
15
17
  after_rollback { flu_rollback_changes }
@@ -55,10 +57,6 @@ module Flu
55
57
  end
56
58
  end
57
59
 
58
- def flu_changes_depending_on_active_record_version
59
- respond_to?(:saved_changes) ? saved_changes : changes
60
- end
61
-
62
60
  def flu_changes
63
61
  @flu_changes ||= []
64
62
  end
@@ -1,4 +1,7 @@
1
1
  require "securerandom"
2
+ require "active_support/core_ext/object/blank"
3
+ require "active_support/core_ext/string/inflections"
4
+ require "active_support/core_ext/time/zones"
2
5
  require_relative "event"
3
6
 
4
7
  module Flu
@@ -71,12 +74,17 @@ module Flu
71
74
  response_code: response.status,
72
75
  user_agent: request.user_agent,
73
76
  duration: Time.zone.now - request_start_time,
74
- params: params.except(*ignored_request_params).except(*@default_ignored_request_params).to_h
77
+ params: extract_params(params, ignored_request_params)
75
78
  }
76
79
  end
77
80
 
78
81
  private
79
82
 
83
+ def extract_params(params, ignored_request_params)
84
+ remaining = params.except(*ignored_request_params).except(*@default_ignored_request_params)
85
+ remaining.respond_to?(:to_unsafe_h) ? remaining.to_unsafe_h.to_h : remaining.to_h
86
+ end
87
+
80
88
  def deep_camelize(value)
81
89
  case value
82
90
  when Array
@@ -42,8 +42,7 @@ module Flu
42
42
  end
43
43
 
44
44
  def find_all_entity_types
45
- eager_loaded = Rails.application.eager_load!
46
- Zeitwerk::Loader.eager_load_all if !eager_loaded && defined?(Zeitwerk)
45
+ Rails.application.eager_load!
47
46
  ActiveRecord::Base.descendants
48
47
  end
49
48
 
@@ -1,3 +1,3 @@
1
1
  module Flu
2
- VERSION = "1.2.0"
2
+ VERSION = "8.0.0"
3
3
  end
data/lib/flu-rails.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "logger"
2
2
  require "json"
3
+ require "active_support/core_ext/module/introspection"
3
4
  require_relative "flu-rails/version"
4
5
  require_relative "flu-rails/event"
5
6
  require_relative "flu-rails/event_factory"
@@ -33,6 +34,7 @@ module Flu
33
34
  end
34
35
 
35
36
  def self.init
37
+ @configuration.application_name ||= default_application_name
36
38
  raise "configuration.application_name must not be nil" if @configuration.application_name.nil?
37
39
  @logger = @configuration.logger
38
40
  @event_factory = Flu::EventFactory.new(@configuration)
@@ -40,6 +42,15 @@ module Flu
40
42
  extend_models_and_controllers
41
43
  end
42
44
 
45
+ def self.default_application_name
46
+ if defined?(Rails) && Rails.respond_to?(:application)
47
+ application = Rails.application
48
+ application.nil? ? nil : application.class.module_parent_name
49
+ else
50
+ nil
51
+ end
52
+ end
53
+
43
54
  def self.create_event_publisher(configuration)
44
55
  if is_testing_environment?
45
56
  logger.info("Loading Flu with a dummy event publisher (this will not connect any exchange)")
@@ -79,7 +90,7 @@ module Flu
79
90
  config.auto_connect_to_exchange = true
80
91
  config.default_ignored_model_changes = [:password, :password_confirmation, :created_at, :updated_at]
81
92
  config.default_ignored_request_params = [:password, :password_confirmation, :controller, :action]
82
- config.application_name = defined?(Rails) ? Rails.application.class.module_parent_name : nil
93
+ config.application_name = nil
83
94
  config.bunny_options = {}
84
95
  end
85
96
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flu-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 8.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loïc Vigneron
@@ -12,75 +12,89 @@ cert_chain: []
12
12
  date: 1980-01-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: bunny
15
+ name: actionpack
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '3.1'
20
+ version: '8.0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '3.1'
27
+ version: '8.0'
28
28
  - !ruby/object:Gem::Dependency
29
- name: logger
29
+ name: activerecord
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '1.7'
34
+ version: '8.0'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '1.7'
41
+ version: '8.0'
42
42
  - !ruby/object:Gem::Dependency
43
- name: rabbitmq_http_api_client
43
+ name: activesupport
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '3.2'
48
+ version: '8.0'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '3.2'
55
+ version: '8.0'
56
56
  - !ruby/object:Gem::Dependency
57
- name: actionpack
57
+ name: bunny
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: '8.0'
63
- type: :development
62
+ version: '3.1'
63
+ type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: '8.0'
69
+ version: '3.1'
70
70
  - !ruby/object:Gem::Dependency
71
- name: activerecord
71
+ name: logger
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: '8.0'
77
- type: :development
76
+ version: '1.7'
77
+ type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: '8.0'
83
+ version: '1.7'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rabbitmq_http_api_client
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '3.2'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '3.2'
84
98
  - !ruby/object:Gem::Dependency
85
99
  name: byebug
86
100
  requirement: !ruby/object:Gem::Requirement
@@ -109,6 +123,20 @@ dependencies:
109
123
  - - "~>"
110
124
  - !ruby/object:Gem::Version
111
125
  version: '0.6'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rake
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '13.0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '13.0'
112
140
  - !ruby/object:Gem::Dependency
113
141
  name: rspec
114
142
  requirement: !ruby/object:Gem::Requirement
@@ -186,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
214
  - !ruby/object:Gem::Version
187
215
  version: '0'
188
216
  requirements: []
189
- rubygems_version: 4.0.17
217
+ rubygems_version: 3.6.9
190
218
  specification_version: 4
191
219
  summary: Track your application events and publish them to RabbitMQ.
192
220
  test_files: []