rails_admin_next 1.2.0 → 1.2.1
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/README.md +8 -4
- data/app/controllers/rails_admin_next/main_controller.rb +11 -0
- data/docs/UPGRADING.md +34 -2
- data/docs/security.md +5 -0
- data/docs/upstream-parity.md +47 -3
- data/lib/rails_admin_next/config/actions/export.rb +2 -1
- data/lib/rails_admin_next/config/actions/index.rb +2 -2
- data/lib/rails_admin_next/config/actions/show.rb +1 -1
- data/lib/rails_admin_next/extensions/pundit/authorization_adapter.rb +4 -2
- data/lib/rails_admin_next/support/serialization_schema.rb +74 -0
- data/lib/rails_admin_next/version.rb +1 -1
- data/lib/rails_admin_next.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 957743cf70d6fa24bb0cb1eaf74ca15b4a3b2996e0dca4f5dcee2d6428985d6b
|
|
4
|
+
data.tar.gz: a205770a7170c2b1ce7e04a85cd6422f6cda1d150da237df81795387af8cc18d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad848e8080f75c1e3d6b12c180dcb745bb4a3caea7791ee08d4fec1d97567836effacf01ea340a764b0febb4a52c345e793b3d1708d7496e9d1c2e3f6a167f6d
|
|
7
|
+
data.tar.gz: 37ec4a516104eb2ecc4d8924c758ad862b8fa091f32a0d460b0dfda2f8bc566a233fa61ea81d6cdbbfe49695b1d71eb0aed55f75c281001e9d86a73821fbe8a8
|
data/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://github.com/6temes/rails_admin_next/actions/workflows/test.yml)
|
|
10
10
|
[](LICENSE.md)
|
|
11
|
-
[](https://www.ruby-lang.org)
|
|
12
12
|
[](https://rubyonrails.org)
|
|
13
13
|
|
|
14
14
|
[Why RailsAdminNext?](#why-railsadminnext) ◆ [Quick Start](#quick-start) ◆ [Installation](#installation) ◆ [Architecture](#architecture) ◆ [Security](#security) ◆ [Upgrading](#upgrading-from-railsadmin)
|
|
@@ -32,7 +32,7 @@ multi-bundler, jQuery-era machinery. RailsAdminNext keeps the admin and drops th
|
|
|
32
32
|
- **⚡ Zero build step** — browser-native ESM over **importmap + Propshaft**; no Webpack/Vite/Sprockets, no `yarn build`, no generated pins.
|
|
33
33
|
- **🧩 Turbo + Stimulus** — the jQuery / jQuery-UI / Bootstrap-JS / `@rails/ujs` stack is gone, replaced by engine-shipped Stimulus controllers; styling is hand-maintained vanilla CSS.
|
|
34
34
|
- **🔒 Hardened & CDN-free** — a documented CSRF / clickjacking / mass-assignment / CSP posture ([SECURITY.md](SECURITY.md)) and **zero external CDN**, default or opt-in — every asset is self-hosted off a gem.
|
|
35
|
-
- **🎯 One modern target** — Ruby ≥ 4.0.
|
|
35
|
+
- **🎯 One modern target** — Ruby ≥ 4.0.9, Rails ~> 8.1, ActiveRecord only, latest Chrome + Safari. No Mongoid, no multi-bundler / multi-Rails matrix, no legacy-browser CSS.
|
|
36
36
|
- **↩️ Familiar** — `RailsAdminNext.config`, per-model `rails_admin_next do … end` blocks, and CanCanCan / Pundit authorization all work as before; upgrading from RailsAdmin is a mechanical rename.
|
|
37
37
|
|
|
38
38
|
## Quick Start
|
|
@@ -50,17 +50,21 @@ bin/rails s # then open http://localhost:3000/admin
|
|
|
50
50
|
|
|
51
51
|
That's the whole setup — no `yarn add`, no asset build, no generated pins. The engine ships its own importmap and CSS.
|
|
52
52
|
|
|
53
|
-
> **Prerequisites:** Ruby ≥ 4.0.
|
|
53
|
+
> **Prerequisites:** Ruby ≥ 4.0.9 · Rails ~> 8.1 · ActiveRecord · a [Propshaft][propshaft] + [importmap-rails][importmap] host (both are pulled in as dependencies). See [Installation](#installation) for the full walkthrough.
|
|
54
54
|
|
|
55
55
|
## Requirements
|
|
56
56
|
|
|
57
|
-
- Ruby >= 4.0.
|
|
57
|
+
- Ruby >= 4.0.9
|
|
58
58
|
- Rails ~> 8.1
|
|
59
59
|
- ActiveRecord (Mongoid is not supported)
|
|
60
60
|
- [Propshaft][propshaft] and [importmap-rails][importmap] (both are pulled in as
|
|
61
61
|
dependencies; RailsAdminNext serves its frontend over them, with no bundler or build step)
|
|
62
62
|
- Latest stable Chrome or Safari for the admin's users (see [Browser support](#browser-support))
|
|
63
63
|
|
|
64
|
+
RailsAdminNext expects **evergreen** hosts. The Ruby floor follows the latest stable Ruby
|
|
65
|
+
patch release, and a release can raise it without a major version bump. Keep your app on
|
|
66
|
+
current Ruby and Rails to keep receiving updates.
|
|
67
|
+
|
|
64
68
|
[propshaft]: https://github.com/rails/propshaft
|
|
65
69
|
[importmap]: https://github.com/rails/importmap-rails
|
|
66
70
|
|
|
@@ -108,6 +108,17 @@ module RailsAdminNext
|
|
|
108
108
|
model_config.send(action).with(controller: self, view: view_context, object: @object).visible_fields
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
+
# Memoized, as export renders through index, which switches @action
|
|
112
|
+
def serialization_schema
|
|
113
|
+
@serialization_schema ||= begin
|
|
114
|
+
section = %i[export show].include?(@action.key) ? @model_config.send(@action.key) : @model_config.list
|
|
115
|
+
SerializationSchema.new(
|
|
116
|
+
section.with(controller: self, view: view_context, object: @object || @abstract_model.model.new),
|
|
117
|
+
include_associations: @action.key == :export
|
|
118
|
+
)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
111
122
|
def sanitize_params_for!(action, model_config = @model_config, target_params = params[@abstract_model.param_key], nested_in = nil)
|
|
112
123
|
return unless target_params.present?
|
|
113
124
|
|
data/docs/UPGRADING.md
CHANGED
|
@@ -416,8 +416,40 @@ curl -H 'Accept: application/json' https://example.com/admin/player/1
|
|
|
416
416
|
curl https://example.com/admin/player/1.json
|
|
417
417
|
```
|
|
418
418
|
|
|
419
|
-
|
|
420
|
-
|
|
419
|
+
The JSON branch renders only the fields the show view displays (see below).
|
|
420
|
+
|
|
421
|
+
## JSON and XML serialize only configured fields
|
|
422
|
+
|
|
423
|
+
The index action's `.json`/`.xml`, the show action's `.json`, and the export action's JSON/XML
|
|
424
|
+
used to serialize every attribute of the record, and export passed the submitted `schema` straight
|
|
425
|
+
to `to_json`/`to_xml` — so any `methods` or `include` name in it was called on every record.
|
|
426
|
+
|
|
427
|
+
They now serialize only what the matching section shows: `list` for index, `show` for show,
|
|
428
|
+
`export` for export. Index and show also keep the foreign keys of the `belongs_to` associations
|
|
429
|
+
they display. A submitted export `schema` is intersected with the export fields, and `except` is
|
|
430
|
+
ignored.
|
|
431
|
+
|
|
432
|
+
If a client relied on a column the section doesn't show, add that field to the section.
|
|
433
|
+
|
|
434
|
+
## Pundit: a model with no policy Scope lists nothing
|
|
435
|
+
|
|
436
|
+
A model whose policy defines no `Scope` used to list every record. It now lists none: the
|
|
437
|
+
list, export, bulk delete and dashboard count all return an empty set. Bulk delete deletes
|
|
438
|
+
whatever the scope returns, with no per-record check, so "no Scope" can't mean "everything".
|
|
439
|
+
|
|
440
|
+
Define a `Scope` for each model the admin exposes:
|
|
441
|
+
|
|
442
|
+
```ruby
|
|
443
|
+
class PlayerPolicy < ApplicationPolicy
|
|
444
|
+
class Scope < ApplicationPolicy::Scope
|
|
445
|
+
def resolve
|
|
446
|
+
scope.all
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
CanCanCan hosts are unaffected.
|
|
421
453
|
## Removed: options deprecated before RailsAdmin 3.0
|
|
422
454
|
|
|
423
455
|
These six were deprecated upstream between 2019-07 and 2022-01 and had no effect for
|
data/docs/security.md
CHANGED
|
@@ -11,6 +11,11 @@ destructive-action controls itself; a few things are left for the host to opt in
|
|
|
11
11
|
- **Clickjacking.** Every admin response carries `X-Frame-Options: SAMEORIGIN`.
|
|
12
12
|
- **Export.** The CSV/JSON/XML data stream requires a non-GET, CSRF-protected request; `GET` only
|
|
13
13
|
renders the export form, so the table can't be exfiltrated via a crafted link.
|
|
14
|
+
- **Serialization.** JSON and XML output is limited to the fields the section shows (`list`,
|
|
15
|
+
`show` or `export`). A submitted export `schema` is intersected with the export fields, so it
|
|
16
|
+
can't name a hidden column, an association the export doesn't show, or a method to call.
|
|
17
|
+
- **Pundit scopes fail closed.** A model whose policy has no `Scope` lists no records, rather
|
|
18
|
+
than all of them.
|
|
14
19
|
- **Destructive actions.** `delete` and `bulk_delete` render a confirmation page and additionally
|
|
15
20
|
carry `data-turbo-confirm` on the destructive submit (Turbo's confirmation, not `@rails/ujs`).
|
|
16
21
|
- **Mass assignment.** Submitted attributes are sliced to the model config's `visible_fields`
|
data/docs/upstream-parity.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Upstream parity
|
|
2
2
|
|
|
3
|
-
Assessed through upstream `
|
|
3
|
+
Assessed through upstream `2dfd05f1` (2026-10-30). Fork point: `d8e0809e` (2025-09-14).
|
|
4
4
|
|
|
5
|
-
Divergence from the fork point:
|
|
5
|
+
Divergence from the fork point: 792 files, +21,203 / −73,569 lines.
|
|
6
6
|
|
|
7
7
|
## How this fork tracks upstream
|
|
8
8
|
|
|
@@ -18,6 +18,50 @@ Commits are listed newest first, as `git log` reports them.
|
|
|
18
18
|
|
|
19
19
|
| upstream | subject | verdict | ours |
|
|
20
20
|
|---|---|---|---|
|
|
21
|
+
| `2dfd05f1` | Test ferrum 0.19.2 with flatten mode on JRuby | n/a — JRuby leg over Appraisal gemfiles; neither exists here | — |
|
|
22
|
+
| `bf8f645c` | Replace nested_form with RailsAdmin's own nested form implementation | partly relevant — per-controller `<template>` and button controls already here; unsaved-row remove, self-reference recursion, placeholder collision and the dummy belongs_to still apply | [#73](https://github.com/6temes/rails_admin_next/issues/73) |
|
|
23
|
+
| `6e27f4d3` | Let the adapter narrow a scope, instead of merging it here | n/a — one AR adapter; the controller's merge is already its vocabulary, no behaviour change | — |
|
|
24
|
+
| `20f8f29a` | Narrow a listing by the scope it selects before it is paginated | partly adapted — pre-pagination done; export and bulk delete ignore the tab, and remote pickers get it | [#60](https://github.com/6temes/rails_admin_next/issues/60) |
|
|
25
|
+
| `7e5a7d67` | Keep the browser driver off a version the suite hangs on | partly relevant — the pin is JRuby-only (n/a); the missing job timeout matches this fork's apt-step hangs | [#74](https://github.com/6temes/rails_admin_next/issues/74) |
|
|
26
|
+
| `1e0bd4fd` | Say what an upload needs from an embedded document | n/a — embedded documents are Mongoid; no upload docs here | — |
|
|
27
|
+
| `6651f64d` | Say which records associated_collection_scope governs | n/a — the option isn't documented here, so nothing to correct | — |
|
|
28
|
+
| `51d7321a` | Look up a registered visible block by the option's own name | relevant — measured: redeclaring a field drops its visible block; `admin?` raises NameError | [#64](https://github.com/6temes/rails_admin_next/issues/64) |
|
|
29
|
+
| `e67edd00` | Escape a field name before it stands in for a selector | n/a — the filter container is found by `getElementById`; other selectors use `CSS.escape` or quoted values | — |
|
|
30
|
+
| `11cd3e53` | Leave out a column the queried term could never fit | relevant — measured: PG raises NumericValueOutOfRange for a 10-digit term on int4 | [#56](https://github.com/6temes/rails_admin_next/issues/56) |
|
|
31
|
+
| `2d9f951f` | Have no enumeration rather than crash when there's no _enum method | relevant — measured: enum without a source crashes filter_operators; native PG enums hit it unconfigured | [#58](https://github.com/6temes/rails_admin_next/issues/58) |
|
|
32
|
+
| `c4b64ede` | Document sort_by's array and hash forms | n/a — sort_by isn't documented here; the forms are supported | — |
|
|
33
|
+
| `cbed4c42` | Fall back to the guessed encoding when a CSV export leaves it blank | n/a — measured: blank does what the form says here (leaves encoding untouched); the fallback is a no-op on the connection encoding | — |
|
|
34
|
+
| `8748af05` | Bind the controller and view before reading a model's list scopes | relevant — measured: both reads are unbound | [#62](https://github.com/6temes/rails_admin_next/issues/62) |
|
|
35
|
+
| `3e26f685` | Keep a serialized value's wrapper class out of the text an admin edits | relevant — measured: every AR `store` round-trip raises DisallowedClass | [#63](https://github.com/6temes/rails_admin_next/issues/63) |
|
|
36
|
+
| `8b7f686b` | Let a requested sort win over has_paper_trail's own version order | relevant — `order` appended after paper_trail's association order | [#69](https://github.com/6temes/rails_admin_next/issues/69) |
|
|
37
|
+
| `e9e13ebf` | Recognize a native timestamptz column as a timestamp field | relevant — measured: Rails 8.1.4 PG reports `:timestamptz`, which the registry rejects | [#55](https://github.com/6temes/rails_admin_next/issues/55) |
|
|
38
|
+
| `0c6b8e9d` | Version 4.0.0.beta2 | n/a — upstream release chore | — |
|
|
39
|
+
| `d96845da` | [Security] Fail closed when Pundit policy scope is undefined | relevant — the adapter rescued a missing Scope with `model.all`; fixed with plain AR `none` (no repository indirection needed) | [#77](https://github.com/6temes/rails_admin_next/pull/77) |
|
|
40
|
+
| `a6cf6bb0` | [Security] Limit JSON/XML serialization to the configured fields | partly adapted — the GET gate was already here; methods/hidden columns via `schema` and full-row index/show output fixed; the default never calls virtual fields | [#77](https://github.com/6temes/rails_admin_next/pull/77) |
|
|
41
|
+
| `fca081f2` | Version 4.0.0.beta | n/a — upstream release chore | — |
|
|
42
|
+
| `00ddcd06` | Drop the dummy app's tooling for asset modes that no longer exist | n/a — none of those files are tracked here | — |
|
|
43
|
+
| `d593bcaf` | Serve the dummy app's own JavaScript through every asset pipeline | n/a — one pipeline; the host entry is an ESM module importing Turbo | — |
|
|
44
|
+
| `72bdd18d` | Let any callable serve as asset_source | n/a — `asset_source=` is a deprecated no-op here | — |
|
|
45
|
+
| `812109cf` | Put the :external stylesheet where a JS build will not eat it | n/a — the installer writes only an initializer | — |
|
|
46
|
+
| `9ed33f69` | Keep the dummy app's test hooks out of development | n/a — the only test hook here is invisible | — |
|
|
47
|
+
| `7cc5e292` | Keep the dummy app's cookies readable, and cover CSRF both ways | partly relevant — the json pin is moot on Rails 8.1.4; the CSRF acceptance coverage gap applies | [#76](https://github.com/6temes/rails_admin_next/issues/76) |
|
|
48
|
+
| `fd0bf316` | Drop the docs left behind by the asset rework | n/a — docs here mention those pipelines only as removed | — |
|
|
49
|
+
| `3af6946c` | Flush rich-text editors before the modal submits | n/a — Trix writes its input on every change; no submit-time editor remains | — |
|
|
50
|
+
| `a16b425f` | Test carrierwave 3.x and 4.x within the existing CI matrix | n/a — CarrierWave removed | — |
|
|
51
|
+
| `8302cc29` | Lower a search term with String#downcase | adapted — already `downcase`; no `mb_chars` left | — |
|
|
52
|
+
| `63ebb9ac` | Ask whether an enum is null, not whether it equals '' | relevant — measured: PG rejects `= ''` on an integer enum | [#57](https://github.com/6temes/rails_admin_next/issues/57) |
|
|
53
|
+
| `749cbe75` | Let associated_collection_scope decide the order it asks for | relevant — scope applied before the reorder; the swap must follow #60 | [#61](https://github.com/6temes/rails_admin_next/issues/61) |
|
|
54
|
+
| `47da8e99` | Refresh SimpleMDE editors when their tab is shown | n/a — no layout-measuring editor ships here | — |
|
|
55
|
+
| `4443ab35` | Ship a prebuilt asset bundle; collapse config.asset_source | n/a — already a single zero-build importmap + Propshaft path | — |
|
|
56
|
+
| `478484fb` | CI: install ImageMagick against a refreshed package list | n/a — the step here already runs `apt-get update` and `-y`; the failure here is a stall (#74) | — |
|
|
57
|
+
| `a6f4c5ad` | Fix the viewport meta tag's name attribute | relevant — the identical malformed tag is in `_head.html.erb` | [#72](https://github.com/6temes/rails_admin_next/issues/72) |
|
|
58
|
+
| `88e6df4d` | Strip a leading :: when deriving a model's config registry key | relevant — measured: config ignored and the model listed twice | [#70](https://github.com/6temes/rails_admin_next/issues/70) |
|
|
59
|
+
| `a5607f24` | Use label_plural in bulk delete flash messages | relevant — measured: translated plural ignored | [#71](https://github.com/6temes/rails_admin_next/issues/71) |
|
|
60
|
+
| `7b60193b` | Let the page catch up before reading the database | adapted — fixed independently here | [#23](https://github.com/6temes/rails_admin_next/pull/23) |
|
|
61
|
+
| `ef3e3f57` | Keep one dead browser from failing the examples after it | partly relevant — the driver restore applies; the startup-timeout half is deferred (never seen in ~60 runs) | [#75](https://github.com/6temes/rails_admin_next/issues/75) |
|
|
62
|
+
| `cc293dea` | Wait for the autocomplete menu itself, not for one of its entries | n/a — waits here use counts or text the stale menu can't satisfy; the widget renders once per query (as `77e5d0bc`) | — |
|
|
63
|
+
| `d3cfba1d` | Render the list for a filter URL written by hand | relevant — measured: seven malformed shapes 500, one specific to this fork | [#65](https://github.com/6temes/rails_admin_next/issues/65) |
|
|
64
|
+
| `ede4e77b` | Split the adapter layer into a Reflection and a Repository | declined — multi-ORM refactor, one adapter here; four embedded fixes filed separately | [#59](https://github.com/6temes/rails_admin_next/issues/59), [#66](https://github.com/6temes/rails_admin_next/issues/66), [#67](https://github.com/6temes/rails_admin_next/issues/67), [#68](https://github.com/6temes/rails_admin_next/issues/68) |
|
|
21
65
|
| `897ffc13` | Fix _discard leaking into SQL for multi-select enum filters | adapted — server half only; the client half was already stronger here (disabled options), so upstream's JS was deliberately not ported | [#36](https://github.com/6temes/rails_admin_next/pull/36) |
|
|
22
66
|
| `11f214f6` | Remove config options deprecated before RailsAdmin 3.0 | adapted — the deprecator half already shipped; this removed the six options | [#40](https://github.com/6temes/rails_admin_next/pull/40) |
|
|
23
67
|
| `cbea80b1` | Match GET in http_methods case-insensitively | adapted — `Actions::Base#linkable?` | [#38](https://github.com/6temes/rails_admin_next/pull/38) |
|
|
@@ -31,7 +75,7 @@ Commits are listed newest first, as `git log` reports them.
|
|
|
31
75
|
| `2eed28e1` | Fully specify all ESM imports with an extension | n/a — measured: every relative import in `src/` already carries `.js`; browser-native ESM requires it | — |
|
|
32
76
|
| `e8dec57a` | Upgrade @hotwired/turbo-rails to resolve security warning | n/a — turbo comes from the `turbo-rails` gem (2.0.23), which Dependabot reads | — |
|
|
33
77
|
| `07b2066a` | Replace `asset-url` with `url` in Sass files | n/a — no Sass; one hand-owned CSS file | — |
|
|
34
|
-
| `a0946615` | Drop support for Rails 6.x and Ruby 2.5/2.6 | n/a — this fork is Rails ~> 8.1 / Ruby >= 4.0.
|
|
78
|
+
| `a0946615` | Drop support for Rails 6.x and Ruby 2.5/2.6 | n/a — this fork is Rails ~> 8.1 / Ruby >= 4.0.9 only | — |
|
|
35
79
|
| `0543cb3f` | Revert npm package.json version ahead of actual publish | n/a — no npm package | — |
|
|
36
80
|
| `cf7b112e` | Run Prettier on migrated docs | n/a — upstream's vendored wiki | — |
|
|
37
81
|
| `1c2b92a3` | Rewrite wiki cross-links to relative docs/ links | n/a — upstream's vendored wiki | — |
|
|
@@ -22,7 +22,8 @@ module RailsAdminNext
|
|
|
22
22
|
# table with attacker-chosen columns; the export form posts back to this same action.
|
|
23
23
|
if format && !request.get?
|
|
24
24
|
request.format = format
|
|
25
|
-
|
|
25
|
+
serialization_schema # built while @action is still export
|
|
26
|
+
@schema = serialization_schema.sanitize(params[:schema].slice(:include, :methods, :only).permit!.to_h) if params[:schema]
|
|
26
27
|
@objects = list_entries(@model_config, :export)
|
|
27
28
|
index
|
|
28
29
|
else
|
|
@@ -66,7 +66,7 @@ module RailsAdminNext
|
|
|
66
66
|
@objects.collect { |object| {id: object.id.to_s, label: object.send(@model_config.object_label_method).to_s} }
|
|
67
67
|
end
|
|
68
68
|
else
|
|
69
|
-
@objects.to_json(@schema)
|
|
69
|
+
@objects.to_json(@schema || serialization_schema.default)
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
if params[:send_data]
|
|
@@ -77,7 +77,7 @@ module RailsAdminNext
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
format.xml do
|
|
80
|
-
output = @objects.map { |object| object.serializable_hash(@schema ||
|
|
80
|
+
output = @objects.map { |object| object.serializable_hash(@schema || serialization_schema.default) }.to_xml(root: @abstract_model.model.model_name.plural)
|
|
81
81
|
if params[:send_data]
|
|
82
82
|
send_data output, filename: "#{params[:model_name]}_#{DateTime.now.strftime("%Y-%m-%d_%Hh%Mm%S")}.xml"
|
|
83
83
|
else
|
|
@@ -24,7 +24,7 @@ module RailsAdminNext
|
|
|
24
24
|
# registered type, so Rails falls back to whichever is declared first.
|
|
25
25
|
respond_to do |format|
|
|
26
26
|
format.html { render @action.template_name }
|
|
27
|
-
format.json { render json: @object }
|
|
27
|
+
format.json { render json: @object.to_json(serialization_schema.default) }
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -40,11 +40,13 @@ module RailsAdminNext
|
|
|
40
40
|
|
|
41
41
|
# This is called when needing to scope a database query. It is called within the list
|
|
42
42
|
# and bulk_delete/destroy actions and should return a scope which limits the records
|
|
43
|
-
# to those which the user can perform the given action on.
|
|
43
|
+
# to those which the user can perform the given action on. A model with no policy
|
|
44
|
+
# Scope gets no records: bulk_delete deletes whatever this returns without a
|
|
45
|
+
# per-record check, so a forgotten Scope must not mean "everything".
|
|
44
46
|
def query(_action, abstract_model)
|
|
45
47
|
@controller.send(:policy_scope, abstract_model.model.all)
|
|
46
48
|
rescue ::Pundit::NotDefinedError
|
|
47
|
-
abstract_model.model.
|
|
49
|
+
abstract_model.model.none
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
# This is called in the new/create actions to determine the initial attributes for new
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails_admin_next/support/hash_helper"
|
|
4
|
+
|
|
5
|
+
module RailsAdminNext
|
|
6
|
+
# The options handed to to_json/serializable_hash, limited to what a section
|
|
7
|
+
# shows. Both serializers call every name under `methods` and `include` on each
|
|
8
|
+
# record, and serialize every attribute when `only` is missing, so a requested
|
|
9
|
+
# schema is only ever intersected with this, never passed through.
|
|
10
|
+
class SerializationSchema
|
|
11
|
+
def initialize(section, include_associations:)
|
|
12
|
+
@section = section
|
|
13
|
+
@include_associations = include_associations
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Attributes only: a virtual field need not be a method on the record, so
|
|
17
|
+
# calling it unasked could raise where the plain serialization never did.
|
|
18
|
+
def default
|
|
19
|
+
{only: allowed[:only]}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def sanitize(requested)
|
|
23
|
+
requested = HashHelper.symbolize(requested)
|
|
24
|
+
schema = filter(requested, allowed)
|
|
25
|
+
if @include_associations && requested[:include].is_a?(Hash)
|
|
26
|
+
schema[:include] = requested[:include].each_with_object({}) do |(name, value), included|
|
|
27
|
+
next unless value.is_a?(Hash) && allowed[:include].key?(name)
|
|
28
|
+
|
|
29
|
+
included[name] = filter(value, allowed[:include][name])
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
schema
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def allowed
|
|
38
|
+
@allowed ||= begin
|
|
39
|
+
fields = @section.visible_fields
|
|
40
|
+
names = field_names(fields.select { |f| !f.association? || f.association.polymorphic? })
|
|
41
|
+
if @include_associations
|
|
42
|
+
names[:include] = fields.select { |f| f.association? && !f.association.polymorphic? }.to_h do |field|
|
|
43
|
+
associated = field.associated_model_config.export.with(@section.bindings.merge(object: field.associated_model_config.abstract_model.model.new))
|
|
44
|
+
[field.name, field_names(associated.visible_fields.reject(&:association?))]
|
|
45
|
+
end
|
|
46
|
+
else
|
|
47
|
+
# The section already shows these associations, so their keys expose nothing more
|
|
48
|
+
names[:only].concat(fields.select { |f| f.association? && f.association.type == :belongs_to && !f.association.polymorphic? }
|
|
49
|
+
.flat_map { |f| Array(f.association.foreign_key).map(&:to_sym) })
|
|
50
|
+
end
|
|
51
|
+
names
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Mirrors the names the export form offers (main/export.html.erb).
|
|
56
|
+
def field_names(fields)
|
|
57
|
+
fields.each_with_object({only: [], methods: []}) do |field, names|
|
|
58
|
+
list = field.virtual? ? names[:methods] : names[:only]
|
|
59
|
+
if field.association?
|
|
60
|
+
list << field.method_name.to_sym << field.association.foreign_type.to_sym
|
|
61
|
+
else
|
|
62
|
+
list << field.name.to_sym
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# An empty `only` serializes no attribute in ActiveRecord, which is the point.
|
|
68
|
+
def filter(requested, permitted)
|
|
69
|
+
schema = {only: Array(requested[:only]) & permitted[:only]}
|
|
70
|
+
schema[:methods] = Array(requested[:methods]) & permitted[:methods] if requested.key?(:methods)
|
|
71
|
+
schema
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
data/lib/rails_admin_next.rb
CHANGED
|
@@ -12,6 +12,7 @@ require "rails_admin_next/extensions/paper_trail"
|
|
|
12
12
|
require "rails_admin_next/support/csv_converter"
|
|
13
13
|
require "rails_admin_next/support/hash_helper"
|
|
14
14
|
require "rails_admin_next/support/paginated_collection"
|
|
15
|
+
require "rails_admin_next/support/serialization_schema"
|
|
15
16
|
require "yaml"
|
|
16
17
|
|
|
17
18
|
module RailsAdminNext
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_admin_next
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel López Prat
|
|
@@ -298,6 +298,7 @@ files:
|
|
|
298
298
|
- lib/rails_admin_next/support/csv_converter.rb
|
|
299
299
|
- lib/rails_admin_next/support/hash_helper.rb
|
|
300
300
|
- lib/rails_admin_next/support/paginated_collection.rb
|
|
301
|
+
- lib/rails_admin_next/support/serialization_schema.rb
|
|
301
302
|
- lib/rails_admin_next/version.rb
|
|
302
303
|
- lib/tasks/rails_admin.rake
|
|
303
304
|
- skills/rails-admin-next/SKILL.md
|
|
@@ -338,7 +339,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
338
339
|
requirements:
|
|
339
340
|
- - ">="
|
|
340
341
|
- !ruby/object:Gem::Version
|
|
341
|
-
version: 4.0.
|
|
342
|
+
version: 4.0.9
|
|
342
343
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
343
344
|
requirements:
|
|
344
345
|
- - ">="
|