action_version_preview 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +44 -0
- data/README.md +88 -70
- data/app/views/action_version_preview/_variant_switcher.html.erb +2 -2
- data/docs/releases/0.2.0.md +46 -0
- data/docs/releasing.md +97 -0
- data/docs/usage.md +295 -0
- data/lib/action_version_preview/engine.rb +7 -1
- data/lib/action_version_preview/switcher_helper.rb +18 -0
- data/lib/action_version_preview/version.rb +1 -1
- metadata +9 -4
- data/app/helpers/action_version_preview/switcher_helper.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e06ec511eedee6043f22f30770eba50bbaaf4e084607fa22aefc3dd0bec1c590
|
|
4
|
+
data.tar.gz: c0b5c97188fc3e16d3a68d2df693198f96957f035fc565af62b07cac569d153e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c4a6ecab2cdcff048f1de1181d2924f6a5f7531fa20855a0c2af6fbeafd632e394e385fe34d95f5e447bb5e65cf30215f1cf1adf837a39b94ec60e1945e21b00
|
|
7
|
+
data.tar.gz: '089c2fb8619a595af161f68c3f5e73f1ce16cd0df053c6b53320bebfb6954764a86608efe93b944e2a030c68031f453198974c0c0279a7584e6009e967d80b21'
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
## [0.2.0] - 2026-09-15
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed `ActionVersionPreview::SwitcherHelper` load-order errors during Rails boot
|
|
10
|
+
and asset precompilation, including early controller/view loading.
|
|
11
|
+
- Kept switcher links on the current path, preserving mounted prefixes, nested
|
|
12
|
+
query filters, and configured preview parameter names. Query keys are no longer
|
|
13
|
+
interpreted as Rails routing options.
|
|
14
|
+
- Excluded POST body fields from switcher URLs.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Fresh-process regression tests for early/lazy framework loading, development
|
|
19
|
+
reloading, and production asset precompilation using a built and installed gem.
|
|
20
|
+
- Integration tests for switcher URL safety, mounted paths, custom parameters,
|
|
21
|
+
nested filters, and POST-body exclusion.
|
|
22
|
+
- Comprehensive public usage documentation and upgrade instructions, included
|
|
23
|
+
with the gem alongside this changelog.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Explicitly load the stateless switcher helper from `lib` so its availability does
|
|
28
|
+
not depend on Rails autoloading or reloading.
|
|
29
|
+
- Updated development dependency resolution and GitHub Actions versions.
|
|
30
|
+
- Clarified supported integration behavior and current discovery limitations.
|
|
31
|
+
|
|
32
|
+
No migrations or required configuration changes. Declared Ruby/Rails requirements,
|
|
33
|
+
preview access defaults, and Default-link behavior are unchanged. Full details are
|
|
34
|
+
in the [0.2.0 release notes](docs/releases/0.2.0.md).
|
|
35
|
+
|
|
36
|
+
## [0.1.0] - 2025-12-17
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Initial release.
|
|
41
|
+
- Side-by-side UI previews in separate tabs using Rails view variants.
|
|
42
|
+
- Automatic integration with `ActionController::Base`.
|
|
43
|
+
- Optional variant switcher and configurable preview parameter/access check.
|
|
44
|
+
- Declared support for Rails 7.0 through 8.x.
|
data/README.md
CHANGED
|
@@ -1,118 +1,136 @@
|
|
|
1
1
|
# ActionVersionPreview
|
|
2
2
|
|
|
3
|
-
Preview multiple versions of
|
|
3
|
+
Preview multiple versions of a Rails UI in separate browser tabs using native
|
|
4
|
+
view variants. Add variant templates, open their URLs, and compare designs while
|
|
5
|
+
signed in as the same user. No additional database, feature-flag service, or
|
|
6
|
+
JavaScript is required.
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
[Full usage guide](docs/usage.md) · [Changelog](CHANGELOG.md) · [RubyGems](https://rubygems.org/gems/action_version_preview)
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
## Install
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<img width="2146" height="2014" alt="image" src="https://github.com/user-attachments/assets/c39b1305-ad14-4958-be39-d714d53d1990" />
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
Add to your Gemfile:
|
|
12
|
+
Add the gem to your Rails application's Gemfile:
|
|
16
13
|
|
|
17
14
|
```ruby
|
|
18
|
-
gem "action_version_preview"
|
|
15
|
+
gem "action_version_preview", "~> 0.2.0"
|
|
19
16
|
```
|
|
20
17
|
|
|
21
|
-
Run `bundle install
|
|
18
|
+
Run `bundle install` and restart the application. No generator or engine mount is
|
|
19
|
+
needed. Preview selection is added to controllers inheriting from
|
|
20
|
+
`ActionController::Base`.
|
|
22
21
|
|
|
23
|
-
##
|
|
22
|
+
## Quick start
|
|
24
23
|
|
|
25
|
-
### 1. Create
|
|
24
|
+
### 1. Create variant templates
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
For a `DashboardController#show` action, keep a default template and add variants:
|
|
28
27
|
|
|
29
|
-
```
|
|
30
|
-
app/views/dashboard/show.html.erb
|
|
31
|
-
app/views/dashboard/show.html+v2.erb
|
|
32
|
-
app/views/dashboard/show.html+redesign.erb
|
|
28
|
+
```text
|
|
29
|
+
app/views/dashboard/show.html.erb
|
|
30
|
+
app/views/dashboard/show.html+v2.erb
|
|
31
|
+
app/views/dashboard/show.html+redesign.erb
|
|
33
32
|
```
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
Use names such as `v2`, `redesign`, or `new_layout` for automatic switcher discovery.
|
|
36
35
|
|
|
37
|
-
### 2.
|
|
36
|
+
### 2. Open the preview URLs
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
In development or test:
|
|
39
|
+
|
|
40
|
+
| URL | Result |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `/dashboard` | Normal rendering |
|
|
43
|
+
| `/dashboard?vv=v2` | Selects the `v2` variant |
|
|
44
|
+
| `/dashboard?vv=redesign` | Selects the `redesign` variant |
|
|
45
|
+
| `/dashboard?vv=true` | Enables the switcher without selecting a variant |
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
The last example keeps any variant your application already set, such as a mobile
|
|
48
|
+
variant. Otherwise it renders the default template.
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
### 3. Add the optional switcher
|
|
51
|
+
|
|
52
|
+
Put this near the end of your application layout's body:
|
|
48
53
|
|
|
49
54
|
```erb
|
|
50
55
|
<%= variant_switcher %>
|
|
51
56
|
```
|
|
52
57
|
|
|
53
|
-
The switcher
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
The switcher appears only when preview mode is requested, access is allowed, and
|
|
59
|
+
variant templates are discovered for the current action. Its links preserve the
|
|
60
|
+
current path, mounted prefix, and query filters. **Default** removes the preview
|
|
61
|
+
parameter and closes the switcher. Add `?vv=true` again to reopen it.
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
Automatic discovery in 0.2.0 covers HTML ERB action templates in the host app's
|
|
64
|
+
`app/views/<controller_path>` directory. See the [discovery limits](docs/usage.md#template-discovery)
|
|
65
|
+
for layouts, partials, other handlers, and engine views.
|
|
59
66
|
|
|
60
|
-
##
|
|
67
|
+
## Enable previews for your users
|
|
61
68
|
|
|
62
|
-
|
|
69
|
+
By default, previews are enabled only in development and test. Production,
|
|
70
|
+
staging, and other environments deny preview selection until you configure access.
|
|
63
71
|
|
|
64
72
|
```ruby
|
|
65
73
|
# config/initializers/action_version_preview.rb
|
|
66
74
|
ActionVersionPreview.configure do |config|
|
|
67
|
-
#
|
|
68
|
-
config.param_name = :v
|
|
69
|
-
|
|
70
|
-
# Control who can preview variants (default: dev/test only)
|
|
71
|
-
# In production, you might want admins only:
|
|
75
|
+
config.param_name = :vv # Optional; a string also works.
|
|
72
76
|
config.access_check = ->(controller) {
|
|
73
|
-
Rails.env.development? ||
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
Rails.env.development? || Rails.env.test? ||
|
|
78
|
+
(controller.respond_to?(:current_user, true) &&
|
|
79
|
+
controller.send(:current_user)&.admin?)
|
|
76
80
|
}
|
|
77
81
|
end
|
|
78
82
|
```
|
|
79
83
|
|
|
80
|
-
|
|
84
|
+
Adapt `current_user` and `admin?` to your authentication system. The example also
|
|
85
|
+
works when `current_user` is private. Your user/context must be available when the
|
|
86
|
+
preview callback runs; see [access control and callback order](docs/usage.md#access-control-and-callback-order).
|
|
87
|
+
|
|
88
|
+
The preview parameter applies to one request. Links and redirects elsewhere in
|
|
89
|
+
your app do not inherit it automatically. Ordinary application authorization still
|
|
90
|
+
controls access to data and actions.
|
|
81
91
|
|
|
82
|
-
|
|
92
|
+
## What's new in 0.2.0
|
|
83
93
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
| `can_preview_variants?` | Returns true if current user can access variants |
|
|
90
|
-
| `variant_switcher` | Renders the switcher widget |
|
|
94
|
+
- Fixes `ActionVersionPreview::SwitcherHelper` load-order errors during application
|
|
95
|
+
boot and asset precompilation, including early controller/view loading.
|
|
96
|
+
- Keeps switcher links on the current request path. Query keys such as `host` and
|
|
97
|
+
`protocol` remain query data; POST body fields are not copied into URLs.
|
|
98
|
+
- Adds boot, reload, packaged-gem precompilation, and switcher URL regression tests.
|
|
91
99
|
|
|
92
|
-
|
|
100
|
+
To upgrade from 0.1.0, update your Gemfile constraint if necessary, run
|
|
101
|
+
`bundle update action_version_preview`, and rebuild/restart the application.
|
|
102
|
+
No migration or configuration change is required. Read the [0.2.0 release notes](docs/releases/0.2.0.md).
|
|
93
103
|
|
|
94
|
-
|
|
104
|
+
## Compatibility
|
|
95
105
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
4.
|
|
106
|
+
- Declared requirements: Ruby **3.1+**, Rails **7.0 or later, below 9.0**.
|
|
107
|
+
- Each Rails version may require a newer Ruby; the reviewed Rails 8.1 bundle
|
|
108
|
+
requires Ruby 3.2+.
|
|
109
|
+
- Release validation used Ruby 4.0.5 with Rails 8.1.3.1. CI is configured for Ruby
|
|
110
|
+
3.4.7. A full matrix of the declared versions is not yet in place.
|
|
111
|
+
- Automatic controller integration targets `ActionController::Base`, not API-only
|
|
112
|
+
controllers inheriting directly from `ActionController::API`.
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
bundle install
|
|
118
|
+
bin/rails test
|
|
119
|
+
bin/rubocop
|
|
120
|
+
RAILS_ENV=test bundle exec rake app:zeitwerk:check
|
|
121
|
+
bundle exec rake build
|
|
122
|
+
```
|
|
101
123
|
|
|
102
|
-
|
|
124
|
+
The test suite includes an isolated host that installs the built gem and compiles
|
|
125
|
+
assets in production mode. See the [release procedure](docs/releasing.md) for
|
|
126
|
+
security scans and publication.
|
|
103
127
|
|
|
104
|
-
|
|
105
|
-
|------------------------|--------------------------|
|
|
106
|
-
| Toggle features on/off for users | Access all versions simultaneously |
|
|
107
|
-
| One version "live" at a time | Side-by-side comparison in multiple tabs |
|
|
108
|
-
| Percentage rollouts, A/B testing | Design iteration, feedback collection |
|
|
109
|
-
| Requires database/Redis | Zero dependencies |
|
|
128
|
+
## Background
|
|
110
129
|
|
|
111
|
-
|
|
130
|
+
[Why I built design previews for Rails](https://code.avi.nyc/design-previews-for-ruby-on-rails)
|
|
112
131
|
|
|
113
|
-
|
|
114
|
-
- Ruby 3.1+
|
|
132
|
+
<img width="2146" height="2014" alt="Several Rails UI variants displayed for comparison" src="https://github.com/user-attachments/assets/c39b1305-ad14-4958-be39-d714d53d1990" />
|
|
115
133
|
|
|
116
134
|
## License
|
|
117
135
|
|
|
118
|
-
MIT License
|
|
136
|
+
[MIT License](MIT-LICENSE).
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<div style="position: fixed; bottom: 1rem; right: 1rem; background: #18181b; color: white; padding: 0.75rem; border-radius: 0.5rem; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); z-index: 9999; font-size: 0.875rem; font-family: system-ui, -apple-system, sans-serif;">
|
|
3
3
|
<span style="color: #a1a1aa; margin-right: 0.5rem;">View:</span>
|
|
4
4
|
<%= link_to "Default",
|
|
5
|
-
|
|
5
|
+
variant_preview_path,
|
|
6
6
|
style: "padding: 0.25rem 0.5rem; border-radius: 0.25rem; text-decoration: none; color: white; #{current_variant.nil? ? 'background: #2563eb;' : ''}" %>
|
|
7
7
|
<% detected_variants.each do |variant| %>
|
|
8
8
|
<%= link_to variant.upcase,
|
|
9
|
-
|
|
9
|
+
variant_preview_path(variant),
|
|
10
10
|
style: "padding: 0.25rem 0.5rem; border-radius: 0.25rem; text-decoration: none; color: white; #{current_variant.to_s == variant ? 'background: #2563eb;' : ''}" %>
|
|
11
11
|
<% end %>
|
|
12
12
|
</div>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# ActionVersionPreview 0.2.0
|
|
2
|
+
|
|
3
|
+
ActionVersionPreview 0.2.0 fixes deployment-time helper loading and makes the
|
|
4
|
+
built-in switcher's links safe to use with arbitrary query filters.
|
|
5
|
+
|
|
6
|
+
## Fixed
|
|
7
|
+
|
|
8
|
+
- Fixed `NameError: uninitialized constant ActionVersionPreview::SwitcherHelper`
|
|
9
|
+
when Rails loads controllers or views early during application initialization
|
|
10
|
+
and asset precompilation. The helper is loaded explicitly and remains available
|
|
11
|
+
across development reloads.
|
|
12
|
+
- Switcher links now use the current request path and query data. Parameters such
|
|
13
|
+
as `host`, `protocol`, and `script_name` cannot redirect links to another origin
|
|
14
|
+
or path. Nested filters, pagination, mounted prefixes, and custom preview
|
|
15
|
+
parameter names are preserved.
|
|
16
|
+
- POST body fields, including submitted form fields, are no longer copied into
|
|
17
|
+
switcher URLs.
|
|
18
|
+
|
|
19
|
+
## Documentation and validation
|
|
20
|
+
|
|
21
|
+
- Added a [complete usage guide](https://github.com/aviflombaum/action_version_preview/blob/main/docs/usage.md) covering installation, permissions,
|
|
22
|
+
configuration, discovery, navigation, integrations, and troubleshooting.
|
|
23
|
+
- Added regression tests for early/lazy loading, reloading, installed-gem
|
|
24
|
+
production asset precompilation, and switcher URLs.
|
|
25
|
+
- Refreshed development dependency resolution and CI actions.
|
|
26
|
+
|
|
27
|
+
## Upgrade
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
gem "action_version_preview", "~> 0.2.0"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Run `bundle update action_version_preview` and restart or rebuild your application.
|
|
34
|
+
There are no migrations or required configuration changes. The Default link still
|
|
35
|
+
removes the preview parameter and closes the widget.
|
|
36
|
+
|
|
37
|
+
## Compatibility and scope
|
|
38
|
+
|
|
39
|
+
Declared requirements remain Ruby >= 3.1 and Rails >= 7.0, < 9.0; your Rails version
|
|
40
|
+
may require a newer Ruby. Local release checks ran with Ruby 4.0.5 / Rails 8.1.3.1.
|
|
41
|
+
A full supported-version matrix is not yet in place.
|
|
42
|
+
|
|
43
|
+
This release does not add variant persistence or layout/partial/component
|
|
44
|
+
scanning. Preview parameters must be scalar strings; malformed array/hash input
|
|
45
|
+
handling remains a known limitation. See the [usage guide](https://github.com/aviflombaum/action_version_preview/blob/main/docs/usage.md) for the
|
|
46
|
+
current discovery and access-check behavior.
|
data/docs/releasing.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Releasing ActionVersionPreview
|
|
2
|
+
|
|
3
|
+
Use this procedure to publish a tested gem and then attach a GitHub tag/release
|
|
4
|
+
to the exact source revision used to build it. RubyGems publication is performed
|
|
5
|
+
manually by the maintainer.
|
|
6
|
+
|
|
7
|
+
## Prepare and validate
|
|
8
|
+
|
|
9
|
+
1. Audit the local and remote release branches. Merge all intended changes into
|
|
10
|
+
the release branch, including any new commits from remote `main`.
|
|
11
|
+
2. Update `lib/action_version_preview/version.rb`, the local gem entry in
|
|
12
|
+
`Gemfile.lock`, the changelog, README, usage guide, and release notes.
|
|
13
|
+
3. Run the checks below. Security tools are maintainer tools, not runtime gem
|
|
14
|
+
dependencies. Use current installed versions and an updated advisory database.
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
bundle check
|
|
18
|
+
bin/rails test
|
|
19
|
+
CI=true bin/rails test
|
|
20
|
+
bin/rubocop
|
|
21
|
+
RAILS_ENV=test bundle exec rake app:zeitwerk:check
|
|
22
|
+
bundle-audit check --update
|
|
23
|
+
brakeman --force-scan --no-pager .
|
|
24
|
+
brakeman --no-pager --add-engines-path ../.. --gemfile ../../Gemfile test/dummy
|
|
25
|
+
erb_lint --lint-all --enable-linters erb_safety,parser_errors
|
|
26
|
+
npx --yes markdownlint-cli2@0.23.2 README.md CHANGELOG.md SUGGESTIONS.md docs/usage.md docs/releasing.md docs/releases/0.2.0.md
|
|
27
|
+
git diff --check
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The test suite builds and installs the gem into a temporary directory, checks
|
|
31
|
+
early loading/reloading, renders the real helper, and compiles a production asset
|
|
32
|
+
with `SECRET_KEY_BASE_DUMMY=1`. Brakeman needs the relative `../../Gemfile` argument
|
|
33
|
+
to identify the dummy app's shared dependency resolution correctly.
|
|
34
|
+
|
|
35
|
+
Check Markdown and all local/public documentation links as part of release
|
|
36
|
+
preparation. Avoid treating a remote server's rate limit as a broken link without
|
|
37
|
+
checking it separately.
|
|
38
|
+
|
|
39
|
+
## Merge and build
|
|
40
|
+
|
|
41
|
+
After validation, commit the release changes, merge the release branch into
|
|
42
|
+
`main`, and push `main`. Wait for GitHub CI to pass before publication. Verify that
|
|
43
|
+
each intended release-branch tip is an ancestor of `main`.
|
|
44
|
+
|
|
45
|
+
From a clean `main` checkout:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
git rev-parse HEAD
|
|
49
|
+
bundle exec rake build
|
|
50
|
+
shasum -a 256 pkg/action_version_preview-0.2.0.gem
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Record that commit SHA and the gem's checksum. Inspect the archive for the runtime
|
|
54
|
+
files, helper partial, license, README, changelog, and public documentation. It
|
|
55
|
+
must not contain development credentials, generated assets, tests, or research
|
|
56
|
+
notes. Check that packaged files are readable by other users.
|
|
57
|
+
|
|
58
|
+
## Maintainer publishes to RubyGems
|
|
59
|
+
|
|
60
|
+
Use the already-built artifact:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
gem push pkg/action_version_preview-0.2.0.gem
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Complete RubyGems authentication/MFA as prompted. See the official
|
|
67
|
+
[RubyGems publishing guide](https://guides.rubygems.org/publishing/) for account
|
|
68
|
+
setup. Do not rebuild or change the release commit after this artifact is pushed.
|
|
69
|
+
|
|
70
|
+
## Verify publication, then tag and release on GitHub
|
|
71
|
+
|
|
72
|
+
Confirm RubyGems lists version 0.2.0 and compare its SHA-256 with the local artifact.
|
|
73
|
+
The version API provides the published checksum:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
https://rubygems.org/api/v2/rubygems/action_version_preview/versions/0.2.0.json
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then use the recorded release commit, rather than assuming `main` has not moved:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
git tag -a v0.2.0 RELEASE_COMMIT_SHA -m "ActionVersionPreview 0.2.0"
|
|
83
|
+
git push origin v0.2.0
|
|
84
|
+
gh release create v0.2.0 pkg/action_version_preview-0.2.0.gem \
|
|
85
|
+
--verify-tag \
|
|
86
|
+
--repo aviflombaum/action_version_preview \
|
|
87
|
+
--title "ActionVersionPreview 0.2.0" \
|
|
88
|
+
--notes-file docs/releases/0.2.0.md
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Replace `RELEASE_COMMIT_SHA` with the recorded SHA. Inspect the resulting GitHub
|
|
92
|
+
release and verify its tag targets that commit. If a tag or release already
|
|
93
|
+
exists, inspect it before proceeding; do not move a published tag.
|
|
94
|
+
|
|
95
|
+
`bundle exec rake release` combines tagging, Git pushes, and RubyGems publication.
|
|
96
|
+
Do not use it for this staged workflow: the manual RubyGems push must happen before
|
|
97
|
+
the GitHub tag and release.
|
data/docs/usage.md
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# ActionVersionPreview usage guide
|
|
2
|
+
|
|
3
|
+
This guide describes the public behavior of ActionVersionPreview 0.2.0. The gem
|
|
4
|
+
lets you compare Rails UI designs by selecting a view variant for an individual
|
|
5
|
+
request. It does not assign visitors to experiments or store a selected design in
|
|
6
|
+
a session.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
Add the gem to an application's Gemfile:
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
gem "action_version_preview", "~> 0.2.0"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Run `bundle install` and restart Rails. You do not need to mount routes, run
|
|
17
|
+
migrations, generate configuration, or install JavaScript. Controllers inheriting
|
|
18
|
+
from `ActionController::Base` receive the preview behavior automatically. The
|
|
19
|
+
switcher is optional; variant URLs work without it.
|
|
20
|
+
|
|
21
|
+
The gem declares Ruby >= 3.1 and Rails >= 7.0, < 9.0. Choose a Ruby version supported
|
|
22
|
+
by your Rails release. API-only controllers inheriting directly from
|
|
23
|
+
`ActionController::API` are outside the automatic integration.
|
|
24
|
+
|
|
25
|
+
## Create your first preview
|
|
26
|
+
|
|
27
|
+
Suppose your application already renders `DashboardController#show` at
|
|
28
|
+
`/dashboard`. Keep the default view and add a variant:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
app/views/dashboard/show.html.erb
|
|
32
|
+
app/views/dashboard/show.html+v2.erb
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For example, the variant might contain:
|
|
36
|
+
|
|
37
|
+
```erb
|
|
38
|
+
<h1>A new dashboard design</h1>
|
|
39
|
+
<%= render "summary" %>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Visit `/dashboard?vv=v2` in development. Open `/dashboard` in another tab to compare
|
|
43
|
+
the original. Both requests use your normal controller action, authentication,
|
|
44
|
+
and data; only template selection changes.
|
|
45
|
+
|
|
46
|
+
Add more files such as `show.html+redesign.erb` as needed. The name after `+` is
|
|
47
|
+
case-sensitive. Lowercase letters, digits, and underscores work with the built-in
|
|
48
|
+
discovery, for example `v2`, `redesign`, and `new_layout`.
|
|
49
|
+
|
|
50
|
+
Rails performs the actual [variant template selection](https://guides.rubyonrails.org/layouts_and_rendering.html#the-variants-option).
|
|
51
|
+
If an action has no matching variant template but does have a normal template,
|
|
52
|
+
Rails can fall back to that normal template. Selecting a name does not prove a
|
|
53
|
+
matching template was rendered.
|
|
54
|
+
|
|
55
|
+
## URL behavior
|
|
56
|
+
|
|
57
|
+
These examples use the default parameter name, `vv`, and assume access is allowed:
|
|
58
|
+
|
|
59
|
+
| Request | Behavior |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| `/dashboard` | Leaves normal application variant selection unchanged |
|
|
62
|
+
| `/dashboard?vv=v2` | Sets the request variant to `v2` |
|
|
63
|
+
| `/dashboard?vv=true` | Enables preview mode without changing the request variant |
|
|
64
|
+
| `/dashboard?vv=` | Does not enable preview mode or change the request variant |
|
|
65
|
+
| `/dashboard?vv=unknown` | Requests `unknown`; Rails may render the default template |
|
|
66
|
+
|
|
67
|
+
`true` is a reserved trigger string. It cannot be used to select a template variant
|
|
68
|
+
named `true` through this parameter. `false` is an ordinary variant name, not a
|
|
69
|
+
switch to disable previews. Remove the parameter to leave preview mode.
|
|
70
|
+
|
|
71
|
+
Use scalar strings. In 0.2.0, array/hash forms such as `vv[]=v2` or `vv[name]=v2`
|
|
72
|
+
are unsupported and may raise an exception when access is allowed. Malformed-input
|
|
73
|
+
handling is a separate planned improvement.
|
|
74
|
+
|
|
75
|
+
When access is denied, the gem leaves the request variant unchanged and hides the
|
|
76
|
+
switcher. It does not render an access-denied page or change the response status.
|
|
77
|
+
|
|
78
|
+
## Add the switcher
|
|
79
|
+
|
|
80
|
+
Place this inside an HTML layout, usually near the closing `</body>` tag:
|
|
81
|
+
|
|
82
|
+
```erb
|
|
83
|
+
<%= variant_switcher %>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The widget appears when all three conditions hold:
|
|
87
|
+
|
|
88
|
+
1. The configured preview parameter has a nonblank value.
|
|
89
|
+
2. The access check permits the request.
|
|
90
|
+
3. The current action has discoverable variant templates.
|
|
91
|
+
|
|
92
|
+
It works when `config.action_controller.include_all_helpers = false`. It uses
|
|
93
|
+
ordinary links and inline styles, with no JavaScript dependency.
|
|
94
|
+
|
|
95
|
+
### Switching and returning to Default
|
|
96
|
+
|
|
97
|
+
A variant link selects that name on the current path. Other query data, including
|
|
98
|
+
nested filters and pagination, is preserved. For example:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
/reports?page=2&vv=v2
|
|
102
|
+
/reports?page=2&vv=redesign
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Mounted application prefixes are preserved. Query keys that happen to be named
|
|
106
|
+
`host`, `protocol`, or `script_name` remain query data and cannot override the link
|
|
107
|
+
destination. Request-body fields are not copied into the links.
|
|
108
|
+
|
|
109
|
+
**Default** removes the preview parameter. The resulting page follows your normal
|
|
110
|
+
application rendering and the switcher disappears. Use `?vv=true` to show it again.
|
|
111
|
+
There is no separate persistent preview session or exit button in 0.2.0.
|
|
112
|
+
|
|
113
|
+
The highlighted link reflects `current_variant`, the request's first variant.
|
|
114
|
+
If the requested variant falls back to the normal template, the highlight is not
|
|
115
|
+
a report of the template Rails ultimately rendered.
|
|
116
|
+
|
|
117
|
+
### Styling
|
|
118
|
+
|
|
119
|
+
The supplied widget is fixed at the bottom-right of the viewport and uses inline
|
|
120
|
+
styles. A Content Security Policy that disallows style attributes can prevent
|
|
121
|
+
those styles from applying. There are no theme or position configuration options
|
|
122
|
+
in 0.2.0. You can override the engine partial in your host application at:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
app/views/action_version_preview/_variant_switcher.html.erb
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Keep application-specific overrides under review when upgrading. Custom styles
|
|
129
|
+
and markup are your application's responsibility.
|
|
130
|
+
|
|
131
|
+
## Configuration
|
|
132
|
+
|
|
133
|
+
Configure the gem once at application startup:
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
# config/initializers/action_version_preview.rb
|
|
137
|
+
ActionVersionPreview.configure do |config|
|
|
138
|
+
config.param_name = :design
|
|
139
|
+
end
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
You can then use `/dashboard?design=v2` or `/dashboard?design=true`. The switcher
|
|
143
|
+
uses the configured name for every link. Strings and symbols are both accepted.
|
|
144
|
+
Choose a name that does not conflict with your application's existing parameters.
|
|
145
|
+
Configuration is application-wide, not per-user or per-request.
|
|
146
|
+
|
|
147
|
+
### Access control and callback order
|
|
148
|
+
|
|
149
|
+
The default check allows only `Rails.env.development?` or `Rails.env.test?`.
|
|
150
|
+
Production, staging, and custom environments are disabled by default. To allow
|
|
151
|
+
administrators as well:
|
|
152
|
+
|
|
153
|
+
```ruby
|
|
154
|
+
ActionVersionPreview.configure do |config|
|
|
155
|
+
config.access_check = ->(controller) {
|
|
156
|
+
Rails.env.development? || Rails.env.test? ||
|
|
157
|
+
(controller.respond_to?(:current_user, true) &&
|
|
158
|
+
controller.send(:current_user)&.admin?)
|
|
159
|
+
}
|
|
160
|
+
end
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The callable receives the current controller. A truthy return value allows
|
|
164
|
+
previewing; `false` or `nil` denies it. The example supports a private
|
|
165
|
+
`current_user` method, but you must adapt the method and permission check to your
|
|
166
|
+
application. Avoid performing side effects: the check can run during variant
|
|
167
|
+
selection and again while rendering helpers.
|
|
168
|
+
|
|
169
|
+
The gem registers its callback on `ActionController::Base`. A user lookup that
|
|
170
|
+
happens only in a later host `before_action` may not be ready when selection runs.
|
|
171
|
+
Prefer a current-user lookup that can resolve its own state when called. If your
|
|
172
|
+
authentication requires a callback first, order that callback before preview
|
|
173
|
+
selection using Rails' callback ordering facilities, and test the request in your
|
|
174
|
+
host application. The gem has no callback-order configuration setting in 0.2.0.
|
|
175
|
+
|
|
176
|
+
Keep your normal authorization checks for data and actions. The preview access
|
|
177
|
+
check governs selection through this gem; it is not a replacement for host
|
|
178
|
+
application authorization. Excluding a name from the widget is not an access rule.
|
|
179
|
+
|
|
180
|
+
## Template discovery
|
|
181
|
+
|
|
182
|
+
The built-in switcher scans:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
app/views/<controller_path>/<action_name>.html+<variant>.erb
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
For example, `Admin::ReportsController#index` is scanned under
|
|
189
|
+
`app/views/admin/reports/index.html+*.erb`. Names are returned in sorted order and
|
|
190
|
+
cached for that request.
|
|
191
|
+
|
|
192
|
+
The following names are omitted from the widget: `mobile`, `tablet`, `phone`, and
|
|
193
|
+
`desktop`. These are the gem's device-name convention, not names reserved by Rails.
|
|
194
|
+
An authorized `?vv=mobile` request can still select a mobile template.
|
|
195
|
+
|
|
196
|
+
In 0.2.0, automatic discovery does not enumerate:
|
|
197
|
+
|
|
198
|
+
- Layout-only or partial-only variants.
|
|
199
|
+
- Templates in engine-owned or custom/prepended view directories.
|
|
200
|
+
- Locale-qualified filenames such as `show.en.html+v2.erb`.
|
|
201
|
+
- Handlers other than ERB, such as Haml or Slim.
|
|
202
|
+
- Variant names containing hyphens or other characters outside letters, digits,
|
|
203
|
+
and underscores.
|
|
204
|
+
- A different template explicitly rendered by the action.
|
|
205
|
+
|
|
206
|
+
Rails may still render these variants when selected directly by URL. Discovery
|
|
207
|
+
controls the widget's choices; it is not an allowlist for request variants.
|
|
208
|
+
|
|
209
|
+
## Layouts, partials, and components
|
|
210
|
+
|
|
211
|
+
Native Rails rendering can apply the selected variant to layouts and partials.
|
|
212
|
+
For example, a request selecting `v2` can use these files where your normal render
|
|
213
|
+
calls refer to them:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
app/views/layouts/application.html+v2.erb
|
|
217
|
+
app/views/dashboard/_summary.html+v2.erb
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The switcher does not discover a `v2` choice from those files alone. Use the URL
|
|
221
|
+
directly, or also provide an action variant when you want automatic discovery.
|
|
222
|
+
|
|
223
|
+
ViewComponent and other rendering libraries have their own variant behavior.
|
|
224
|
+
ActionVersionPreview sets `request.variant`; it does not scan component directories
|
|
225
|
+
or provide a dedicated component integration. Test component rendering in your
|
|
226
|
+
host application.
|
|
227
|
+
|
|
228
|
+
Mailers and background jobs do not automatically inherit the preview URL or its
|
|
229
|
+
variant. Pass and select the desired variant in those systems separately.
|
|
230
|
+
|
|
231
|
+
## Navigation and existing application variants
|
|
232
|
+
|
|
233
|
+
Selection lasts for the current request. Normal links, redirects, form submissions,
|
|
234
|
+
and Turbo requests only keep preview mode if their destination includes the
|
|
235
|
+
configured parameter. The gem does not modify `default_url_options`, cookies,
|
|
236
|
+
sessions, localStorage, or Turbo behavior.
|
|
237
|
+
|
|
238
|
+
For a link where you explicitly want to carry the current variant forward, add it
|
|
239
|
+
with your application's route helper:
|
|
240
|
+
|
|
241
|
+
```erb
|
|
242
|
+
<%= link_to "Reports", reports_path(design: current_variant) %>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
This example assumes `config.param_name = :design`. If you want to open the
|
|
246
|
+
switcher without selecting a variant, pass `design: "true"` instead. Consider
|
|
247
|
+
whether the destination action actually has the same variants.
|
|
248
|
+
|
|
249
|
+
A nonblank preview name replaces the request's variant selection. Missing/blank
|
|
250
|
+
parameters, denied access, and the `true` trigger leave an existing application
|
|
251
|
+
variant unchanged. Other controller callbacks can still change it later.
|
|
252
|
+
|
|
253
|
+
## Helper reference
|
|
254
|
+
|
|
255
|
+
| Method | Available in | Meaning |
|
|
256
|
+
| --- | --- | --- |
|
|
257
|
+
| `variant_switcher` | Views | Renders the built-in widget, or no visible widget when its conditions are not met |
|
|
258
|
+
| `current_variant` | Controller and views | First request variant as a symbol, or `nil` |
|
|
259
|
+
| `detected_variants` | Controller and views | Sorted array of discovered names as strings |
|
|
260
|
+
| `variant_preview_active?` | Controller and views | Truthy when the parameter is nonblank and access is allowed |
|
|
261
|
+
| `can_preview_variants?` | Controller and views | Result of the configured access check |
|
|
262
|
+
|
|
263
|
+
The controller methods are private and exposed as view helpers. Use the widget
|
|
264
|
+
or normal Rails route helpers for your own links.
|
|
265
|
+
|
|
266
|
+
## Troubleshooting
|
|
267
|
+
|
|
268
|
+
| Symptom | What to check |
|
|
269
|
+
| --- | --- |
|
|
270
|
+
| No switcher | Include the helper, provide `vv=true`, allow access, and check that action ERB variants are discoverable |
|
|
271
|
+
| Works locally but not in staging | Configure `access_check`; staging is denied by default |
|
|
272
|
+
| Requested variant renders the original view | Check spelling, case, filename, access, callback order, and Rails fallback behavior |
|
|
273
|
+
| Default makes the switcher disappear | Expected in 0.2.0; Default removes the parameter |
|
|
274
|
+
| Variant disappears after navigation | Include the preview parameter in that destination if you want to retain it |
|
|
275
|
+
| Device variant changes unexpectedly | A concrete preview name replaces the request variant; check other callbacks too |
|
|
276
|
+
| Widget is unstyled | Check the host's Content Security Policy and any partial override |
|
|
277
|
+
| 0.1.0 raises `SwitcherHelper` during asset precompilation | Upgrade to 0.2.0, update the lockfile, and rebuild the deployment image |
|
|
278
|
+
|
|
279
|
+
## Upgrading from 0.1.0
|
|
280
|
+
|
|
281
|
+
Update your version constraint if it pins 0.1.0, then run:
|
|
282
|
+
|
|
283
|
+
```sh
|
|
284
|
+
bundle update action_version_preview
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Restart Rails or rebuild your deployment image so it installs the new lockfile
|
|
288
|
+
resolution. No migration, route mount, or new initializer is required.
|
|
289
|
+
|
|
290
|
+
0.2.0 fixes helper loading during boot and asset precompilation, and changes the
|
|
291
|
+
built-in switcher to derive URLs from the current path and query data. POST body
|
|
292
|
+
fields no longer appear in its links. The configuration names, default access
|
|
293
|
+
policy, discovery scope, and Default behavior remain the same.
|
|
294
|
+
|
|
295
|
+
See the [changelog](../CHANGELOG.md) and [release notes](releases/0.2.0.md).
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "action_version_preview/controller_methods"
|
|
2
|
+
require "action_version_preview/switcher_helper"
|
|
2
3
|
|
|
3
4
|
module ActionVersionPreview
|
|
4
5
|
class Engine < ::Rails::Engine
|
|
@@ -7,7 +8,12 @@ module ActionVersionPreview
|
|
|
7
8
|
initializer "action_version_preview.controller_methods" do
|
|
8
9
|
ActiveSupport.on_load(:action_controller_base) do
|
|
9
10
|
include ActionVersionPreview::ControllerMethods
|
|
10
|
-
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
initializer "action_version_preview.helpers", after: :load_config_initializers do
|
|
15
|
+
ActiveSupport.on_load(:action_view) do
|
|
16
|
+
include ActionVersionPreview::SwitcherHelper
|
|
11
17
|
end
|
|
12
18
|
end
|
|
13
19
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module ActionVersionPreview
|
|
2
|
+
# Required by the engine: load hooks may run before Rails sets up autoloading.
|
|
3
|
+
module SwitcherHelper
|
|
4
|
+
def variant_switcher
|
|
5
|
+
render partial: "action_version_preview/variant_switcher"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def variant_preview_path(variant = nil)
|
|
11
|
+
param_name = ActionVersionPreview.param_name.to_s
|
|
12
|
+
query = request.query_parameters.except(param_name)
|
|
13
|
+
query[param_name] = variant if variant
|
|
14
|
+
|
|
15
|
+
query.empty? ? request.path : "#{request.path}?#{query.to_query}"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: action_version_preview
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Avi Flombaum
|
|
@@ -38,24 +38,29 @@ executables: []
|
|
|
38
38
|
extensions: []
|
|
39
39
|
extra_rdoc_files: []
|
|
40
40
|
files:
|
|
41
|
+
- CHANGELOG.md
|
|
41
42
|
- MIT-LICENSE
|
|
42
43
|
- README.md
|
|
43
44
|
- Rakefile
|
|
44
|
-
- app/helpers/action_version_preview/switcher_helper.rb
|
|
45
45
|
- app/views/action_version_preview/_variant_switcher.html.erb
|
|
46
46
|
- config/routes.rb
|
|
47
|
+
- docs/releases/0.2.0.md
|
|
48
|
+
- docs/releasing.md
|
|
49
|
+
- docs/usage.md
|
|
47
50
|
- lib/action_version_preview.rb
|
|
48
51
|
- lib/action_version_preview/controller_methods.rb
|
|
49
52
|
- lib/action_version_preview/engine.rb
|
|
53
|
+
- lib/action_version_preview/switcher_helper.rb
|
|
50
54
|
- lib/action_version_preview/version.rb
|
|
51
55
|
- lib/tasks/action_version_preview_tasks.rake
|
|
52
56
|
homepage: https://github.com/aviflombaum/action_version_preview
|
|
53
57
|
licenses:
|
|
54
58
|
- MIT
|
|
55
59
|
metadata:
|
|
56
|
-
homepage_uri: https://github.com/aviflombaum/action_version_preview
|
|
57
60
|
source_code_uri: https://github.com/aviflombaum/action_version_preview
|
|
58
61
|
changelog_uri: https://github.com/aviflombaum/action_version_preview/blob/main/CHANGELOG.md
|
|
62
|
+
documentation_uri: https://github.com/aviflombaum/action_version_preview/blob/main/docs/usage.md
|
|
63
|
+
bug_tracker_uri: https://github.com/aviflombaum/action_version_preview/issues
|
|
59
64
|
rdoc_options: []
|
|
60
65
|
require_paths:
|
|
61
66
|
- lib
|
|
@@ -70,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
70
75
|
- !ruby/object:Gem::Version
|
|
71
76
|
version: '0'
|
|
72
77
|
requirements: []
|
|
73
|
-
rubygems_version:
|
|
78
|
+
rubygems_version: 4.0.14
|
|
74
79
|
specification_version: 4
|
|
75
80
|
summary: Preview multiple view variants side-by-side using Rails' built-in view variants.
|
|
76
81
|
test_files: []
|