mensa 0.7.4 → 0.8.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: ab3722840d818b5e39cac9b51fe13230d93fc1bcc3cfa61ecebedbff2f1fdc52
4
- data.tar.gz: cb5a23038d098bcde99caf7db0764288c82e882c31416a18875ffda4916dc12f
3
+ metadata.gz: 9a9f69de3ec6ea7a204552adbe5182451252b6bcb6029cb0ed05502d461ccd28
4
+ data.tar.gz: b94a39e616e35d1fc24b6cfdb288e85be31ea639a10b34a26aa8c797aac406cf
5
5
  SHA512:
6
- metadata.gz: 32c0a1ada80a403d35e9400e10273f6122c445e7c71ee2cdd4bc4492f9c11881de46f1020bd4db7591f97a3ec8a16c89012458f89a77e1a65e223800298c95f0
7
- data.tar.gz: 0a5532668ef39a57ff4b9118d2940fb63566bd41d287d28e579f4b729c0e811eff494e95a9035f53c97f6f4f12d7758295ba7d6ff7ffbf1956a238e201737273
6
+ metadata.gz: ce4fed3fa64aaf100014b275281c3639c220d98c651504f0e62a43c9be7532027d4fcf1d03cd0741a7057e247b6e2abfd80517da69f07f4d6b19781fd47f0dbc
7
+ data.tar.gz: 532df7e4b842659ae92ec9189fab594c8cf96bbe2456878e8bd0e732666167e73a147ec18900203822f8a7e9ea736ae2fb641944c4b2350df2e997a0899538c2
data/.shipkit.yml CHANGED
@@ -1,2 +1,2 @@
1
1
  ---
2
- previous_version: 0.7.3
2
+ previous_version: 0.7.4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0
4
+
5
+ - **Behaviour change:** a column shows what was selected in SQL under its name
6
+ (a database column, its `attribute` or an alias in the `scope`), and only
7
+ calls a model method when it asks for one with `method`. Before, a model
8
+ method with the same name as the column took its place, so
9
+ `column(:contact) { attribute "concat_ws(...)" }` on a model with a
10
+ `#contact` method showed the method's result. Columns that relied on a
11
+ model method of their name need `method true`.
12
+ - `method true` calls the model method named after the column.
13
+ - The verifier warns about columns that are always empty: nothing is selected
14
+ under their name and they have no `method` or `render`. When the model has a
15
+ method of that name, it suggests `method true`.
16
+
3
17
  ## 0.7.4
4
18
 
5
19
  - **Behaviour change:** the `matches` and `does_not_match` filters now do a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mensa (0.7.3)
4
+ mensa (0.7.4)
5
5
  csv
6
6
  importmap-rails
7
7
  pagy (>= 43)
data/README.md CHANGED
@@ -119,6 +119,28 @@ You can show your tables on the page using the following:
119
119
  Custom views are views not defined by the developer (SystemViews) but by the end-user by adding/removing filters.
120
120
  When you enable these, they are stored in the database and can be used across sessions, by the user who created them.
121
121
 
122
+ ### Column values
123
+
124
+ A column shows what was selected in SQL under its name: the database column of
125
+ the model, its `attribute`, or an alias your table's `scope` selects. Methods of
126
+ the model are never called, unless the column asks for one with `method`, so a
127
+ model method with the same name as the column doesn't take its place:
128
+
129
+ ```ruby
130
+ column(:contact) do # shows the concat_ws, even if the model has a #contact method
131
+ attribute "concat_ws(', ', contacts.last_name, contacts.first_name)"
132
+ end
133
+ column(:full_name) do # calls user.to_s
134
+ method :to_s
135
+ end
136
+ column(:customer) do # calls user.customer
137
+ method true
138
+ end
139
+ ```
140
+
141
+ Calling methods is slow, it happens for each row, and select what those methods
142
+ need with `internal` columns, as Mensa only selects the table's columns.
143
+
122
144
  ### Sortable and filterable columns
123
145
 
124
146
  Sorting and filtering happen in SQL, so whether a column can be sorted or filtered
@@ -22,6 +22,12 @@ module Mensa
22
22
 
23
23
  AGGREGATE_FUNCTIONS = %i[count sum min max].freeze
24
24
 
25
+ # The record method that gives the value: `method :to_s` names one,
26
+ # `method true` uses the column's name
27
+ def value_method
28
+ config[:method] == true ? name : config[:method].presence
29
+ end
30
+
25
31
  def sort_direction
26
32
  value = table.config.dig(:order, name)
27
33
  value.presence&.to_sym
@@ -9,17 +9,14 @@ module Mensa
9
9
  @record = record
10
10
  end
11
11
 
12
+ # A model method is only called when the column asks for one with
13
+ # `method`, otherwise the value is what was selected under the column's
14
+ # name, so a model method with the same name doesn't shadow it
12
15
  def value(column)
13
- if column.attribute && record.respond_to?(column.attribute)
14
- record.public_send(column.attribute)
15
- elsif column.method && record.respond_to?(column.method)
16
- record.public_send(column.method)
17
- elsif record.respond_to?(column.name)
18
- record.public_send(column.name)
19
- elsif record.respond_to?(:[])
16
+ if column.value_method
17
+ record.public_send(column.value_method)
18
+ elsif record.has_attribute?(column.name)
20
19
  record[column.name]
21
- else
22
- "-"
23
20
  end
24
21
  end
25
22
 
@@ -453,6 +453,7 @@ module Mensa
453
453
  def verify_columns
454
454
  @table.columns.each do |column|
455
455
  verify_column_select(column)
456
+ warn_empty_column(column) unless column.internal?
456
457
  verify_column_sort(column) if column.sortable? && !column.internal?
457
458
  verify_column_render(column) unless column.internal?
458
459
  end
@@ -460,7 +461,7 @@ module Mensa
460
461
 
461
462
  def verify_column_select(column)
462
463
  check(:columns, column.name, "select") do |c|
463
- skip!("no SQL attribute, the value comes from #{column.method ? "method :#{column.method}" : "the record"}") if column.attribute.blank?
464
+ skip!("no SQL attribute, the value comes from #{column.value_method ? "method :#{column.value_method}" : "the scope"}") if column.attribute.blank?
464
465
 
465
466
  # What Mensa selects besides the column: the id and internal columns,
466
467
  # which preloads in the scope need
@@ -473,6 +474,25 @@ module Mensa
473
474
  end
474
475
  end
475
476
 
477
+ # A column only calls a model method when it asks for one with `method`,
478
+ # without one its value is what the scope selects under its name. When
479
+ # nothing is selected under it, and no render block shows something else,
480
+ # the column is always empty.
481
+ def warn_empty_column(column)
482
+ return if column.value_method || column.config[:render].present?
483
+
484
+ record = @rows&.first&.record
485
+ return if record.nil? || record.has_attribute?(column.name)
486
+
487
+ fix = if record.respond_to?(column.name)
488
+ "Fix: add `method true` to the column to show the model's ##{column.name}, or give it an `attribute`."
489
+ else
490
+ "Fix: give the column an `attribute`, select #{column.name} in the table's scope, or add a `method`."
491
+ end
492
+ warn!(:columns, column.name, "empty column",
493
+ "nothing is selected as #{column.name} and it has no `method` or `render`, so it is always empty.\n#{fix}")
494
+ end
495
+
476
496
  # The SQL type of an `attribute` decides which filter operators and values
477
497
  # fit it. Without `type`, Mensa treats it as text: it offers LIKE and
478
498
  # compares with text, which fails for e.g. a boolean expression.
data/lib/mensa/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mensa
2
- VERSION = "0.7.4"
2
+ VERSION = "0.8.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mensa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom de Grunt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-14 00:00:00.000000000 Z
11
+ date: 2026-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails