biscuit-rails 0.2.0 → 0.3.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: a99734c304d99da013a29fd797e8d8d9461bdea8811bb87997bddc4a0b1cd100
4
- data.tar.gz: b93c476239e0e9ee02f5466596b1de11dc3f24fcb3794c7b99497a66073efaf4
3
+ metadata.gz: 6af5d93f2b84a14db762315e56fc1e75b1ecd88b0d7763480c81364fcab20046
4
+ data.tar.gz: 13c0ca1019abd874c65ec3a5acd5552af3a2bc84acba6a3c2b2fc7d3c40abb51
5
5
  SHA512:
6
- metadata.gz: 695482883b254ce859513919089eaa30f80947d792f9755cba738db35aff1bfde4bf6472cdbde5860b4e300acf05dda113ba595f26a422f2d6d60ef1833975d1
7
- data.tar.gz: 197a2f37232f33b7b179fef7418497eaed80a3630016175e75709315e01778b273fdc0fa8347371b07c84884b0d78b0e696b9d6f0093eb930f779d8bc4ed0c6b
6
+ metadata.gz: 51ac7899d57bb410cfa26695a7c583490afdf7dc27310086cbce2489678475af409b6391b189570baf2f1836fb07215f20308d04fbb1d6794151affbf7bc1774
7
+ data.tar.gz: 278a5ba3887c2aa9a2d7172b506fdb2c02837ba31827db44a9f58e259a337ebf05334d69f086e99fac6b2d39a22d55ab3a63d1eee29e0e9f095e40c0373ebe2b
data/CHANGELOG.md CHANGED
@@ -5,6 +5,43 @@ 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
+ ## [0.3.0] - 2026-06-21
9
+
10
+ ### Added
11
+
12
+ - `biscuit:consent-given` DOM event — dispatched on the banner element (bubbles)
13
+ after every successful consent POST, with `detail.categories` mirroring the
14
+ saved payload. Lets apps run tracking code (GA4 Consent Mode v2, GTM dataLayer,
15
+ Meta Pixel, etc.) immediately after consent without any page reload.
16
+
17
+ ### Removed
18
+
19
+ - `reload_on_consent` option for `biscuit_banner` — removed as the
20
+ `biscuit:consent-given` event supersedes it. Apps that need a page reload
21
+ after consent can do `document.addEventListener("biscuit:consent-given",
22
+ () => window.location.reload())`.
23
+
24
+ **Migration:** remove `reload_on_consent: true` from any `biscuit_banner`
25
+ calls. Add the one-liner above if a reload is still needed for your use case.
26
+
27
+ ---
28
+
29
+ ## [0.2.1] - 2026-04-02
30
+
31
+ ### Fixed
32
+
33
+ - `biscuit-install` skill: add Sprockets manifest step — when not using Propshaft,
34
+ `biscuit/biscuit.css` and `biscuit/biscuit_controller.js` must be linked in
35
+ `app/assets/config/manifest.js` or they 404 in test and production
36
+ - `biscuit-install` skill: fix integration test POST syntax — `body:` is not a valid
37
+ Rails integration test keyword; replaced with `params: { ... }.to_json` and explicit
38
+ `Content-Type`/`Accept` headers
39
+ - `biscuit-install` skill: explain why the Stimulus controller must be registered
40
+ manually (`eagerLoadControllersFrom` only discovers controllers in
41
+ `app/javascript/controllers/`, not gem-provided ones)
42
+
43
+ ---
44
+
8
45
  ## [0.2.0] - 2026-03-31
9
46
 
10
47
  ### Added
data/README.md CHANGED
@@ -5,6 +5,8 @@ bottom/top banner, manages consent state via a browser cookie, and exposes a
5
5
  Stimulus controller for interactivity. Supports i18n and CSS custom property
6
6
  theming with no external runtime dependencies.
7
7
 
