activeadmin_batched_export 0.3.2 → 0.3.3

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: e93f12265a281843049efbf5266abaa1a097f9d49b642734cf9457c93ce6dd86
4
- data.tar.gz: 9fd765cfb434f66e14ee4a3bcdc76726b0fe45409b0fec04904b435b5949395f
3
+ metadata.gz: 66bcf48aae48932a2dd49a6f494ef82e8ef405e857e0faef6ee9f0df24d2208d
4
+ data.tar.gz: 404850d208cb0339b9a3cc1bc78ceb8acc0bff449f23ed0e1413869cdfa66483
5
5
  SHA512:
6
- metadata.gz: ab8f3476d7eec0a5fba80b7170a116b9a13df06efff0f865d4aa7933593557ecacd056a4fd7ec229f70f66c053779169b6cb6328d3f4a62e0a24ad93f0699eea
7
- data.tar.gz: b7f01fd4e7af21b8c69c0b67bb7380b8b8b0c9fd874e7e155dba65e8bc4197677590c2cc49dade46f2d79c6afca16b08f59edd30e5b87554332e9d6256941c43
6
+ metadata.gz: e3db51c40f02ad9130fd9af283d1d44e45064eb49467046422a4639c24cc5f27bee73b808ff7e5cae4ac436e984ff086556588d0d408a8e52db09b4031bda7a3
7
+ data.tar.gz: c875062f769f3d529ae443cab3de7e46ee8a547e23f8a8a7ad9723a675c153dbcf3c75bb734bdb0cc6fb147535983736da9f0b9f9674b4ec4995b4dd950b7afb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.3.3 (2026-11-03)
4
+
5
+ - Refuse `max_export_rows` on live batch requests even when `export_cursor` is set.
6
+ - Fail closed when release confirmation input reaches EOF; accept empty Enter or case-insensitive `y`.
7
+ - Require a matching `CHANGELOG.md` version heading before `gem push`.
8
+ - Run the test workflow on pull requests.
9
+
3
10
  ## 0.3.2 (2026-09-07)
4
11
 
5
12
  - Serve the workspace export assembly as JavaScript from `ActiveAdmin.importmap`.
data/README.md CHANGED
@@ -53,7 +53,7 @@ add_index :active_admin_batched_export_snapshot_rows, [:token, :position], uniqu
53
53
  add_index :active_admin_batched_export_snapshot_rows, :created_at
54
54
  ```
55
55
 
56
- Without that table, batches walk a live keyset cursor. With it, the first batch stores filtered primary keys and later batches join live rows in freeze order. The token is not an access grant: rows still load through `find_collection`.
56
+ Without that table, batches walk a live keyset cursor. With it, the first batch stores filtered primary keys and later batches join live rows in freeze order. The token is not an access grant: rows still load through `find_collection`. Freeze mode expects integer primary keys (`bigint record_id`); UUID or string keys are not supported yet.
57
57
 
58
58
  Enable download formats per resource:
59
59
 
@@ -153,12 +153,12 @@ Available keys: `workspace`, `card`, `card_title`, `table`, `table_body`, `table
153
153
 
154
154
  Copy any partial from the gem into `app/views/active_admin/batched_export/` in the host app:
155
155
 
156
- - `workspace.html.erb` — page shell; start here for layout changes
156
+ - `workspace.html.erb`: page shell; start here for layout changes
157
157
  - `_summary.html.erb`
158
158
  - `_columns.html.erb`
159
159
  - `_filters.html.erb`
160
160
  - `_progress.html.erb`
161
- - `_actions.html.erb` — load, cancel, save, and back buttons
161
+ - `_actions.html.erb`: load, cancel, save, and back buttons
162
162
 
163
163
  ### Stimulus controller
164
164
 
@@ -185,7 +185,7 @@ The engine pins `controllers/activeadmin_batched_export/batched_export_controlle
185
185
  3. Load export always refetches `export_meta` JSON for a progress estimate, then walks chunks with `export_cursor` / `X-Batched-Export-Next` until that header is absent. When the freeze table exists, the first batch also returns `X-Batched-Export-Snapshot` and later chunks send `export_snapshot` with the cursor.
186
186
  4. User saves the assembled Blob locally. Cancel keeps an incomplete file when any chunks already arrived.
187
187
 
188
- Batched requests limit server memory per request; the browser still holds the full assembled file before save. Very large exports can exhaust tab memory. Tune `batch_size`, `max_batch_size`, and `large_export_row_threshold` for your data width and row counts. The workspace shows a warning when row count reaches the threshold. Set `max_export_rows` to refuse a collection larger than that count (`over_max` on meta, 400 on the first batch).
188
+ Batched requests limit server memory per request; the browser still holds the full assembled file before save. Very large exports can exhaust tab memory. Tune `batch_size`, `max_batch_size`, and `large_export_row_threshold` for your data width and row counts. The workspace shows a warning when row count reaches the threshold. Set `max_export_rows` to refuse a collection larger than that count (`over_max` on meta, 400 on live batches, including requests that already carry `export_cursor`).
189
189
 
190
190
  When the freeze table exists, the first batch stores filtered primary keys in NULL-safe order (RFC-0003). Later batches walk those positions and join live cells. Inserts after freeze are omitted. Updates after freeze appear. Deleted freeze ids are skipped. Without the table, each chunk continues after the last returned sort key and primary key (RFC-0002) and is not a point-in-time snapshot. Custom `order_by` expressions fall back to primary key descending. NULL sort keys sort last in both directions.
191
191
 
@@ -230,7 +230,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md). Bug reports and pull requests are welcom
230
230
 
231
231
  ## License
232
232
 
233
- MIT — see [LICENSE.md](LICENSE.md).
233
+ MIT. See [LICENSE.md](LICENSE.md).
234
234
 
235
235
  ## Sponsors
236
236
 
@@ -48,7 +48,7 @@ Gem::Specification.new do |spec|
48
48
 
49
49
  spec.add_development_dependency "appraisal", "~> 2"
50
50
  spec.add_development_dependency "bundler", ">= 2"
51
- spec.add_development_dependency "polyrun", ">= 2.2.0"
51
+ spec.add_development_dependency "polyrun", ">= 2.2.9"
52
52
  spec.add_development_dependency "prosopite", "~> 2.0"
53
53
  spec.add_development_dependency "rake", "~> 13"
54
54
  spec.add_development_dependency "rspec", "~> 3"
@@ -9,7 +9,7 @@
9
9
  </tr>
10
10
  <tr class="<%= styles[:table_row] %>">
11
11
  <th scope="row" class="<%= styles[:table_header] %>"><%= t("active_admin.batched_export_page.scope_label") %></th>
12
- <td class="<%= styles[:table_cell] %>"><%= current_scope ? scope_name(current_scope) : "—" %></td>
12
+ <td class="<%= styles[:table_cell] %>"><%= current_scope ? scope_name(current_scope) : "-" %></td>
13
13
  </tr>
14
14
  <tr class="<%= styles[:table_row] %>">
15
15
  <th scope="row" class="<%= styles[:table_header] %>"><%= t("active_admin.batched_export_page.sort_label") %></th>
@@ -48,7 +48,9 @@ module ActiveAdmin
48
48
 
49
49
  def render_export_batch(export_format)
50
50
  ensure_batch_download_format_allowed!(export_format)
51
- refuse_over_max_export_rows! if starting_export_walk?
51
+ # Live walks (no snapshot token) always admit against max_export_rows.
52
+ # export_cursor is client-supplied Base64 JSON, so presence alone must not skip the cap.
53
+ refuse_over_max_export_rows! if params[:export_snapshot].blank?
52
54
  field, direction = batched_export_sort_pair
53
55
  cursor = decode_export_cursor(field: field, direction: direction)
54
56
  page = snapshot_export_page(field: field, direction: direction, cursor: cursor)
@@ -139,10 +141,6 @@ module ActiveAdmin
139
141
  paginate(find_collection(except: [:pagination]), 1, effective_batch_size).total_count
140
142
  end
141
143
 
142
- def starting_export_walk?
143
- params[:export_snapshot].blank? && params[:export_cursor].blank?
144
- end
145
-
146
144
  def refuse_over_max_export_rows!
147
145
  cap = BatchedExport.config.max_export_rows
148
146
  return if cap.blank?
@@ -238,7 +236,7 @@ module ActiveAdmin
238
236
  def batched_export_sort_description
239
237
  order_param = params[:order].presence || active_admin_config.sort_order
240
238
  clause = ActiveAdmin::OrderClause.new(active_admin_config, order_param)
241
- return order_param.to_s.tr("_", " ").strip.presence || "—" unless clause.valid?
239
+ return order_param.to_s.tr("_", " ").strip.presence || "-" unless clause.valid?
242
240
 
243
241
  attribute = active_admin_config.resource_class.human_attribute_name(clause.field)
244
242
  direction =
@@ -247,7 +245,7 @@ module ActiveAdmin
247
245
  else
248
246
  I18n.t("active_admin.batched_export_page.sort_ascending")
249
247
  end
250
- "#{attribute} — #{direction}"
248
+ "#{attribute} - #{direction}"
251
249
  end
252
250
 
253
251
  def batched_export_csv_column_metadata
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveAdmin
4
4
  module BatchedExport
5
- VERSION = "0.3.2"
5
+ VERSION = "0.3.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeadmin_batched_export
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Makarov
@@ -91,14 +91,14 @@ dependencies:
91
91
  requirements:
92
92
  - - ">="
93
93
  - !ruby/object:Gem::Version
94
- version: 2.2.0
94
+ version: 2.2.9
95
95
  type: :development
96
96
  prerelease: false
97
97
  version_requirements: !ruby/object:Gem::Requirement
98
98
  requirements:
99
99
  - - ">="
100
100
  - !ruby/object:Gem::Version
101
- version: 2.2.0
101
+ version: 2.2.9
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: prosopite
104
104
  requirement: !ruby/object:Gem::Requirement