recourse 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48a53c1e56600fb74f444c4cd101c9927562a1571a7d3b31e0837f46e0d894af
4
- data.tar.gz: cdd8ae93dbddeb9bbf3b0467ae7ee33c927a4692d1c70b59e5f157c7a49a3843
3
+ metadata.gz: 4258e3870b7a65f742563e24f02f45e2c2716bcc22666fbbb63867f70b656e71
4
+ data.tar.gz: 5d2ae92ccde9995457f78060fd9f22d74fd3971bae0c5de68ec7aa022e290603
5
5
  SHA512:
6
- metadata.gz: d70d2a2d28bc6a44cf2f3b138dbf088a2390a316e7baa74ff554d477d48cf561612f3c06fc6760a48a4fa950f4a0e85f555f4d8b050bae81d78228cdd90b179a
7
- data.tar.gz: 2e736d79aaecff3ecec5f9f0881a049456e6eb3a99072a4bea6a484152c889569d77e5c39b118449e0c6595eab190654640df12b2a9e570c36d8fa99e639d88c
6
+ metadata.gz: 343ca9a2eba9663618236339649c017f00934d3d01cf8741e6b152a8cc6c6bf17036eff91ea63f46acf5cf804e65ae7f59b68ffdf541ae1bd06e9c5dd1332793
7
+ data.tar.gz: 5f5946a02e7d397bec49ac1089912933f730758215ea4e18559f003a5a13522e5de587db0abb9c75d00a9fab5ba7978a73858a634bfda05956d0267c70617df0
data/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  For more information about changelogs, check [Keep a Changelog](http://keepachangelog.com) and
6
6
  [Vandamme](http://tech-angels.github.io/vandamme).
7
7
 
8
+ ## 4.1.0 - 2026-09-08
9
+
10
+ * [Feature] Rows with nothing in the sorted column come last
11
+
12
+ Whichever way a table is ordered — by the model's own `recourse_order`, or by the
13
+ heading a reader clicked — the rows with nothing in that column now come after every
14
+ row that has something, where the database's default put them first on a descending
15
+ sort. A `recourse_order` given as a Symbol or a Hash earns this; a SQL string a host
16
+ wrote is still taken as written, so `'size desc nulls last'` and `{ size: :desc }` now
17
+ say the same thing.
18
+
8
19
  ## 4.0.0 - 2026-09-08
9
20
 
10
21
  Version 4 is a rewrite, developed under the working name `drive` and released here
data/README.md CHANGED
@@ -95,7 +95,7 @@ module Market::Recoursive extend ActiveSupport::Concern
95
95
  def recourse_label = :slug # what a menu and a cell call one
96
96
  def recourse_hidden = %i[callback_url payload] # off every screen
97
97
  def recourse_displayed = :created_at # back on the table
98
- def recourse_order = 'size desc nulls last' # how the index sorts
98
+ def recourse_order = { size: :desc } # how the index sorts
99
99
  def recourse_icon = :question # a Unicon concept
100
100
  end
101
101
  end
@@ -106,7 +106,7 @@ end
106
106
  | [`recourse_label`](https://rubydoc.info/gems/recourse/Recourse/Recoursive#recourse_label-instance_method) | `:name` | the column a combobox shows and a foreign-key cell reads; typed rather than picked where it has a length validator |
107
107
  | [`recourse_hidden`](https://rubydoc.info/gems/recourse/Recourse/Recoursive#recourse_hidden-instance_method) | `[]` | columns kept off the table, the page, the form and the search |
108
108
  | [`recourse_displayed`](https://rubydoc.info/gems/recourse/Recourse/Recoursive#recourse_displayed-instance_method) | `[]` | columns a table draws that it would leave off: encrypted ones, the id, timestamps, JSON |
109
- | [`recourse_order`](https://rubydoc.info/gems/recourse/Recourse/Recoursive#recourse_order-instance_method) | `:id` | the index's order, in any shape `order` takes |
109
+ | [`recourse_order`](https://rubydoc.info/gems/recourse/Recourse/Recoursive#recourse_order-instance_method) | `:id` | the index's order, a Symbol or a Hash; rows with nothing in the column come last |
110
110
  | [`recourse_icon`](https://rubydoc.info/gems/recourse/Recourse/Recoursive#recourse_icon-instance_method) | the model's name | the icon on the sidebar, the crumbs and the tabs |
111
111
 
112
112
  What needs no hook, being read off the model:
@@ -0,0 +1,21 @@
1
+ # Reopened for the order an index lists its rows in.
2
+ module Recourse
3
+ # What `recourse_order` comes to as Arel, every column ending in NULLS LAST: a row
4
+ # with nothing in the column is what a reader is least looking for, whichever way
5
+ # the rows run. Extended onto `Recourse`, so this is `Recourse.nulls_last`.
6
+ module Orders
7
+ # A Symbol is that column ascending and a Hash is each column in its direction,
8
+ # both with the empty rows last. Anything else — a SQL string a host wrote — is
9
+ # taken as written.
10
+ def nulls_last(model, order)
11
+ directions = order.is_a?(Symbol) ? { order => :asc } : order
12
+ return [*order] unless directions.is_a? Hash
13
+
14
+ directions.map do |column, direction|
15
+ model.arel_table[column].public_send(direction).nulls_last
16
+ end
17
+ end
18
+ end
19
+
20
+ extend Orders
21
+ end
@@ -19,11 +19,9 @@ module Recourse
19
19
  @query = relation.ransack conditions(params)
20
20
  end
21
21
 
22
- # The relation the index lists. Ransack has already ordered it where a heading
23
- # asked, so the model's own order only applies when nothing did.
22
+ # The relation the index lists, in the order a heading asked for or the model's own.
24
23
  def scope
25
- scope = @query.result
26
- scope = scope.order(*kept_first, @model.recourse_order) if @query.sorts.empty?
24
+ scope = @query.result.reorder(*ordering)
27
25
  includes = @model.recourse_includes
28
26
  return scope if includes.blank?
29
27
 
@@ -32,6 +30,16 @@ module Recourse
32
30
 
33
31
  private
34
32
 
33
+ # A heading's sort or the model's own order, each column with its empty rows last.
34
+ # Ransack has ordered the relation already where a heading asked, but as the bare
35
+ # column; the same sort is written again here so it ends the way every order does.
36
+ def ordering
37
+ sorts = @query.sorts.map { |sort| sort.attr.public_send(sort.dir).nulls_last }
38
+ return sorts if sorts.any?
39
+
40
+ kept_first + Recourse.nulls_last(@model, @model.recourse_order)
41
+ end
42
+
35
43
  # The rows this viewer has kept, ahead of whatever the model orders by — but only
36
44
  # where nobody clicked a heading, which is the same word `recourse_order` answers
37
45
  # to. A semi-join rather than an outer one: it cannot multiply a row, and it
@@ -1,4 +1,4 @@
1
1
  module Recourse
2
2
  # Version of the gem, read by the gemspec and by hosts checking compatibility.
3
- VERSION = '4.0.0'
3
+ VERSION = '4.1.0'
4
4
  end
data/lib/recourse.rb CHANGED
@@ -12,6 +12,7 @@ require_relative 'recourse/icons'
12
12
  require_relative 'recourse/controllers'
13
13
  require_relative 'recourse/helpers'
14
14
  require_relative 'recourse/limits'
15
+ require_relative 'recourse/orders'
15
16
  require_relative 'recourse/writes'
16
17
  require_relative 'recourse/zones'
17
18
  require_relative 'recourse/broadcasting'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recourse
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - claudiob
@@ -220,6 +220,7 @@ files:
220
220
  - lib/recourse/helpers/zones.rb
221
221
  - lib/recourse/icons.rb
222
222
  - lib/recourse/limits.rb
223
+ - lib/recourse/orders.rb
223
224
  - lib/recourse/recoursive.rb
224
225
  - lib/recourse/registry.rb
225
226
  - lib/recourse/routes.rb