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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6af5d93f2b84a14db762315e56fc1e75b1ecd88b0d7763480c81364fcab20046
|
|
4
|
+
data.tar.gz: 13c0ca1019abd874c65ec3a5acd5552af3a2bc84acba6a3c2b2fc7d3c40abb51
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
122
|
+
Currently there are no banner-level options. Configuration is done via the
|
|
123
|
+
initializer — see **Configuration** below.
|
|
121
124
|
|
|
122
|
-
|
|
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
|
-
|
|
128
|
-
|
|
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
|
-
|
|
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
|
|
368
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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"
|
data/lib/biscuit/version.rb
CHANGED
|
@@ -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",
|
|
213
|
-
|
|
214
|
-
|
|
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",
|
|
223
|
-
|
|
224
|
-
|
|
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.
|
|
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-
|
|
10
|
+
date: 2026-06-21 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rails
|