8
+ [Project page](https://bemused.org/projects/biscuit-rails/) · [GitHub](https://github.com/garethfr/biscuit-rails) · [Changelog](https://github.com/garethfr/biscuit-rails/blob/main/CHANGELOG.md) · [Issues](https://github.com/garethfr/biscuit-rails/issues)
9
+
8
10
  ---
9
11
 
10
12
  ## Requirements
@@ -115,20 +117,45 @@ revisit their preferences at any time.
115
117
 
116
118
  ## Banner Options
117
119
 
118
- `biscuit_banner` accepts keyword options to control behaviour per-page:
120
+ `biscuit_banner` accepts keyword options to control behaviour per-page.
119
121
 
120
- ### `reload_on_consent`
122
+ Currently there are no banner-level options. Configuration is done via the
123
+ initializer — see **Configuration** below.
121
124
 
122
- When `true`, the page reloads via `Turbo.visit` after the user saves their
123
- consent choice, instead of just hiding the banner. This is useful when your
124
- layout conditionally loads scripts based on consent — a reload ensures those
125
- scripts are evaluated with the new cookie in place.
125
+ ---
126
126
 
127
- ```erb
128
- <%= biscuit_banner(reload_on_consent: true) %>
127
+ ## `biscuit:consent-given` event
128
+
129
+ After any consent POST succeeds, the controller dispatches a
130
+ `biscuit:consent-given` DOM event on the banner's root element. The event
131
+ bubbles, so you can listen anywhere:
132
+
133
+ ```js
134
+ document.addEventListener("biscuit:consent-given", ({ detail }) => {
135
+ if (detail.categories.analytics) {
136
+ // GA4 Consent Mode v2 — no page reload needed
137
+ gtag("consent", "update", { analytics_storage: "granted" })
138
+ gtag("event", "page_view")
139
+ }
140
+ if (detail.categories.marketing) {
141
+ fbq("consent", "grant")
142
+ fbq("track", "PageView")
143
+ }
144
+ })
129
145
  ```
130
146
 
131
- Default: `false` the banner hides in place without a page reload.
147
+ `detail.categories` mirrors the payload sent to the server
148
+ `{ analytics: true, marketing: false, ... }`.
149
+
150
+ If you need a full page reload after consent (for example, to trigger
151
+ server-side `biscuit_allowed?()` guards on the current page), do it in the
152
+ handler:
153
+
154
+ ```js
155
+ document.addEventListener("biscuit:consent-given", () => {
156
+ window.location.reload()
157
+ })
158
+ ```
132
159
 
133
160
  ---
134
161
 
@@ -364,10 +391,8 @@ Biscuit provides the consent UI and storage mechanism. You are responsible for:
364
391
  ```
365
392
 
366
393
  For scripts that must load on the client side after a user accepts consent
367
- during their current session (without a page reload), listen for the Fetch
368
- response in your own JavaScript and initialise scripts there, or use a
369
- lightweight Turbo visit to reload the page after the consent POST succeeds.
370
- (Turbo Stream support for post-consent injection is planned for v2.)
394
+ during their current session (without a page reload), listen for the
395
+ `biscuit:consent-given` DOM event and initialise scripts there.
371
396
 
372
397
  ### GDPR compliance checklist
373
398
 
@@ -6,8 +6,7 @@ export default class extends Controller {
6
6
  endpoint: String,
7
7
  csrfToken: String,
8
8
  position: { type: String, default: "bottom" },
9
- alreadyConsented: { type: Boolean, default: false },
10
- reloadOnConsent: { type: Boolean, default: false }
9
+ alreadyConsented: { type: Boolean, default: false }
11
10
  }
12
11
 
13
12
  connect() {
@@ -70,12 +69,12 @@ export default class extends Controller {
70
69
  body: JSON.stringify({ categories })
71
70
  })
72
71
  if (response.ok) {
73
- if (this.reloadOnConsentValue) {
74
- Turbo.visit(window.location.href)
75
- } else {
76
- this.#hideBanner()
77
- this.#showManageLink()
78
- }
72
+ this.element.dispatchEvent(new CustomEvent("biscuit:consent-given", {
73
+ bubbles: true,
74
+ detail: { categories }
75
+ }))
76
+ this.#hideBanner()
77
+ this.#showManageLink()
79
78
  }
80
79
  } catch (error) {
81
80
  console.error("[Biscuit] Failed to save consent:", error)
@@ -2,8 +2,7 @@
2
2
  data-biscuit-position-value="<%= Biscuit.configuration.position %>"
3
3
  data-biscuit-csrf-token-value="<%= form_authenticity_token %>"
4
4
  data-biscuit-endpoint-value="<%= biscuit.consent_path %>"
5
- data-biscuit-already-consented-value="<%= consent.given? %>"
6
- data-biscuit-reload-on-consent-value="<%= options[:reload_on_consent] ? 'true' : 'false' %>">
5
+ data-biscuit-already-consented-value="<%= consent.given? %>">
7
6
 
8
7
  <div class="biscuit-banner"
9
8
  data-biscuit-target="banner"
@@ -1,3 +1,3 @@
1
1
  module Biscuit
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -100,6 +100,8 @@ application.register("biscuit", BiscuitController)
100
100
 
101
101
  Ensure `application` is already imported at the top of that file (it will be in the standard Rails 8 scaffold).
102
102
 
103
+ The explicit import is required because Rails' `eagerLoadControllersFrom` only auto-discovers controllers under `app/javascript/controllers/` — it cannot find controllers provided by gems, so they must always be registered manually.
104
+
103
105
  ### If using esbuild / jsbundling
104
106
 
105
107
  The same import and register lines apply, but inform the user that `@hotwired/stimulus` must be marked as external in their esbuild config so it is not bundled twice:
@@ -126,6 +128,15 @@ If the app uses `reload_on_consent: true` (from Step 4), use:
126
128
  <%= biscuit_banner(reload_on_consent: true) %>
127
129
  ```
128
130
 
131
+ ### Sprockets manifest (if not using Propshaft)
132
+
133
+ If the app uses Sprockets (no `propshaft` in Gemfile), check whether `app/assets/config/manifest.js` exists. If it does, append these two lines if they are not already present — otherwise the stylesheet and JS file will 404 in test and production:
134
+
135
+ ```js
136
+ //= link biscuit/biscuit.css
137
+ //= link biscuit/biscuit_controller.js
138
+ ```
139
+
129
140
  ---
130
141
 
131
142
  ## Step 7 — Cookie and tracking script audit
@@ -209,20 +220,18 @@ class BiscuitConsentTest < ActionDispatch::IntegrationTest
209
220
  end
210
221
 
211
222
  test "accept all sets consent cookie" do
212
- post "/biscuit/consent", params: {},
213
- headers: { "Content-Type" => "application/json" },
214
- as: :json,
215
- body: { categories: { analytics: true, marketing: true } }.to_json
223
+ post "/biscuit/consent",
224
+ params: { categories: { analytics: true, marketing: true } }.to_json,
225
+ headers: { "Content-Type" => "application/json", "Accept" => "application/json" }
216
226
  assert_response :success
217
227
  assert Biscuit::Consent.new(cookies).given?
218
228
  assert Biscuit::Consent.new(cookies).allowed?(:analytics)
219
229
  end
220
230
 
221
231
  test "reject all sets non-required categories to false" do
222
- post "/biscuit/consent", params: {},
223
- headers: { "Content-Type" => "application/json" },
224
- as: :json,
225
- body: { categories: { analytics: false, marketing: false } }.to_json
232
+ post "/biscuit/consent",
233
+ params: { categories: { analytics: false, marketing: false } }.to_json,
234
+ headers: { "Content-Type" => "application/json", "Accept" => "application/json" }
226
235
  assert_response :success
227
236
  assert Biscuit::Consent.new(cookies).given?
228
237
  assert_equal false, Biscuit::Consent.new(cookies).allowed?(:analytics)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: biscuit-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gareth James
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-03-31 00:00:00.000000000 Z
10
+ date: 2026-06-21 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails