recourse 7.0.0 → 7.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 +4 -4
- data/CHANGELOG.md +18 -0
- data/app/views/recourses/_card.html.erb +3 -0
- data/app/views/recourses/edit.html.erb +0 -4
- data/lib/recourse/columns.rb +8 -0
- data/lib/recourse/helpers/cards.rb +1 -4
- data/lib/recourse/helpers/deletions.rb +10 -1
- data/lib/recourse/recoursive.rb +3 -0
- data/lib/recourse/searchable/columns.rb +1 -0
- data/lib/recourse/searchable/terms.rb +3 -0
- data/lib/recourse/searchable.rb +2 -0
- data/lib/recourse/version.rb +1 -1
- data/lib/recourse.rb +3 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80390029ce0bfed87fcf8247faceb992a392422044f0b0641bbfadb9bd3660f0
|
|
4
|
+
data.tar.gz: 81f226e7f69b2fa9846e2bc80e610d227e182d680b8c1d563b095a26f26fee1c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f87b1572b17070744c3c03c2f64b6d699e53a738270b4bf2d88f0040264992a050709e891fde967e2c21f64508e41191a56cab0ba3b7e3dda1fa04bb3b25f9dd
|
|
7
|
+
data.tar.gz: bcf92ebc75b14486038c81b558580ff958e49d28a17259d895a97888e5a350dd3afe610f72b959b343a9a47b9c41a09b203518b1f28532d61fada8df683b5f2c
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,24 @@ For more information about changelogs, check [Keep a Changelog](http://keepachan
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## 7.1.0 - 2026-09-20
|
|
11
|
+
|
|
12
|
+
* [CHANGE] The card draws the button that deletes what the page is about
|
|
13
|
+
|
|
14
|
+
It was drawn by the gem's own `edit` template, so a host writing a template of its own
|
|
15
|
+
lost it and wrote `destroy_resource_button` back by hand. The card draws it now, the way
|
|
16
|
+
it draws the tabs and the buttons beside the trail, and a host's page is its body alone.
|
|
17
|
+
|
|
18
|
+
A record's own page carries it, whichever of the two is open, so a resource routed to be
|
|
19
|
+
read and deleted but never changed is deleted from the page that reads it. Nothing gains
|
|
20
|
+
the ability to delete what it could not: a route without `destroy` draws no button.
|
|
21
|
+
|
|
22
|
+
* [CHANGE] A column the database generates is never offered on a form
|
|
23
|
+
|
|
24
|
+
Postgres writes a stored generated column out of the others and takes no value for one,
|
|
25
|
+
so a field for it would be refused whatever was typed. Such a column is read on every
|
|
26
|
+
other screen as before.
|
|
27
|
+
|
|
10
28
|
## 7.0.0 - 2026-09-19
|
|
11
29
|
|
|
12
30
|
* [BREAKING] What a page counts is the gem's to work out
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
<%# Every bare action the routes drew under this record: a nested resource with no
|
|
5
5
|
index of its own is reached from nowhere, so its button sits beside the
|
|
6
6
|
breadcrumbs wherever the record is shown, on whichever of its pages that is. -%>
|
|
7
|
+
<%# The button that deletes what the page is about, drawn here rather than in a template
|
|
8
|
+
so a host writing its own show or edit keeps it without asking. -%>
|
|
7
9
|
<% content_for :actions do %>
|
|
10
|
+
<%= destroy_resource_button destroyable_record %>
|
|
8
11
|
<% bare_action_buttons(record).each do |label, path, method| %>
|
|
9
12
|
<%= button_to label, path, method:, form_class: 'ms-3',
|
|
10
13
|
class: 'btn theme-primary btn-sm btn-solid' %>
|
data/lib/recourse/columns.rb
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Reopened for the order a row reads in, which a table, a show page and a form all ask
|
|
2
2
|
# for the same way.
|
|
3
3
|
module Recourse
|
|
4
|
+
# Columns the database writes itself out of the others, which a form never offers: a
|
|
5
|
+
# stored generated column takes no value, and Postgres refuses the one a form would send.
|
|
6
|
+
# @param model [Class] the model the page is about.
|
|
7
|
+
# @return [Array<String>] the names of its generated columns.
|
|
8
|
+
def self.virtual_columns(model)
|
|
9
|
+
model.columns.select(&:virtual?).map(&:name)
|
|
10
|
+
end
|
|
11
|
+
|
|
4
12
|
# Which part of a row a column belongs to. What a column holds is the gem's to know
|
|
5
13
|
# and where the schema put it is the host's, so both have a say: the kind picks the
|
|
6
14
|
# band, and the order inside the band is the one the table already has. Extended onto
|
|
@@ -7,11 +7,8 @@ module Recourse
|
|
|
7
7
|
|
|
8
8
|
# The record whose card this page is drawn in: the parent, on a page nested under
|
|
9
9
|
# one, and the record itself where the page is its look or its change. An index of
|
|
10
|
-
# its own, and a form for a record that is not there yet, stand outside a card.
|
|
11
|
-
# host drawing a page whole says so by assigning `@recourse_card = false`.
|
|
10
|
+
# its own, and a form for a record that is not there yet, stand outside a card.
|
|
12
11
|
def card_record
|
|
13
|
-
return if controller_assign('recourse_card') == false
|
|
14
|
-
|
|
15
12
|
resource_parent || (resource_record if controller.action_name.in? %w[show edit])
|
|
16
13
|
end
|
|
17
14
|
|
|
@@ -12,10 +12,18 @@ module Recourse
|
|
|
12
12
|
|
|
13
13
|
private
|
|
14
14
|
|
|
15
|
+
# The record a page may delete: the one it is about, on its own look or its own
|
|
16
|
+
# change page. A nested index wears the parent's card and deletes nothing from it.
|
|
17
|
+
# @api private
|
|
18
|
+
def destroyable_record
|
|
19
|
+
resource_record if controller.action_name.in? %w[show edit]
|
|
20
|
+
end
|
|
21
|
+
|
|
15
22
|
# Deletes the record on the page, or nothing at all where no action is routed
|
|
16
23
|
# to delete it with — the same two guards the edit link answers to.
|
|
24
|
+
# @api private
|
|
17
25
|
def destroy_resource_button(record)
|
|
18
|
-
path = destroy_resource_path
|
|
26
|
+
path = record && destroy_resource_path(record)
|
|
19
27
|
return unless path
|
|
20
28
|
|
|
21
29
|
confirm_button_to t('recourse.delete', model: resource_name), path,
|
|
@@ -24,6 +32,7 @@ module Recourse
|
|
|
24
32
|
form_class: 'd-inline-block'
|
|
25
33
|
end
|
|
26
34
|
|
|
35
|
+
# @api private
|
|
27
36
|
# What deleting this record takes with it, counted a level down and no further:
|
|
28
37
|
# a state reaches counties, then ZIPs, then locations, and counting that far
|
|
29
38
|
# would join 40,965 rows to draw one page.
|
data/lib/recourse/recoursive.rb
CHANGED
|
@@ -25,10 +25,12 @@ module Recourse
|
|
|
25
25
|
# `%i[created_at updated_at]` asks for the two Rails keeps rather than the two
|
|
26
26
|
# a record is about. A timestamp named here still lands last, and in that order,
|
|
27
27
|
# whichever way round it was written.
|
|
28
|
+
# @api private
|
|
28
29
|
def recourse_displayed = []
|
|
29
30
|
|
|
30
31
|
# `ZIP code`: what to call a foreign key pointing here. A form's label, a table's
|
|
31
32
|
# heading and a search prompt all name the same thing, so they name it once.
|
|
33
|
+
# @api private
|
|
32
34
|
def recourse_reference_name
|
|
33
35
|
attribute = Recourse.downcase human_attribute_name(recourse_label)
|
|
34
36
|
|
|
@@ -37,6 +39,7 @@ module Recourse
|
|
|
37
39
|
|
|
38
40
|
# True when the label has a length, so it is short enough to be typed and a
|
|
39
41
|
# form can ask for the value instead of listing every record to pick from.
|
|
42
|
+
# @api private
|
|
40
43
|
def recourse_typed_label?
|
|
41
44
|
validators_on(recourse_label).any? ActiveModel::Validations::LengthValidator
|
|
42
45
|
end
|
|
@@ -2,6 +2,7 @@ module Recourse
|
|
|
2
2
|
module Searchable
|
|
3
3
|
# What a model's own schema offers a search: which of its columns are worth
|
|
4
4
|
# looking through, and which of its foreign keys are worth looking past.
|
|
5
|
+
# @api private
|
|
5
6
|
module Columns
|
|
6
7
|
# Column types a search box can match on containment. An enum is a Postgres
|
|
7
8
|
# type of its own, and what it holds is a word, so it reads as a string too.
|
|
@@ -15,6 +15,7 @@ module Recourse
|
|
|
15
15
|
# and the labels behind foreign keys — less the one `except:` names — on
|
|
16
16
|
# containment; or, for a model that keeps nothing in plaintext worth
|
|
17
17
|
# searching, its encrypted columns, whole.
|
|
18
|
+
# @api private
|
|
18
19
|
def recourse_search_terms(except: nil)
|
|
19
20
|
plain = recourse_searchable_columns + recourse_searchable_references(except:)
|
|
20
21
|
return [plain, 'cont'] if plain.any?
|
|
@@ -23,6 +24,7 @@ module Recourse
|
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
# Those same terms as words, lower case but for the acronyms among them.
|
|
27
|
+
# @api private
|
|
26
28
|
def recourse_search_names(except: nil)
|
|
27
29
|
fields, = recourse_search_terms(except:)
|
|
28
30
|
|
|
@@ -33,6 +35,7 @@ module Recourse
|
|
|
33
35
|
|
|
34
36
|
# A term is a column of this model, or a `zip_code` reaching through one of its
|
|
35
37
|
# foreign keys — which a form and a table already have a name for.
|
|
38
|
+
# @api private
|
|
36
39
|
def recourse_term_name(field)
|
|
37
40
|
reached = recourse_searchable_associations.find { |one| field.start_with? "#{one.name}_" }
|
|
38
41
|
return reached.klass.recourse_reference_name if reached
|
data/lib/recourse/searchable.rb
CHANGED
|
@@ -47,11 +47,13 @@ module Recourse
|
|
|
47
47
|
# True where a foreign key pointing here is typed rather than picked, which a
|
|
48
48
|
# form and the controller reading its parameters back have to agree on: the label
|
|
49
49
|
# is bounded, or the table is too long to list.
|
|
50
|
+
# @api private
|
|
50
51
|
def recourse_typed_reference? = recourse_typed_label? || !recourse_listable?
|
|
51
52
|
|
|
52
53
|
# True where every row of this model could be listed in one menu. The count is
|
|
53
54
|
# bounded, so the question costs the same on ten rows as on ten million, and it
|
|
54
55
|
# is asked once per class — a table that crosses the line is noticed at boot.
|
|
56
|
+
# @api private
|
|
55
57
|
def recourse_listable?
|
|
56
58
|
return @recourse_listable unless @recourse_listable.nil?
|
|
57
59
|
|
data/lib/recourse/version.rb
CHANGED
data/lib/recourse.rb
CHANGED
|
@@ -59,10 +59,11 @@ module Recourse
|
|
|
59
59
|
|
|
60
60
|
# Columns a user may set: the form offers these, the show page reads these out, and
|
|
61
61
|
# `create` permits these. A counter cache is none of a user's business — Rails keeps
|
|
62
|
-
# it, so a form that offered one would let it be typed over
|
|
62
|
+
# it, so a form that offered one would let it be typed over, and neither is a column
|
|
63
|
+
# the database generates: it takes no value at all.
|
|
63
64
|
def self.editable_columns(model)
|
|
64
65
|
ordered model, model.column_names - ['id', *TIMESTAMPS] - counters(model).keys -
|
|
65
|
-
hidden_columns(model)
|
|
66
|
+
hidden_columns(model) - virtual_columns(model)
|
|
66
67
|
end
|
|
67
68
|
|
|
68
69
|
# Columns no screen shows: whatever the model asked to hide through `recourse_hidden`
|