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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbd1b1c7b37f7d5d89eb5f9ef44dc086bedf1ecbd47f908c545afbb35e8f8bc1
4
- data.tar.gz: 9358676100cad7935f07c91a757e27a761fe463e1a2fc6b291f8d8a0dc63df0d
3
+ metadata.gz: 957743cf70d6fa24bb0cb1eaf74ca15b4a3b2996e0dca4f5dcee2d6428985d6b
4
+ data.tar.gz: a205770a7170c2b1ce7e04a85cd6422f6cda1d150da237df81795387af8cc18d
5
5
  SHA512:
6
- metadata.gz: 8b999764cff3b8b068b54f5bba5ac2107d9f4545584a76be7764c63b24cfc7135560ce7372fc953bae2aab8a5ef5e3e09735e3e592125b93d21ee70f6f5662a8
7
- data.tar.gz: 477419b70e7056875a32b0790422a1310423d93cd43d91bc68007e918dace9b30acd3a6ad55c38eff654df59fbbe11bb87e5a8141c669807849897519a2ad8d0
6
+ metadata.gz: ad848e8080f75c1e3d6b12c180dcb745bb4a3caea7791ee08d4fec1d97567836effacf01ea340a764b0febb4a52c345e793b3d1708d7496e9d1c2e3f6a167f6d
7
+ data.tar.gz: 37ec4a516104eb2ecc4d8924c758ad862b8fa091f32a0d460b0dfda2f8bc566a233fa61ea81d6cdbbfe49695b1d71eb0aed55f75c281001e9d86a73821fbe8a8
data/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  [![Build](https://github.com/6temes/rails_admin_next/actions/workflows/test.yml/badge.svg)](https://github.com/6temes/rails_admin_next/actions/workflows/test.yml)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE.md)
11
- [![Ruby](https://img.shields.io/badge/Ruby-4.0.5%2B-CC342D.svg)](https://www.ruby-lang.org)
11
+ [![Ruby](https://img.shields.io/badge/Ruby-4.0.9%2B-CC342D.svg)](https://www.ruby-lang.org)
12
12
  [![Rails](https://img.shields.io/badge/Rails-8.1-CC0000.svg)](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.5, Rails ~> 8.1, ActiveRecord only, latest Chrome + Safari. No Mongoid, no multi-bundler / multi-Rails matrix, no legacy-browser CSS.
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.5 · Rails ~> 8.1 · ActiveRecord · a [Propshaft][propshaft] + [importmap-rails][importmap] host (both are pulled in as dependencies). See [Installation](#installation) for the full walkthrough.
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.5
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
- Note that the JSON branch renders the whole record, including columns the model config
420
- hides from the show view.
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`
@@ -1,8 +1,8 @@
1
1
  # Upstream parity
2
2
 
3
- Assessed through upstream `897ffc13` (2026-09-13). Fork point: `d8e0809e` (2025-09-14).
3
+ Assessed through upstream `2dfd05f1` (2026-10-30). Fork point: `d8e0809e` (2025-09-14).
4
4
 
5
- Divergence from the fork point: 787 files, +20,899 / −73,565 lines.
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.5 only | — |
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
- @schema = HashHelper.symbolize(params[:schema].slice(:except, :include, :methods, :only).permit!.to_h) if params[:schema] # to_json and to_xml expect symbols for keys AND values.
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 || {}) }.to_xml(root: @abstract_model.model.model_name.plural)
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.all
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
@@ -7,7 +7,7 @@ module RailsAdminNext
7
7
  # the floor a local `gem build` produces.
8
8
  MAJOR = 1
9
9
  MINOR = 2
10
- PATCH = 0
10
+ PATCH = 1
11
11
  PRE = nil
12
12
 
13
13
  class << self
@@ -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.0
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.5
342
+ version: 4.0.9
342
343
  required_rubygems_version: !ruby/object:Gem::Requirement
343
344
  requirements:
344
345
  - - ">="