From 9767d779695da54805daba9a3d50520c7fb81921 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 10:05:02 +0000 Subject: [PATCH 1/2] fix(model): tableName("x") sets the table instead of silently no-opping The documented setter form tableName("my_table") in config() was a silent no-op: tableName() was a zero-argument getter, so the extra positional argument was ignored and the model kept its convention table (first finder throws Wheels.TableNotFound). tableName() now accepts an optional name and delegates to table() when given, returning the resolved name; the zero-argument getter behavior is unchanged. Refs #3079 Co-Authored-By: Claude Opus 4.8 Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> --- changelog.d/3079-tablename-setter.fixed.md | 1 + vendor/wheels/model/miscellaneous.cfc | 10 ++++++- .../tests/specs/model/miscellaneousSpec.cfc | 27 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 changelog.d/3079-tablename-setter.fixed.md diff --git a/changelog.d/3079-tablename-setter.fixed.md b/changelog.d/3079-tablename-setter.fixed.md new file mode 100644 index 0000000000..bd74d02d27 --- /dev/null +++ b/changelog.d/3079-tablename-setter.fixed.md @@ -0,0 +1 @@ +- `tableName("my_table")` now works as a model table setter: when called with a name it delegates to `table()` and returns the resolved name, instead of silently no-opping and leaving the model on its convention table. The zero-argument getter form is unchanged (#3079) diff --git a/vendor/wheels/model/miscellaneous.cfc b/vendor/wheels/model/miscellaneous.cfc index fd763bdec9..fd3b3fac06 100644 --- a/vendor/wheels/model/miscellaneous.cfc +++ b/vendor/wheels/model/miscellaneous.cfc @@ -170,11 +170,19 @@ component { /** * Returns the name of the database table that this model is mapped to. + * When called with a `name` argument it acts as a setter, delegating to `table()`, + * and returns the resolved name. This makes the commonly-reached-for + * `tableName("my_table")` form in `config()` work instead of silently no-opping. * * [section: Model Class] * [category: Miscellaneous Functions] + * + * @name When provided, sets the table this model maps to (alias for `table()`). */ - public string function tableName() { + public string function tableName(any name) { + if (StructKeyExists(arguments, "name")) { + table(arguments.name); + } if ($get("lowerCaseTableNames")) { return LCase(variables.wheels.class.tableName); } else { diff --git a/vendor/wheels/tests/specs/model/miscellaneousSpec.cfc b/vendor/wheels/tests/specs/model/miscellaneousSpec.cfc index a7d7dc84ce..c45c6c5ccb 100644 --- a/vendor/wheels/tests/specs/model/miscellaneousSpec.cfc +++ b/vendor/wheels/tests/specs/model/miscellaneousSpec.cfc @@ -159,6 +159,33 @@ component extends="wheels.WheelsTest" { expect(users.recordcount).toBe(3) }) }) + + describe("Tests that tableName acts as a setter when given a name - issue 3079", () => { + + afterEach(() => { + // Restore the mapped table so the override never leaks into other specs + g.model("author").table("c_o_r_e_authors") + }) + + it("delegates to table() when a name argument is passed", () => { + author = g.model("author") + author.tableName("tbl_authors_override") + + expect(author.tableName()).toBe("tbl_authors_override") + }) + + it("returns the newly set name from the setter call", () => { + author = g.model("author") + + expect(author.tableName("tbl_authors_override")).toBe("tbl_authors_override") + }) + + it("still returns the current name when called with no argument", () => { + author = g.model("author") + + expect(author.tableName()).toBe("c_o_r_e_authors") + }) + }) } function assert_pagination(required string handle) { From eb0eb5fa9accbffb4f0d52c05db69ec32a0602f3 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 10:17:52 +0000 Subject: [PATCH 2/2] docs: align model-snippets reference to use tableName() setter form Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> --- .ai/wheels/snippets/model-snippets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ai/wheels/snippets/model-snippets.md b/.ai/wheels/snippets/model-snippets.md index db919550ba..23a8663941 100755 --- a/.ai/wheels/snippets/model-snippets.md +++ b/.ai/wheels/snippets/model-snippets.md @@ -8,7 +8,7 @@ Common model patterns and code snippets for Wheels applications. component extends="Model" { function config() { // Table mapping (if different from convention) - table("custom_table_name"); + tableName("custom_table_name"); // Associations hasMany("comments");