rails_consent 0.1.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 +7 -0
- data/CHANGELOG.md +12 -0
- data/CONTRIBUTING.md +35 -0
- data/LICENSE +21 -0
- data/README.md +264 -0
- data/app/assets/config/rails_consent_manifest.js +2 -0
- data/app/assets/javascripts/rails_consent.js +379 -0
- data/app/assets/stylesheets/rails_consent/application.css +21 -0
- data/app/controllers/concerns/rails_consent/controller_helpers.rb +86 -0
- data/app/controllers/rails_consent/preferences_controller.rb +55 -0
- data/app/helpers/rails_consent/application_helper.rb +44 -0
- data/app/views/rails_consent/_banner.html.erb +45 -0
- data/app/views/rails_consent/_category_toggle.html.erb +32 -0
- data/app/views/rails_consent/_cookie_table.html.erb +19 -0
- data/app/views/rails_consent/_preferences_modal.html.erb +53 -0
- data/config/locales/en.yml +53 -0
- data/lib/generators/rails_consent/install/install_generator.rb +19 -0
- data/lib/generators/rails_consent/install/templates/initializer.rb +109 -0
- data/lib/generators/rails_consent/install/templates/rails_consent.en.yml +53 -0
- data/lib/rails_consent/category.rb +36 -0
- data/lib/rails_consent/category_loader.rb +60 -0
- data/lib/rails_consent/configuration.rb +273 -0
- data/lib/rails_consent/cookie_store.rb +56 -0
- data/lib/rails_consent/default_consent_resolver.rb +13 -0
- data/lib/rails_consent/engine.rb +25 -0
- data/lib/rails_consent/preference_set.rb +49 -0
- data/lib/rails_consent/version.rb +3 -0
- data/lib/rails_consent.rb +31 -0
- metadata +94 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 19e1554e153f613453261717b4d18b77bc83664efe9e35fb178553d45802ad97
|
|
4
|
+
data.tar.gz: df90bf179fe78aab0df69a290aa097c40bdedc21295d24523e6db492e53bd7be
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 35f2aaa9ed70c1a70e79769b0f45d03be70bddf0abf3e3ff9e5441867a6c1ddc8ef7d7c51c56dc6aa8547ddaf911a616f1083ebdb7f519e3893267f8e9cf2d1b
|
|
7
|
+
data.tar.gz: 24b811e64f10bdaaf9aab27aa48a130430caf7fb93576b99a07bb1b1a527eac8fe54b15453f1718c8ade2ab3538d437d02d568289d49d08d4b18d11ab3c8d6b8
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Relaxed the development baseline to Ruby 3.4.7 and Rails 7.1+
|
|
6
|
+
- Simplified the gem contract so consent persistence stays in the host application
|
|
7
|
+
- Refreshed the documentation application into a richer documentation-first Rails app with enhanced live consent demos
|
|
8
|
+
|
|
9
|
+
## 0.1.0
|
|
10
|
+
|
|
11
|
+
- Initial release of `rails_consent`
|
|
12
|
+
- Added the Rails Engine, helpers, generators, templates, JavaScript runtime, specs, and the documentation application
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for considering a contribution to `rails_consent`.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
1. Install the bundle:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bundle install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Run the test suite:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bundle exec rspec
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
3. Verify changes against the public documentation site and reference integration before opening a pull request.
|
|
20
|
+
|
|
21
|
+
## Contribution Guidelines
|
|
22
|
+
|
|
23
|
+
- Keep consent behavior in the library and presentation choices in the host app whenever possible.
|
|
24
|
+
- Add or update specs around the public contract of the gem.
|
|
25
|
+
- Favor extension points over one-off conditionals.
|
|
26
|
+
- Avoid introducing database persistence to the gem itself.
|
|
27
|
+
- Update documentation and examples when public behavior changes.
|
|
28
|
+
|
|
29
|
+
## Pull Requests
|
|
30
|
+
|
|
31
|
+
Please include:
|
|
32
|
+
|
|
33
|
+
- A clear description of the problem and the chosen solution
|
|
34
|
+
- Tests covering the public behavior you changed
|
|
35
|
+
- Documentation updates when relevant
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dhairya Gabhawala
|
|
4
|
+
|
|
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:
|
|
11
|
+
|
|
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
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/dhairyagabha/rails_consent/main/.github/assets/rails-consent-lockup.png" alt="Rails Consent" width="420">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://rubygems.org/gems/rails_consent">
|
|
7
|
+
<img src="https://img.shields.io/gem/v/rails_consent.svg" alt="RubyGems version">
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://rails-consent.dhairyagabhawala.com">Documentation</a>
|
|
13
|
+
·
|
|
14
|
+
<a href="https://rails-consent.dhairyagabhawala.com/docs/example-integrations">See the demo</a>
|
|
15
|
+
·
|
|
16
|
+
<a href="https://github.com/dhairyagabha/rails_consent/blob/main/CHANGELOG.md">Changelog</a>
|
|
17
|
+
·
|
|
18
|
+
<a href="https://rubygems.org/gems/rails_consent">RubyGems</a>
|
|
19
|
+
·
|
|
20
|
+
<a href="https://github.com/dhairyagabha/rails_consent">GitHub</a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
# Rails Consent
|
|
24
|
+
|
|
25
|
+
`rails_consent` is a Rails engine for cookie consent in Rails applications, built around locale-backed categories, a built-in signed cookie flow, small helper APIs, and a minimal JavaScript runtime.
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- Cookie consent banner and preferences modal
|
|
30
|
+
- Built-in signed cookie persistence with optional `:db` storage hooks
|
|
31
|
+
- Locale-backed category definitions and interface copy
|
|
32
|
+
- Helpers for views, controllers, and layouts
|
|
33
|
+
- Minimal browser runtime with lifecycle events and a small client-side API
|
|
34
|
+
- Overrideable templates without copying runtime assets
|
|
35
|
+
- Importmap and Turbo-friendly integration
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
Add the gem to your Rails app:
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
gem "rails_consent"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then install it:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
bundle install
|
|
49
|
+
bin/rails generate rails_consent:install
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The installer creates:
|
|
53
|
+
|
|
54
|
+
- `config/initializers/rails_consent.rb`
|
|
55
|
+
- `config/locales/rails_consent.en.yml`
|
|
56
|
+
|
|
57
|
+
In the default `:cookie` mode, that generated setup is enough to render the UI and persist consent through a signed Rails cookie.
|
|
58
|
+
|
|
59
|
+
## Define Categories and Copy
|
|
60
|
+
|
|
61
|
+
Rails Consent keeps banner copy, modal copy, and category definitions in one locale file:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
en:
|
|
65
|
+
rails_consent:
|
|
66
|
+
banner:
|
|
67
|
+
eyebrow: Privacy settings
|
|
68
|
+
title: Review cookie choices
|
|
69
|
+
description: Necessary cookies stay enabled. Optional categories can be updated at any time.
|
|
70
|
+
accept_all: Allow all
|
|
71
|
+
reject_optional: Reject optional
|
|
72
|
+
manage_preferences: Privacy preferences
|
|
73
|
+
modal:
|
|
74
|
+
eyebrow: Cookie preferences
|
|
75
|
+
title: Review cookie categories
|
|
76
|
+
save_preferences: Save settings
|
|
77
|
+
categories:
|
|
78
|
+
necessary:
|
|
79
|
+
label: Necessary
|
|
80
|
+
required: true
|
|
81
|
+
description: Essential cookies required for site functionality
|
|
82
|
+
analytics:
|
|
83
|
+
label: Analytics
|
|
84
|
+
required: false
|
|
85
|
+
description: Used to understand visitor behavior
|
|
86
|
+
marketing:
|
|
87
|
+
label: Marketing
|
|
88
|
+
required: false
|
|
89
|
+
description: Used for advertising and remarketing
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Display order follows the locale file order.
|
|
93
|
+
|
|
94
|
+
## Configure Rails Consent
|
|
95
|
+
|
|
96
|
+
The initializer defines where consent lives, how the banner behaves by default, and how category checks should resolve:
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
RailsConsent.configure do |config|
|
|
100
|
+
config.storage = :cookie
|
|
101
|
+
config.banner_position = :bottom
|
|
102
|
+
config.prompt_dismissible = true
|
|
103
|
+
config.cookie_name = "rails_consent_preferences"
|
|
104
|
+
config.cookie_expiration_days = 180
|
|
105
|
+
# config.cookie_same_site = :lax
|
|
106
|
+
# config.cookie_http_only = true
|
|
107
|
+
# config.cookie_secure = ->(request) { request.ssl? || Rails.env.production? }
|
|
108
|
+
config.consent_resolver = RailsConsent::DefaultConsentResolver.new
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`consent_resolver` is required. Start with `RailsConsent::DefaultConsentResolver.new` when each optional category maps directly to a boolean consent decision, then replace it when your application needs additional rules.
|
|
113
|
+
|
|
114
|
+
## Render the Consent UI
|
|
115
|
+
|
|
116
|
+
Load the gem assets in your layout and keep the banner mounted near the bottom of the page:
|
|
117
|
+
|
|
118
|
+
```erb
|
|
119
|
+
<head>
|
|
120
|
+
<%= rails_consent_assets %>
|
|
121
|
+
</head>
|
|
122
|
+
|
|
123
|
+
<body>
|
|
124
|
+
<%= yield %>
|
|
125
|
+
<%= rails_consent_banner %>
|
|
126
|
+
</body>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`rails_consent_assets` loads only the gem's core runtime assets: `rails_consent.js` and the minimal `rails_consent/application.css` stylesheet used for runtime visibility utilities.
|
|
130
|
+
|
|
131
|
+
If one page needs different behavior, override it locally:
|
|
132
|
+
|
|
133
|
+
```erb
|
|
134
|
+
<%= rails_consent_banner position: :top, dismissible: false %>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Reopen Preferences Later
|
|
138
|
+
|
|
139
|
+
Use the shared helper anywhere you want to reopen the preferences modal:
|
|
140
|
+
|
|
141
|
+
```erb
|
|
142
|
+
<%= rails_consent_preferences_button "Privacy preferences", class: "footer-button" %>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
That helper is a good fit for footers, privacy pages, and account settings screens.
|
|
146
|
+
|
|
147
|
+
## Gate Optional Behavior
|
|
148
|
+
|
|
149
|
+
Use `consent_given?` anywhere you need to align server-rendered behavior with the current consent state:
|
|
150
|
+
|
|
151
|
+
```erb
|
|
152
|
+
<% if consent_given?(:analytics) %>
|
|
153
|
+
<%= render "analytics_script" %>
|
|
154
|
+
<% end %>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The public helper surface is:
|
|
158
|
+
|
|
159
|
+
```ruby
|
|
160
|
+
rails_consent_assets
|
|
161
|
+
rails_consent_banner
|
|
162
|
+
rails_consent_preferences_button
|
|
163
|
+
consent_given?(:analytics)
|
|
164
|
+
consent_preferences
|
|
165
|
+
consent_recorded?
|
|
166
|
+
reset_consent!
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Client-side API
|
|
170
|
+
|
|
171
|
+
Rails Consent also exposes a small browser API through `window.RailsConsent`:
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
window.RailsConsent.preferences()
|
|
175
|
+
window.RailsConsent.consentGiven("analytics")
|
|
176
|
+
window.RailsConsent.consentRecorded()
|
|
177
|
+
window.RailsConsent.sessionId()
|
|
178
|
+
window.RailsConsent.openPreferences()
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Lifecycle events are dispatched on `document` so host apps can react without modifying the gem runtime:
|
|
182
|
+
|
|
183
|
+
- `rails-consent:banner-shown`
|
|
184
|
+
- `rails-consent:preferences-opened`
|
|
185
|
+
- `rails-consent:preferences-saved`
|
|
186
|
+
- `rails-consent:preferences-updated`
|
|
187
|
+
- `rails-consent:accepted-all`
|
|
188
|
+
- `rails-consent:rejected-optional`
|
|
189
|
+
- `rails-consent:dismissed`
|
|
190
|
+
|
|
191
|
+
## Storage Modes
|
|
192
|
+
|
|
193
|
+
### Signed Cookie Storage
|
|
194
|
+
|
|
195
|
+
`config.storage = :cookie` uses the built-in persistence route and a signed cookie payload keyed by category name. This is the default integration path.
|
|
196
|
+
|
|
197
|
+
If you want to wrap the built-in cookie flow without replacing it, provide `cookie_reader`, `cookie_writer`, or `cookie_destroyer` hooks around `RailsConsent::CookieStore`.
|
|
198
|
+
|
|
199
|
+
### Database-backed Storage
|
|
200
|
+
|
|
201
|
+
When consent should live alongside a user or account record, switch only the storage hooks:
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
RailsConsent.configure do |config|
|
|
205
|
+
config.storage = :db
|
|
206
|
+
config.banner_position = :bottom
|
|
207
|
+
config.prompt_dismissible = true
|
|
208
|
+
config.consent_resolver = RailsConsent::DefaultConsentResolver.new
|
|
209
|
+
|
|
210
|
+
config.preferences_provider = ->(context:, **) do
|
|
211
|
+
context.current_user&.consent_preferences || {}
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
config.preferences_writer = ->(preferences:, context:, **) do
|
|
215
|
+
user = context.current_user
|
|
216
|
+
raise "current_user is required for db-backed consent" unless user
|
|
217
|
+
|
|
218
|
+
user.update!(consent_preferences: preferences)
|
|
219
|
+
user.consent_preferences
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
config.preferences_destroyer = ->(context:, **) do
|
|
223
|
+
context.current_user&.update!(consent_preferences: {})
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Most applications pair that initializer with a JSON or JSONB column such as `users.consent_preferences`.
|
|
229
|
+
|
|
230
|
+
## Customize Presentation
|
|
231
|
+
|
|
232
|
+
Override any shipped partial from your host app by creating:
|
|
233
|
+
|
|
234
|
+
```text
|
|
235
|
+
app/views/rails_consent/_banner.html.erb
|
|
236
|
+
app/views/rails_consent/_preferences_modal.html.erb
|
|
237
|
+
app/views/rails_consent/_category_toggle.html.erb
|
|
238
|
+
app/views/rails_consent/_cookie_table.html.erb
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Keep wording changes in locale YAML when the markup stays the same. Reach for template overrides only when the structure itself needs to change.
|
|
242
|
+
|
|
243
|
+
## Troubleshooting
|
|
244
|
+
|
|
245
|
+
- If the banner never appears, confirm `rails_consent_banner` is mounted in your layout and consent has not already been recorded.
|
|
246
|
+
- If the UI opens without styles or behavior, confirm `rails_consent_assets` is loaded in `<head>`.
|
|
247
|
+
- If boot fails with a configuration error, compare your initializer to the generated file and restore any required lines that were removed.
|
|
248
|
+
- If a custom category never enables, review `consent_resolver` after changing `config/locales/rails_consent.en.yml`.
|
|
249
|
+
- If `:db` mode does not persist updates, confirm `preferences_provider`, `preferences_writer`, and `preferences_destroyer` are all configured and return hashes keyed by category name.
|
|
250
|
+
- If client-side integrations cannot read consent, keep `rails_consent_banner` mounted on the page so `window.RailsConsent` has a rendered boundary to read from.
|
|
251
|
+
|
|
252
|
+
## Documentation
|
|
253
|
+
|
|
254
|
+
Full guides, live demos, and integration examples are available at:
|
|
255
|
+
|
|
256
|
+
- https://rails-consent.dhairyagabhawala.com/
|
|
257
|
+
|
|
258
|
+
## Contributing
|
|
259
|
+
|
|
260
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for development and contribution guidelines.
|
|
261
|
+
|
|
262
|
+
## License
|
|
263
|
+
|
|
264
|
+
Released under the MIT license. See [`LICENSE`](LICENSE).
|