

{"sections":[{"categories":["Error Handling","Miscellaneous Functions","Multi-Tenancy","Routing"],"name":"Configuration"},{"categories":["Authorization Functions","Configuration Functions","Flash Functions","Miscellaneous Functions","Pagination Functions","Provides Functions","Rendering Functions"],"name":"Controller"},{"categories":["Channel Functions","Date Functions","Miscellaneous Functions","String Functions","UUID Functions"],"name":"Global Helpers"},{"categories":["General Functions","Migration Functions","Table Definition Functions"],"name":"Migrator"},{"categories":["Create Functions","CRUD Functions","Delete Functions","Locking Functions","Miscellaneous Functions","Read Functions","Statistics Functions","Update Functions"],"name":"Model Class"},{"categories":["Association Functions","Callback Functions","Enum Functions","Miscellaneous Functions","Multi-Tenancy","Scope Functions","Validation Functions"],"name":"Model Configuration"},{"categories":["Change Functions","CRUD Functions","Error Functions","Miscellaneous Functions"],"name":"Model Object"},{"categories":["Asset Functions","Error Functions","Form Association Functions","Form Object Functions","Form Tag Functions","General Form Functions","Link Functions","Miscellaneous Functions","Pagination Functions","Sanitization Functions"],"name":"View Helpers"}],"functions":[{"returntype":"void","slug":"model.accessibleProperties","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Allow only `isActive` to be set through mass assignment (e.g. `updateAll()`, `new()`, `update()`).\nconfig() {\n\taccessibleProperties(&quot;isActive&quot;);\n}\n\n// 2. Allow a comma-delimited list of properties to be set through mass assignment.\n//    Any property not in this list is silently ignored when set via mass assignment.\nconfig() {\n\taccessibleProperties(&quot;firstName,lastName,email&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Use this method to specify which properties can be set through mass assignment.\n\n","parameters":[{"type":"string","hint":"Property name (or list of property names) that are allowed to be altered through mass assignment.","required":false,"name":"properties","default":""}],"name":"accessibleProperties","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"migration.addColumn","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a simple string column to an existing table\naddColumn(table=&quot;members&quot;, columnType=&quot;string&quot;, columnName=&quot;status&quot;, limit=50);\n\n// 2. Add a boolean column with a default value and no NULLs allowed\naddColumn(\n    table=&quot;members&quot;,\n    columnType=&quot;boolean&quot;,\n    columnName=&quot;isActive&quot;,\n    default=1,\n    allowNull=false\n);\n\n// 3. Add a decimal column with precision and scale (e.g. for a price field)\naddColumn(\n    table=&quot;products&quot;,\n    columnType=&quot;decimal&quot;,\n    columnName=&quot;price&quot;,\n    precision=10,\n    scale=2,\n    default=0,\n    allowNull=false\n);\n</code></pre>","hasExtended":true},"hint":"adds a column to existing table\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The Name of the table to add the column to","required":true,"name":"table"},{"type":"string","hint":"The type of the new column","required":true,"name":"columnType"},{"type":"string","hint":"The name of the new column","required":false,"name":"columnName"},{"type":"string","hint":"Modern alias for `columnName` (matches the plural form every TableDefinition column helper accepts). Pass one or the other — not both.","required":false,"name":"columnNames"},{"type":"string","hint":"The name of the column which this column should be inserted after","required":false,"name":"afterColumn","default":""},{"type":"string","hint":"Name for new reference column, see documentation for references function, required if columnType is 'reference'","required":false,"name":"referenceName","default":""},{"type":"any","hint":"Default value for this column","required":false,"name":"default"},{"type":"boolean","hint":"Whether to allow NULL values","required":false,"name":"allowNull"},{"type":"numeric","hint":"Character or integer size limit for column","required":false,"name":"limit"},{"type":"numeric","hint":"precision value for decimal columns, i.e. number of digits the column can hold","required":false,"name":"precision"},{"type":"numeric","hint":"scale value for decimal columns, i.e. number of digits that can be placed to the right of the decimal point (must be less than or equal to precision)","required":false,"name":"scale"}],"name":"addColumn","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"model.addError","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add an error to the `email` property.\nthis.addError(property=&quot;email&quot;, message=&quot;Sorry, you are not allowed to use that email. Try again, please.&quot;);\n\n// 2. Add a named error so you can distinguish it from other errors on the same property.\nthis.addError(property=&quot;email&quot;, message=&quot;That email address is already taken.&quot;, name=&quot;emailTaken&quot;);\n\n// 3. Check for the named error after adding it.\nthis.addError(property=&quot;username&quot;, message=&quot;Username is reserved.&quot;, name=&quot;reservedUsername&quot;);\nif (this.hasErrors(property=&quot;username&quot;, name=&quot;reservedUsername&quot;)) {\n\twriteOutput(&quot;A reserved-username error is present.&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Adds an error on a specific property.\n\n","parameters":[{"type":"string","hint":"The name of the property you want to add an error on.","required":true,"name":"property"},{"type":"string","hint":"The error message (such as \"Please enter a correct name in the form field\" for example).","required":true,"name":"message"},{"type":"string","hint":"A name to identify the error by (useful when you need to distinguish one error from another one set on the same object and you don't want to use the error message itself for that).","required":false,"name":"name","default":""}],"name":"addError","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"void","slug":"model.addErrorToBase","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a general error on the object (not tied to any single property)\nuser = model(&quot;User&quot;).findByKey(params.userId);\nuser.addErrorToBase(message=&quot;Your account has been locked. Please contact support.&quot;);\n\n// 2. Add a named base error so it can be targeted or cleared later\norder = model(&quot;Order&quot;).findByKey(params.orderId);\norder.addErrorToBase(message=&quot;This order cannot be placed outside business hours.&quot;, name=&quot;businessHoursViolation&quot;);\nif (order.hasErrors(name=&quot;businessHoursViolation&quot;)) {\n    // handle the named error\n}\n\n// 3. Use addErrorToBase inside a custom validation method on the model\nfunction validate() {\n    if (this.totalAmount &gt; creditLimit()) {\n        this.addErrorToBase(message=&quot;The total amount exceeds your available credit limit.&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Adds an error on the object as a whole (not tied to any specific property).\n\n","parameters":[{"type":"string","hint":"The error message (such as \"Please enter a correct name in the form field\" for example).","required":true,"name":"message"},{"type":"string","hint":"A name to identify the error by (useful when you need to distinguish one error from another one set on the same object and you don't want to use the error message itself for that).","required":false,"name":"name","default":""}],"name":"addErrorToBase","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"void","slug":"migration.addForeignKey","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a foreign key from orders.customerId to customers.id\naddForeignKey(\n    table=&quot;orders&quot;,\n    referenceTable=&quot;customers&quot;,\n    column=&quot;customerId&quot;,\n    referenceColumn=&quot;id&quot;\n);\n\n// 2. Add a foreign key from comments.postId to posts.id\naddForeignKey(\n    table=&quot;comments&quot;,\n    referenceTable=&quot;posts&quot;,\n    column=&quot;postId&quot;,\n    referenceColumn=&quot;id&quot;\n);\n\n// 3. Use addForeignKey in a migration's up() and remove it in down()\n// In your migration CFC:\n//\n// public void function up() {\n//     addForeignKey(\n//         table=&quot;order_items&quot;,\n//         referenceTable=&quot;orders&quot;,\n//         column=&quot;orderId&quot;,\n//         referenceColumn=&quot;id&quot;\n//     );\n// }\n//\n// public void function down() {\n//     dropForeignKey(table=&quot;order_items&quot;, keyName=&quot;FK_order_items_orders&quot;);\n// }\n</code></pre>","hasExtended":true},"hint":"Add a foreign key constraint to the database, using the reference name that was used to create it\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name to perform the operation on","required":true,"name":"table"},{"type":"string","hint":"The reference table name to perform the operation on","required":true,"name":"referenceTable"},{"type":"string","hint":"The column name to perform the operation on","required":false,"name":"column"},{"type":"string","hint":"Modern alias for `column` (consistent with the rest of the migrator surface).","required":false,"name":"columnName"},{"type":"string","hint":"The reference column name to perform the operation on","required":true,"name":"referenceColumn"}],"name":"addForeignKey","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"controller.addFormat","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add the `js` format\naddFormat(extension=&quot;js&quot;, mimeType=&quot;text/javascript&quot;);\n\n// 2. Add the `ppt` and `pptx` formats\naddFormat(extension=&quot;ppt&quot;, mimeType=&quot;application/vnd.ms-powerpoint&quot;);\naddFormat(extension=&quot;pptx&quot;, mimeType=&quot;application/vnd.ms-powerpoint&quot;);\n\n// 3. Add a custom `csv` format so controllers can respond with `responds(formats=&quot;csv&quot;)`\naddFormat(extension=&quot;csv&quot;, mimeType=&quot;text/csv&quot;);\n</code></pre>","hasExtended":true},"hint":"Adds a new MIME type to your Wheels application for use with responding to multiple formats.\n\n","parameters":[{"type":"string","hint":"File extension to add.","required":true,"name":"extension"},{"type":"string","hint":"Matching MIME type to associate with the file extension.","required":true,"name":"mimeType"}],"name":"addFormat","tags":{"category":"Miscellaneous Functions","sectionClass":"configuration","section":"Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"migration.addIndex","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a basic index on a single column\naddIndex(table=&quot;users&quot;, columnNames=&quot;email&quot;);\n\n// 2. Add a unique index to enforce uniqueness on a column\naddIndex(table=&quot;members&quot;, columnNames=&quot;username&quot;, unique=true);\n\n// 3. Add a composite index on multiple columns\naddIndex(table=&quot;orders&quot;, columnNames=&quot;customerId,createdAt&quot;);\n\n// 4. Add an index with a custom index name\n// (defaults to tableName_firstColumnName, e.g. &quot;posts_publishedAt&quot;)\naddIndex(table=&quot;posts&quot;, columnNames=&quot;publishedAt&quot;, indexName=&quot;idx_posts_published&quot;);\n</code></pre>","hasExtended":true},"hint":"Add database index on a table column\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name to perform the index operation on","required":true,"name":"table"},{"type":"string","hint":"One or more column names to index, comma separated","required":false,"name":"columnNames"},{"type":"boolean","hint":"If true will create a unique index constraint","required":false,"name":"unique","default":"false"},{"type":"string","hint":"The name of the index to add: Defaults to table name + underscore + first column name","required":false,"name":"indexName","default":""}],"name":"addIndex","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.addRecord","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Insert a simple seed record into a settings table\naddRecord(\n    table = &quot;settings&quot;,\n    name = &quot;siteName&quot;,\n    value = &quot;My Wheels App&quot;\n);\n\n// 2. Insert a record with multiple columns (extra keyword arguments become column/value pairs)\naddRecord(\n    table = &quot;people&quot;,\n    id = 1,\n    title = &quot;Mr&quot;,\n    firstName = &quot;Bruce&quot;,\n    lastName = &quot;Wayne&quot;,\n    email = &quot;bruce@wayneenterprises.com&quot;,\n    phone = &quot;555-678-9099&quot;\n);\n\n// 3. Seed an admin user role during a migration's up() function\ncomponent extends=&quot;wheels.migrator.Migration&quot; {\n    function up() {\n        addRecord(\n            table = &quot;roles&quot;,\n            id = 1,\n            name = &quot;admin&quot;,\n            active = true\n        );\n    }\n    function down() {\n        removeRecord(table = &quot;roles&quot;, where = &quot;id = 1&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Adds a record to a table\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name to add the record to","required":true,"name":"table"}],"name":"addRecord","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.addReference","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a foreign key from comments.postId to posts.id using a reference name\n// Equivalent to: addForeignKey(table=&quot;comments&quot;, referenceTable=&quot;posts&quot;, column=&quot;postId&quot;, referenceColumn=&quot;id&quot;)\naddReference(table=&quot;comments&quot;, referenceName=&quot;post&quot;);\n\n// 2. Add a foreign key from order_items.orderId to orders.id\naddReference(table=&quot;order_items&quot;, referenceName=&quot;order&quot;);\n\n// 3. Use addReference in a migration's up() and undo it with dropReference() in down()\n// In your migration CFC:\n//\n// public void function up() {\n//     addReference(table=&quot;comments&quot;, referenceName=&quot;post&quot;);\n// }\n//\n// public void function down() {\n//     dropReference(table=&quot;comments&quot;, referenceName=&quot;post&quot;);\n// }\n</code></pre>","hasExtended":true},"hint":"Add a foreign key constraint to the database, using the reference name that was used to create it\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name to perform the operation on","required":true,"name":"table"},{"type":"string","hint":"The reference table name to perform the operation on","required":false,"name":"referenceName"},{"type":"string","hint":"Alias for `referenceName` (consistent with the modern migrator surface — `columnName` / `columnNames` are accepted alongside the legacy form).","required":false,"name":"columnName"},{"type":"string","hint":"Plural alias for `referenceName`. When both `columnName` and `columnNames` are supplied, `columnNames` wins.","required":false,"name":"columnNames"}],"name":"addReference","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"model.afterCreate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single method to run after an object is created\n// In models/User.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterCreate(&quot;sendWelcomeEmail&quot;);\n    }\n    private function sendWelcomeEmail() {\n        // send email to this.email\n    }\n}\n\n// 2. Register multiple methods by passing a comma-delimited list\nafterCreate(&quot;updateCache,notifyAdmin&quot;);\n\n// 3. Register using the named `methods` argument\nafterCreate(methods=&quot;syncToExternalApi&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after a new object is created.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterCreate","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterDelete","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Call a single method after an object is deleted\n// In models/Order.cfc\nafterDelete(&quot;notifyWarehouse&quot;);\n\n// 2. Call multiple methods after an object is deleted (comma-separated list)\n// In models/User.cfc\nafterDelete(&quot;removeFromSearchIndex,clearCachedData&quot;);\n\n// 3. Register several after-delete callbacks individually for clarity\n// In models/Article.cfc\nafterDelete(&quot;logDeletion&quot;);\nafterDelete(&quot;cleanupAttachments&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after an object is deleted.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterDelete","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterFind","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single callback method to run after records are fetched\n// In models/User.cfc\nconfig() {\n\tafterFind(&quot;setFetchedAt&quot;);\n}\n\n// The callback receives each row's columns as arguments; return the struct to modify the record.\nfunction setFetchedAt() {\n\targuments.fetchedAt = Now();\n\treturn arguments;\n}\n\n// 2. Format a column value after a find (works for both query rows and objects)\n// In models/Product.cfc\nconfig() {\n\tafterFind(&quot;formatPrice&quot;);\n}\n\nfunction formatPrice() {\n\tif (StructKeyExists(arguments, &quot;price&quot;)) {\n\t\targuments.price = DollarFormat(arguments.price);\n\t}\n\treturn arguments;\n}\n\n// 3. Register multiple callback methods as a comma-delimited list\nconfig() {\n\tafterFind(&quot;setFetchedAt,formatPrice&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after an existing object has been initialized (which is usually done with the <code>findByKey</code> or <code>findOne</code> method).\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterFind","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterInitialization","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Call a single method after any object is initialized (whether new or fetched from the database)\nafterInitialization(&quot;fixObj&quot;);\n\n// 2. Call multiple methods after initialization by passing a comma-delimited list\nafterInitialization(&quot;setDefaults,fixObj&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after an object has been initialized.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterInitialization","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterNew","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Call a single method after a new object is initialized\n// In models/User.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterNew(&quot;setDefaults&quot;);\n    }\n    private function setDefaults() {\n        this.role = &quot;member&quot;;\n        this.active = true;\n    }\n}\n\n// 2. Call multiple methods after a new object is initialized (comma-delimited list)\nafterNew(&quot;setDefaults,generateToken&quot;);\n\n// 3. Use the `method` argument alias instead of `methods`\nafterNew(method=&quot;setDefaults&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after a new object has been initialized (which is usually done with the <code>new</code> method).\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterNew","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterSave","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single callback method to run after an object is saved (both create and update)\n// In models/User.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterSave(&quot;sendWelcomeEmail&quot;);\n    }\n\n    private function sendWelcomeEmail() {\n        // called automatically each time a User is saved\n    }\n}\n\n// 2. Register multiple callback methods using a comma-delimited list\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterSave(&quot;updateSearchIndex,notifyAdmins&quot;);\n    }\n}\n\n// 3. Register multiple callbacks by calling afterSave() more than once\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterSave(&quot;updateSearchIndex&quot;);\n        afterSave(&quot;notifyAdmins&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after an object is saved.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterSave","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterUpdate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single method to run after an object is updated\n// In models/User.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterUpdate(&quot;clearCache&quot;);\n    }\n    private function clearCache() {\n        // invalidate cached data for this user\n    }\n}\n\n// 2. Register multiple methods by passing a comma-delimited list\nafterUpdate(&quot;clearCache,notifyAuditLog&quot;);\n\n// 3. Register using the named `methods` argument\nafterUpdate(methods=&quot;syncToSearchIndex&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after an existing object is updated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterUpdate","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterValidation","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Call a single method after an object is validated\nafterValidation(&quot;fixObj&quot;);\n\n// 2. Call multiple methods after an object is validated (comma-delimited list)\nafterValidation(&quot;sanitizeFields,logValidationResult&quot;);\n\n// 3. Use the singular `method` alias for clarity\nafterValidation(method=&quot;trimWhitespace&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after an object is validated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterValidation","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterValidationOnCreate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Call a single method after a new object is validated on create\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tafterValidationOnCreate(&quot;assignDefaults&quot;);\n\t}\n\n\tprivate function assignDefaults() {\n\t\tif (!Len(this.role)) {\n\t\t\tthis.role = &quot;member&quot;;\n\t\t}\n\t}\n}\n\n// 2. Call multiple methods after validation on create (comma-delimited list)\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tafterValidationOnCreate(&quot;sanitizeFields,logNewRecord&quot;);\n\t}\n}\n\n// 3. Use the singular `method` alias for clarity\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tafterValidationOnCreate(method=&quot;trimWhitespace&quot;);\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after a new object is validated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterValidationOnCreate","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.afterValidationOnUpdate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Call a single method after an existing object is validated on update\n// In models/User.cfc:\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterValidationOnUpdate(&quot;stampUpdatedBy&quot;);\n    }\n\n    private function stampUpdatedBy() {\n        this.updatedBy = request.currentUserId;\n    }\n}\n\n// 2. Register multiple methods to run after an existing object is validated on update\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterValidationOnUpdate(&quot;normalizeSlug,logValidation&quot;);\n    }\n\n    private function normalizeSlug() {\n        this.slug = LCase(Replace(this.title, &quot; &quot;, &quot;-&quot;, &quot;all&quot;));\n    }\n\n    private function logValidation() {\n        // custom logging logic here\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called after an existing object is validated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"afterValidationOnUpdate","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"array","slug":"model.allAssociationErrors","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Collect all validation errors from associated objects on a post\npost = model(&quot;Post&quot;).findOne(where=&quot;id=1&quot;, include=&quot;comments&quot;);\nerrors = post.allAssociationErrors();\n// errors -&gt; array of error structs from associated comments (and their associations, recursively)\n// Each struct contains keys: property, message, name\n\n// 2. Use allErrors() with includeAssociations=true instead (preferred shorthand)\n// allErrors() calls allAssociationErrors() internally when includeAssociations is true\npost = model(&quot;Post&quot;).findOne(where=&quot;id=1&quot;, include=&quot;comments&quot;);\nallErrors = post.allErrors(includeAssociations=true);\n// allErrors -&gt; combined array of the post's own errors plus all associated errors\n\n// 3. Check if any associated model has errors before saving\norder = model(&quot;Order&quot;).findOne(where=&quot;id=1&quot;, include=&quot;lineItems&quot;);\nassociationErrors = order.allAssociationErrors();\nif (arrayLen(associationErrors)) {\n    writeOutput(&quot;One or more line items have validation errors.&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Gets all associated errors recursively\n\n","parameters":[{"type":"array","required":false,"name":"seenErrors","default":"[runtime expression]"}],"name":"allAssociationErrors","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"struct","slug":"model.allChanges","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get an object, change some properties, and inspect all changes before saving\nmember = model(&quot;member&quot;).findByKey(params.memberId);\nmember.firstName = params.newFirstName;\nmember.email = params.newEmail;\nchanges = member.allChanges();\n// changes -&gt; {\n//   firstName: { changedFrom: &quot;Jane&quot;, changedTo: &quot;Janet&quot; },\n//   email:     { changedFrom: &quot;jane@example.com&quot;, changedTo: &quot;janet@example.com&quot; }\n// }\n\n// 2. Only call allChanges() when there are changes to process\npost = model(&quot;post&quot;).findByKey(params.id);\npost.title = params.title;\npost.body = params.body;\nif (post.hasChanged()) {\n    changes = post.allChanges();\n    for (prop in changes) {\n        writeOutput(&quot;'#prop#' changed from '#changes[prop].changedFrom#' to '#changes[prop].changedTo#'&quot;);\n    }\n}\n\n// 3. allChanges() returns an empty struct when nothing has changed\nuser = model(&quot;user&quot;).findByKey(params.userId);\nchanges = user.allChanges();\n// changes -&gt; {} (empty struct — no unsaved changes)\n</code></pre>","hasExtended":true},"hint":"Returns a struct detailing all changes that have been made on the object but not yet saved to the database.\n\n","parameters":[],"name":"allChanges","tags":{"category":"Change Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"changefunctions"}},{"returntype":"array","slug":"model.allErrors","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all errors on a model object after a failed validation\nuser = model(&quot;User&quot;).new(username=&quot;&quot;, password=&quot;&quot;);\nuser.valid();\nerrors = user.allErrors();\n// errors -&gt;\n// [\n//   { message: &quot;Username must not be blank.&quot;, name: &quot;&quot;, property: &quot;username&quot; },\n//   { message: &quot;Password must not be blank.&quot;, name: &quot;&quot;, property: &quot;password&quot; }\n// ]\n\n// 2. Check for errors and iterate over them\nif (user.hasErrors()) {\n\tfor (error in user.allErrors()) {\n\t\twriteOutput(error.property &amp; &quot;: &quot; &amp; error.message);\n\t}\n}\n\n// 3. Include errors from associated models (e.g. a user with associated profile)\nuser = model(&quot;User&quot;).findOne(where=&quot;id=1&quot;, include=&quot;profile&quot;);\nuser.valid();\nallErrors = user.allErrors(includeAssociations=true);\n// allErrors contains errors from both user and its associated profile model\n</code></pre>","hasExtended":true},"hint":"Returns an array of all the errors on the object.\n\n\nIt does this by storing instances of models that are associations, and not checking associations of those instances because they have already been checked.","parameters":[{"type":"boolean","required":false,"name":"includeAssociations","default":false},{"type":"array","hint":"is a private argument not meant to be used by the user, the function uses this to ensure circular dependency avoidance.","required":false,"name":"seenErrors","default":"[runtime expression]"}],"name":"allErrors","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"any","slug":"migration.announce","availableIn":["migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Log a custom message during a migration's up() step\nfunction up() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\tt = createTable(name=&quot;articles&quot;, force=true);\n\t\t\tt.string(columnNames=&quot;title&quot;, allowNull=false);\n\t\t\tt.text(columnNames=&quot;body&quot;);\n\t\t\tt.timestamps();\n\t\t\tt.create();\n\t\t\tannounce(&quot;Created articles table&quot;);\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (StructKeyExists(state, &quot;exception&quot;)) {\n\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\tthrow(errorCode=&quot;1&quot;, detail=state.exception.detail, message=state.exception.message, type=&quot;any&quot;);\n\t\t} else {\n\t\t\ttransaction action=&quot;commit&quot;;\n\t\t}\n\t}\n}\n\n// 2. Announce multiple steps to provide granular feedback\nfunction up() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\taddColumn(table=&quot;users&quot;, columnType=&quot;string&quot;, columnName=&quot;apiKey&quot;, limit=64, allowNull=true);\n\t\t\tannounce(&quot;Added apiKey column to users&quot;);\n\n\t\t\taddIndex(table=&quot;users&quot;, columnNames=&quot;apiKey&quot;, unique=true);\n\t\t\tannounce(&quot;Added unique index on users.apiKey&quot;);\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (StructKeyExists(state, &quot;exception&quot;)) {\n\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\tthrow(errorCode=&quot;1&quot;, detail=state.exception.detail, message=state.exception.message, type=&quot;any&quot;);\n\t\t} else {\n\t\t\ttransaction action=&quot;commit&quot;;\n\t\t}\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Used internally by Migrator to provide feedback to the GUI and CLI about completed DB operations\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","required":true,"name":"message"}],"name":"announce","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"struct","slug":"mapper.api","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\n// 1. Basic API scope using the default path and name prefix &quot;api&quot;\nmapper()\n    .api()\n        // Route name:  apiUsers\n        // Example URL: /api/users\n        .resources(&quot;users&quot;)\n    .end()\n.end();\n\n// 2. Combine api() with version() for versioned API endpoints\nmapper()\n    .api()\n        .version(1)\n            // Route name:  apiV1Users\n            // Example URL: /api/v1/users\n            .resources(&quot;users&quot;)\n        .end()\n\n        .version(2)\n            // Route name:  apiV2Products\n            // Example URL: /api/v2/products\n            .resources(&quot;products&quot;)\n        .end()\n    .end()\n.end();\n\n// 3. Override the default path and name prefixes\nmapper()\n    .api(path=&quot;public-api&quot;, name=&quot;publicApi&quot;)\n        // Route name:  publicApiOrders\n        // Example URL: /public-api/orders\n        .resources(&quot;orders&quot;)\n    .end()\n.end();\n\n// 4. Use api() with a callback to avoid manual .end() calls\nmapper()\n    .api(callback=function(m) {\n        m.version(number=1, callback=function(m) {\n            // Route name:  apiV1Users\n            // Example URL: /api/v1/users\n            m.resources(&quot;users&quot;);\n        });\n    })\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Scope routes under an API path prefix. Shorthand for <code>.group(path=\"api\", name=\"api\", ...)</code>. Typically used in combination with <code>version()</code> to organize versioned API endpoints.\n\n","parameters":[{"type":"string","hint":"URL path prefix for the API. Defaults to `\"api\"`.","required":false,"name":"path","default":"api"},{"type":"string","hint":"Name prefix for route names. Defaults to `\"api\"`.","required":false,"name":"name","default":"api"},{"type":"struct","hint":"Variable patterns to apply to all child routes.","required":false,"name":"constraints"},{"type":"any","hint":"A callback function to define nested routes within this API scope.","required":false,"name":"callback"}],"name":"api","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"model.associationInfo","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all association definitions for a model and inspect them\ninfo = model(&quot;post&quot;).associationInfo();\n// info is a struct where each key is an association name, e.g.:\n// info.comments.type        -&gt; &quot;hasMany&quot;\n// info.comments.modelName   -&gt; &quot;Comment&quot;\n// info.comments.foreignKey  -&gt; &quot;postId&quot;\n// info.comments.dependent   -&gt; &quot;delete&quot;\n// info.author.type          -&gt; &quot;belongsTo&quot;\n// info.author.modelName     -&gt; &quot;Author&quot;\n\n// 2. Check whether a specific association is defined on the model\ninfo = model(&quot;user&quot;).associationInfo();\nif (structKeyExists(info, &quot;profile&quot;)) {\n    writeOutput(&quot;User has a profile association of type: &quot; &amp; info.profile.type);\n}\n\n// 3. Iterate over all associations to build a summary\ninfo = model(&quot;article&quot;).associationInfo();\nfor (assocName in info) {\n    writeOutput(assocName &amp; &quot; -&gt; &quot; &amp; info[assocName].type &amp; &quot; &quot; &amp; info[assocName].modelName);\n}\n</code></pre>","hasExtended":true},"hint":"Returns a struct containing all association definitions for this model.\nEach key is the association name, and the value is a struct with association metadata\nincluding <code>type</code> (belongsTo, hasMany, hasOne), <code>modelName</code>, <code>foreignKey</code>, <code>joinKey</code>, and <code>dependent</code>.\n\n","parameters":[],"name":"associationInfo","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"model.associationNames","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all association names defined on a model\nnames = model(&quot;User&quot;).associationNames();\n// names -&gt; &quot;profile,posts,comments&quot;\n\n// 2. Check whether a specific association exists on the model\nif (listFindNoCase(model(&quot;Post&quot;).associationNames(), &quot;comments&quot;)) {\n    // the Post model has a &quot;comments&quot; association\n}\n\n// 3. Iterate over each association name\nfor (assocName in listToArray(model(&quot;Order&quot;).associationNames())) {\n    writeOutput(assocName);\n}\n</code></pre>","hasExtended":true},"hint":"Returns a list of association names defined on this model.\n\n","parameters":[],"name":"associationNames","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.authenticityToken","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Embed the CSRF token in a manually-built form hidden field\ntoken = authenticityToken();\nwriteOutput('&lt;input type=&quot;hidden&quot; name=&quot;authenticityToken&quot; value=&quot;' &amp; token &amp; '&quot;&gt;');\n\n// 2. Pass the token as a request header for an AJAX call (e.g. in a JavaScript data island)\nwriteOutput('&lt;meta name=&quot;csrf-token&quot; content=&quot;' &amp; authenticityToken() &amp; '&quot;&gt;');\n// JavaScript can then read this and send it as the X-CSRF-Token header with each POST request.\n\n// 3. Include the token in a JSON API response body so a client can replay it\ntokenValue = authenticityToken();\nwriteOutput(serializeJSON({authenticityToken = tokenValue}));\n</code></pre>","hasExtended":true},"hint":"Returns the raw CSRF authenticity token\n\n","parameters":[],"name":"authenticityToken","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.authenticityTokenField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Include CSRF token in a plain HTML form that POSTs data\n//    (use this when you are not using startFormTag())\n&lt;form action=&quot;#urlFor(route='posts')#&quot; method=&quot;post&quot;&gt;\n  #authenticityTokenField()#\n  &lt;!--- other fields here ---&gt;\n&lt;/form&gt;\n\n// 2. Not needed for GET forms — GET requests are not CSRF-protected\n&lt;form action=&quot;#urlFor(route='posts')#&quot; method=&quot;get&quot;&gt;\n  &lt;!--- no token required ---&gt;\n&lt;/form&gt;\n</code></pre>","hasExtended":true},"hint":"Returns a hidden form field containing a new authenticity token.\n\n","parameters":[],"name":"authenticityTokenField","tags":{"category":"General Form Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"generalformfunctions"}},{"returntype":"any","slug":"controller.authorize","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Authorizes the current user for an action on a record by dispatching to the\nrecord's policy (<code>app/policies/<ModelName>Policy.cfc</code>). Throws\n<code>Wheels.NotAuthorized</code> (HTTP 403) when the policy denies, and returns the\nrecord unchanged when it allows so the call can be inlined:\n<code></code><code>\nfunction update() {\npost = authorize(model(\"Post\").findByKey(params.key));\npost.update(params.post);\n}\n</code><code></code>\nA missing policy class throws <code>Wheels.Policy.NotDefined</code> in development and\ntesting (loud, Pundit-style, to catch typos) and silently denies in\nproduction — the same environment posture as <code>tableName()</code> (##3079). A\npolicy class that lacks a method for the action denies.\n\n","parameters":[{"type":"any","hint":"The model instance (or model class / model name string) to authorize against.","required":true,"name":"record"},{"type":"string","hint":"The policy method to dispatch. Defaults to the current `params.action`, resolved at call time.","required":false,"name":"action","default":""}],"name":"authorize","tags":{"category":"Authorization Functions","sectionClass":"controller","section":"Controller","categoryClass":"authorizationfunctions"}},{"returntype":"string","slug":"controller.autoLink","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Link both URLs and email addresses (default behavior)\nresult = autoLink(&quot;Download CFWheels from http://cfwheels.org/download&quot;);\n// result -&gt; &quot;Download CFWheels from &lt;a href=&quot;http://cfwheels.org/download&quot;&gt;http://cfwheels.org/download&lt;/a&gt;&quot;\n\n// 2. Link email addresses only\nresult = autoLink(text=&quot;Email us at info@cfwheels.org or visit http://cfwheels.org&quot;, link=&quot;emailAddresses&quot;);\n// result -&gt; &quot;Email us at &lt;a href=&quot;mailto:info@cfwheels.org&quot;&gt;info@cfwheels.org&lt;/a&gt; or visit http://cfwheels.org&quot;\n\n// 3. Link URLs only (skip email addresses)\nresult = autoLink(text=&quot;Visit http://cfwheels.org or contact info@cfwheels.org&quot;, link=&quot;URLs&quot;);\n// result -&gt; &quot;Visit &lt;a href=&quot;http://cfwheels.org&quot;&gt;http://cfwheels.org&lt;/a&gt; or contact info@cfwheels.org&quot;\n\n// 4. Disable auto-linking of relative URLs\nresult = autoLink(text=&quot;See /docs/guide for details or http://cfwheels.org for more.&quot;, relative=false);\n// result -&gt; &quot;See /docs/guide for details or &lt;a href=&quot;http://cfwheels.org&quot;&gt;http://cfwheels.org&lt;/a&gt; for more.&quot;\n</code></pre>","hasExtended":true},"hint":"Turns all URLs and email addresses into links.\n\n","parameters":[{"type":"string","hint":"The text to create links in.","required":true,"name":"text"},{"type":"string","hint":"Whether to link URLs, email addresses or both. Possible values are: `all` (default), `URLs` and `emailAddresses`.","required":false,"name":"link","default":"all"},{"type":"boolean","hint":"Should we auto-link relative urls.","required":false,"name":"relative","default":true},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"autoLink","tags":{"category":"Link Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"linkfunctions"}},{"returntype":"void","slug":"model.automaticValidations","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Disable automatic validations for this model (useful when automatic validations are enabled globally but you want to opt out for a specific model).\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tautomaticValidations(false);\n\t}\n}\n\n// 2. Explicitly enable automatic validations for this model (useful when automatic validations are disabled globally but you want to opt in for a specific model).\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tautomaticValidations(true);\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Whether or not to enable default validations for this model.\n\n","parameters":[{"type":"boolean","hint":"Set to `true` or `false`.","required":true,"name":"value"}],"name":"automaticValidations","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"any","slug":"model.average","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the average salary for all employees.\navgSalary = model(&quot;employee&quot;).average(&quot;salary&quot;);\n\n// 2. Get the average salary for employees in a given department.\navgSalary = model(&quot;employee&quot;).average(property=&quot;salary&quot;, where=&quot;departmentId=#params.key#&quot;);\n\n// 3. Make sure a numeric value is always returned if no records are found.\navgSalary = model(&quot;employee&quot;).average(property=&quot;salary&quot;, where=&quot;salary BETWEEN #params.min# AND #params.max#&quot;, ifNull=0);\n\n// 4. Average only distinct salary values (duplicates excluded).\navgSalary = model(&quot;employee&quot;).average(property=&quot;salary&quot;, distinct=true);\n\n// 5. Get the average salary grouped by department (returns a query).\navgByDept = model(&quot;employee&quot;).average(property=&quot;salary&quot;, group=&quot;departmentId&quot;);\n</code></pre>","hasExtended":true},"hint":"Calculates the average value for a given property.\nUses the SQL function <code>AVG</code>.\nIf no records can be found to perform the calculation on you can use the <code>ifNull</code> argument to decide what should be returned.\n\n","parameters":[{"type":"string","hint":"Name of the property to calculate the average for.","required":true,"name":"property"},{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"boolean","hint":"When `true`, `AVG` will be performed only on each unique instance of a value, regardless of how many times the value occurs.","required":false,"name":"distinct","default":false},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"any","hint":"The value returned if no records are found. Common usage is to set this to `0` to make sure a numeric value is always returned instead of a blank string.","required":false,"name":"ifNull","default":""},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"},{"type":"string","hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"group"}],"name":"average","tags":{"category":"Statistics Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"statisticsfunctions"}},{"returntype":"string","slug":"controller.badgeClass","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Classe Bootstrap d'une valeur de reference.\nLa couleur vient desormais de l'API, qui la tient du referentiel. Le\nhelper ne fait plus que l'habiller — il ne DEDUIT plus rien d'un libelle,\nce qui obligeait a maintenir la correspondance en double.","parameters":[{"type":"any","required":false,"name":"valeur","default":"[runtime expression]"}],"name":"badgeClass","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"void","slug":"model.beforeCreate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single callback method to run before a new object is created\n// Defined inside the model's config() function\nbeforeCreate(&quot;setDefaults&quot;);\n\n// 2. Register multiple callback methods to run in sequence before creation\nbeforeCreate(&quot;generateSlug,stampCreatedBy&quot;);\n\n// 3. Register callbacks using the named argument\nbeforeCreate(methods=&quot;generateToken,normalizeEmail&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called before a new object is created.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"beforeCreate","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.beforeDelete","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single method to run before an object is deleted\n// In models/Post.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeDelete(&quot;cleanUpAttachments&quot;);\n    }\n\n    private function cleanUpAttachments() {\n        // Remove associated files from disk before the record is deleted\n        fileDelete(expandPath(&quot;/uploads/#this.id#&quot;));\n    }\n}\n\n// 2. Register multiple methods to run before deletion (comma-delimited list)\n// In models/User.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeDelete(&quot;revokeTokens,archiveActivity&quot;);\n    }\n\n    private function revokeTokens() {\n        model(&quot;Token&quot;).deleteAll(where=&quot;userId=#this.id#&quot;);\n    }\n\n    private function archiveActivity() {\n        model(&quot;ActivityLog&quot;).updateAll(\n            properties=&quot;archivedAt=NOW()&quot;,\n            where=&quot;userId=#this.id#&quot;\n        );\n    }\n}\n\n// 3. Halt deletion by returning false from the callback\n// In models/Order.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeDelete(&quot;preventIfShipped&quot;);\n    }\n\n    private function preventIfShipped() {\n        // Returning false cancels the delete operation\n        if (this.status eq &quot;shipped&quot;) {\n            return false;\n        }\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called before an object is deleted.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"beforeDelete","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.beforeSave","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Call a single method before every save (create or update)\n// In models/User.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeSave(&quot;normalizeEmail&quot;);\n    }\n\n    private function normalizeEmail() {\n        this.email = LCase(Trim(this.email));\n    }\n}\n\n// 2. Register multiple callback methods as a comma-delimited list\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeSave(&quot;stripWhitespace,generateSlug&quot;);\n    }\n}\n\n// 3. Use the `method` argument alias to register a single callback\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeSave(method=&quot;sanitizeContent&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called before an object is saved.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"beforeSave","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.beforeUpdate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Call a single method before every update\n// In models/User.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeUpdate(&quot;stampUpdatedBy&quot;);\n    }\n\n    private function stampUpdatedBy() {\n        this.updatedBy = session.userId;\n    }\n}\n\n// 2. Register multiple callback methods as a comma-delimited list\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeUpdate(&quot;validateOwnership,recalculateTotals&quot;);\n    }\n}\n\n// 3. Use the `method` argument alias to register a single callback\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeUpdate(method=&quot;fixObj&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called before an existing object is updated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"beforeUpdate","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.beforeValidation","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single method to run before any validation\n// In models/User.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeValidation(&quot;normalizeEmail&quot;);\n        validatesPresenceOf(&quot;email&quot;);\n    }\n\n    private function normalizeEmail() {\n        this.email = LCase(Trim(this.email));\n    }\n}\n\n// 2. Register multiple methods to run before validation using a comma-delimited list\n// In models/Article.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeValidation(&quot;stripTags,setSlug&quot;);\n        validatesPresenceOf(properties=&quot;title,slug&quot;);\n    }\n\n    private function stripTags() {\n        this.title = ReReplace(this.title, &quot;&lt;[^&gt;]*&gt;&quot;, &quot;&quot;, &quot;all&quot;);\n    }\n\n    private function setSlug() {\n        if (!Len(this.slug)) {\n            this.slug = LCase(ReReplace(Trim(this.title), &quot;\\s+&quot;, &quot;-&quot;, &quot;all&quot;));\n        }\n    }\n}\n\n// 3. Register callbacks across multiple calls (they are stacked in order)\n// In models/Product.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeValidation(&quot;trimFields&quot;);\n        beforeValidation(&quot;setDefaults&quot;);\n    }\n\n    private function trimFields() {\n        this.name = Trim(this.name);\n    }\n\n    private function setDefaults() {\n        if (!Len(this.status)) {\n            this.status = &quot;draft&quot;;\n        }\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called before an object is validated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"beforeValidation","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.beforeValidationOnCreate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single method to run before a new object is validated\n// In models/User.cfc config()\nbeforeValidationOnCreate(&quot;sanitizeEmail&quot;);\n\n// 2. Register multiple methods to run before a new object is validated\n// In models/Order.cfc config()\nbeforeValidationOnCreate(&quot;setDefaultStatus,generateTrackingNumber&quot;);\n\n// 3. Use the `method` argument alias instead of `methods`\n// In models/Post.cfc config()\nbeforeValidationOnCreate(method=&quot;normalizeSlug&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called before a new object is validated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"beforeValidationOnCreate","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.beforeValidationOnUpdate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single method to run before an existing object is validated on update\n// Called inside the model's config() function\nbeforeValidationOnUpdate(&quot;sanitizeFields&quot;);\n\n// 2. Register multiple methods as a comma-delimited list\nbeforeValidationOnUpdate(&quot;sanitizeFields,enforceBusinessRules&quot;);\n\n// 3. Use the `method` argument alias for a single callback\nbeforeValidationOnUpdate(method=&quot;normalizeEmail&quot;);\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called before an existing object is validated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","required":false,"name":"methods","default":""}],"name":"beforeValidationOnUpdate","tags":{"category":"Callback Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"callbackfunctions"}},{"returntype":"void","slug":"model.belongsTo","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Specify that instances of this model belong to an author.\n// (The table for this model should have a foreign key column, typically named `authorId`.)\nbelongsTo(&quot;author&quot;);\n\n// 2. Override naming conventions by specifying `modelName` and `foreignKey` explicitly.\nbelongsTo(name=&quot;bookWriter&quot;, modelName=&quot;author&quot;, foreignKey=&quot;authorId&quot;);\n\n// 3. Use a LEFT OUTER JOIN instead of the default INNER JOIN when including this association.\nbelongsTo(name=&quot;category&quot;, joinType=&quot;outer&quot;);\n\n// 4. Declare a polymorphic belongsTo association (e.g. a Comment that can belong to a Post or a Photo).\n// Wheels will look for `commentableId` and `commentableType` columns on the comments table.\nbelongsTo(name=&quot;commentable&quot;, polymorphic=true);\n</code></pre>","hasExtended":true},"hint":"Sets up a <code>belongsTo</code> association between this model and the specified one.\nUse this association when this model contains a foreign key referencing another model.\n\n","parameters":[{"type":"string","hint":"Gives the association a name that you refer to when working with the association (in the `include` argument to `findAll`, to name one example).","required":true,"name":"name"},{"type":"string","hint":"Name of associated model (usually not needed if you follow Wheels conventions because the model name will be deduced from the `name` argument).","required":false,"name":"modelName","default":""},{"type":"string","hint":"Foreign key property name (usually not needed if you follow Wheels conventions since the foreign key name will be deduced from the `name` argument).","required":false,"name":"foreignKey","default":""},{"type":"string","hint":"Column name to join to if not the primary key (usually not needed if you follow Wheels conventions since the join key will be the table's primary key/keys).","required":false,"name":"joinKey","default":""},{"type":"string","hint":"Use to set the join type when joining associated tables. Possible values are `inner` (for `INNER JOIN`) and `outer` (for `LEFT OUTER JOIN`).","required":false,"name":"joinType","default":"inner"},{"type":"boolean","hint":"Set to `true` to declare a polymorphic `belongsTo` association. The foreign key defaults to `{name}Id` and a `{name}Type` column is used to store the owning model name at runtime.","required":false,"name":"polymorphic","default":false}],"name":"belongsTo","tags":{"category":"Association Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"associationfunctions"}},{"returntype":"any","slug":"tabledefinition.bigInteger","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single bigInteger column to a new table\nt = createTable(name='events');\n\tt.bigInteger(columnNames='externalId');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple bigInteger columns at once\nt = createTable(name='analytics');\n\tt.bigInteger(columnNames='pageViews,uniqueVisitors', default=0, allowNull=false);\n\tt.string(columnNames='path', limit=500, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a bigInteger column with a limit and default when altering an existing table\nt = changeTable(name='orders');\n\tt.bigInteger(columnNames='totalCents', default=0, allowNull=false);\nt.change();\n</code></pre>","hasExtended":true},"hint":"Adds integer columns to table definition.\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"numeric","required":false,"name":"limit"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"bigInteger","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"any","slug":"tabledefinition.binary","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single binary column to a new table\nt = createTable(name='attachments');\n\tt.string(columnNames='filename', limit=255, allowNull=false);\n\tt.binary(columnNames='fileData');\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple binary columns at once\nt = createTable(name='media');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.binary(columnNames='thumbnail,fullImage', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a binary column with a default when altering an existing table\nt = changeTable(name='documents');\n\tt.binary(columnNames='rawContent', allowNull=true);\nt.change();\n</code></pre>","hasExtended":true},"hint":"Adds binary columns to table definition.\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"binary","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"any","slug":"tabledefinition.boolean","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single boolean column to a new table\nt = createTable(name='products');\n\tt.string(columnNames='name', limit=255, allowNull=false);\n\tt.boolean(columnNames='isActive', default=1, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple boolean columns at once\nt = createTable(name='users');\n\tt.string(columnNames='email', limit=255, allowNull=false);\n\tt.boolean(columnNames='isAdmin,isVerified,isActive', default=0, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a boolean column to an existing table\nt = changeTable(name='articles');\n\tt.boolean(columnNames='isPublished', default=0, allowNull=false);\nt.change();\n</code></pre>","hasExtended":true},"hint":"Adds boolean columns to table definition.\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"boolean","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"controller.buttonTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic submit button inside a form\n#startFormTag(action=&quot;create&quot;)#\n    #buttonTag(content=&quot;Save changes&quot;, value=&quot;save&quot;)#\n#endFormTag()#\n&lt;!--- Produces: &lt;button type=&quot;submit&quot; value=&quot;save&quot;&gt;Save changes&lt;/button&gt; ---&gt;\n\n// 2. Reset button to clear form fields\n#buttonTag(content=&quot;Clear form&quot;, type=&quot;reset&quot;)#\n&lt;!--- Produces: &lt;button type=&quot;reset&quot; value=&quot;save&quot;&gt;Clear form&lt;/button&gt; ---&gt;\n\n// 3. Plain button (no form submission) with a CSS class and id\n#buttonTag(content=&quot;Open dialog&quot;, type=&quot;button&quot;, value=&quot;open&quot;, class=&quot;btn btn-secondary&quot;, id=&quot;openDialogBtn&quot;)#\n&lt;!--- Produces: &lt;button type=&quot;button&quot; value=&quot;open&quot; class=&quot;btn btn-secondary&quot; id=&quot;openDialogBtn&quot;&gt;Open dialog&lt;/button&gt; ---&gt;\n\n// 4. Submit button wrapped in a paragraph using prepend and append\n#buttonTag(content=&quot;Submit&quot;, value=&quot;submit&quot;, prepend=&quot;&lt;p&gt;&quot;, append=&quot;&lt;/p&gt;&quot;)#\n&lt;!--- Produces: &lt;p&gt;&lt;button type=&quot;submit&quot; value=&quot;submit&quot;&gt;Submit&lt;/button&gt;&lt;/p&gt; ---&gt;\n\n// 5. Image button (renders an img tag inside the button element)\n#buttonTag(content=&quot;&quot;, image=&quot;submit-icon.png&quot;, value=&quot;save&quot;)#\n&lt;!--- Produces: &lt;button type=&quot;submit&quot; value=&quot;save&quot;&gt;&lt;img src=&quot;/images/submit-icon.png&quot; alt=&quot;Submit Icon&quot; /&gt;&lt;/button&gt; ---&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a button form control.\n\n","parameters":[{"type":"string","hint":"Content to display inside the button.","required":false,"name":"content","default":"Save changes"},{"type":"string","hint":"The type for the button: `button`, `reset`, or `submit`.","required":false,"name":"type","default":"submit"},{"type":"string","hint":"The value of the button when submitted.","required":false,"name":"value","default":"save"},{"type":"string","hint":"File name of the image file to use in the button form control.","required":false,"name":"image","default":""},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"buttonTag","tags":{"category":"General Form Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"generalformfunctions"}},{"returntype":"string","slug":"controller.buttonTo","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic button that submits to a controller/action\n#buttonTo(text=&quot;Delete Account&quot;, controller=&quot;account&quot;, action=&quot;delete&quot;)#\n&lt;!--- Outputs: &lt;form action=&quot;/account/delete&quot; method=&quot;post&quot;&gt;&lt;button type=&quot;submit&quot;&gt;Delete Account&lt;/button&gt;&lt;/form&gt; ---&gt;\n\n// 2. If you're already in the `account` controller, CFWheels will assume the current controller\n#buttonTo(text=&quot;Delete Account&quot;, action=&quot;delete&quot;)#\n&lt;!--- Outputs: &lt;form action=&quot;/account/delete&quot; method=&quot;post&quot;&gt;&lt;button type=&quot;submit&quot;&gt;Delete Account&lt;/button&gt;&lt;/form&gt; ---&gt;\n\n// 3. Use `method` to send a DELETE request (a hidden `_method` field is added automatically)\n#buttonTo(text=&quot;Remove Post&quot;, controller=&quot;blog&quot;, action=&quot;delete&quot;, key=99, method=&quot;delete&quot;)#\n&lt;!--- Outputs: &lt;form action=&quot;/blog/delete/99&quot; method=&quot;post&quot;&gt;&lt;input type=&quot;hidden&quot; name=&quot;_method&quot; value=&quot;delete&quot; /&gt;&lt;button type=&quot;submit&quot;&gt;Remove Post&lt;/button&gt;&lt;/form&gt; ---&gt;\n\n// 4. Use a named route configured in `config/routes.cfm`\n#buttonTo(text=&quot;Archive&quot;, route=&quot;archivePost&quot;, postId=12)#\n\n// 5. Show a &quot;please wait&quot; state by disabling the button on click — pass extra attributes to the button using the `input` prefix\n#buttonTo(text=&quot;Place Order&quot;, action=&quot;checkout&quot;, inputId=&quot;checkout-btn&quot;, inputClass=&quot;btn btn-primary&quot;, inputData-disable-with=&quot;Processing...&quot;)#\n\n// 6. Use an image instead of text for the button\n#buttonTo(image=&quot;icons/trash.png&quot;, action=&quot;destroy&quot;, key=params.id, method=&quot;delete&quot;)#\n</code></pre>","hasExtended":true},"hint":"Creates a form containing a single button that submits to the URL. Note: Pass any additional arguments by prefixing them with \"input\" like inputClass, inputRel, and inputId, and the generated tag will also include those values as HTML attributes.\nThe URL is built the same way as the <code>linkTo</code> function.\n\n","parameters":[{"type":"string","hint":"The text content of the button.","required":false,"name":"text","default":""},{"type":"string","hint":"If you want to use an image for the button pass in the link to it here (relative from the `images` folder).","required":false,"name":"image","default":""},{"type":"string","hint":"Name of a route that you have configured in `config/routes.cfm`.","required":false,"name":"route","default":""},{"type":"string","hint":"Name of the controller to include in the URL.","required":false,"name":"controller","default":""},{"type":"string","hint":"Name of the action to include in the URL.","required":false,"name":"action","default":""},{"type":"any","hint":"Key(s) to include in the URL.","required":false,"name":"key","default":""},{"type":"string","hint":"Any additional parameters to be set in the query string (example: `wheels=cool&x=y`). Please note that Wheels uses the `&` and `=` characters to split the parameters and encode them properly for you. However, if you need to pass in `&` or `=` as part of the value, then you need to encode them (and only them), example: `a=cats%26dogs%3Dtrouble!&b=1`.","required":false,"name":"params","default":""},{"type":"string","hint":"Sets an anchor name to be appended to the path.","required":false,"name":"anchor","default":""},{"type":"string","hint":"The type of `method` to use in the `form` tag (`delete`, `get`, `patch`, `post`, and `put` are the options).","required":false,"name":"method"},{"type":"boolean","hint":"If `true`, returns only the relative URL (no protocol, host name or port).","required":false,"name":"onlyPath","default":true},{"type":"string","hint":"Set this to override the current host.","required":false,"name":"host","default":""},{"type":"string","hint":"Set this to override the current protocol.","required":false,"name":"protocol","default":""},{"type":"numeric","hint":"Set this to override the current port number.","required":false,"name":"port","default":0},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"buttonTo","tags":{"category":"Link Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"linkfunctions"}},{"returntype":"void","slug":"controller.caches","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Cache the `termsOfUse` action for the default 60 minutes.\ncaches(&quot;termsOfUse&quot;);\n\n// 2. Cache two actions for 30 minutes.\ncaches(actions=&quot;browseByUser,browseByTitle&quot;, time=30);\n\n// 3. Cache the `termsOfUse` and `codeOfConduct` actions, including their filters.\ncaches(actions=&quot;termsOfUse,codeOfConduct&quot;, static=true);\n\n// 4. Cache content separately based on region.\ncaches(action=&quot;home&quot;, appendToKey=&quot;request.region&quot;);\n</code></pre>","hasExtended":true},"hint":"Tells Wheels to cache one or more actions.\n\n","parameters":[{"type":"string","hint":"Action(s) to cache. This argument is also aliased as `actions`.","required":false,"name":"action","default":""},{"type":"numeric","hint":"Minutes to cache the action(s) for.","required":false,"name":"time","default":60},{"type":"boolean","hint":"Set to `true` to tell Wheels that this is a static page and that it can skip running the controller filters (before and after filters set on actions). Please note that the `onSessionStart` and `onRequestStart` events still execute though.","required":false,"name":"static","default":false},{"type":"string","hint":"List of variables to be evaluated at runtime and included in the cache key so that content can be cached separately.","required":false,"name":"appendToKey","default":""}],"name":"caches","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"struct","slug":"model.callbackInfo","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Inspect all registered callbacks for a model\ninfo = model(&quot;Order&quot;).callbackInfo();\n// info is a struct keyed by callback type, each containing an array of method names:\n// {\n//   beforeSave:               [&quot;stampUpdatedAt&quot;],\n//   afterCreate:              [&quot;sendConfirmationEmail&quot;],\n//   afterSave:                [&quot;clearCacheEntries&quot;],\n//   beforeValidation:         [],\n//   beforeValidationOnCreate: [],\n//   afterValidation:          [],\n//   afterFind:                [],\n//   ...\n// }\n\n// 2. Check whether a specific callback type has any registered methods\ninfo = model(&quot;User&quot;).callbackInfo();\nif (arrayLen(info.beforeDelete)) {\n    writeOutput(&quot;User model has beforeDelete callbacks.&quot;);\n}\n\n// 3. Loop over all callback types and their methods for debugging\ninfo = model(&quot;Post&quot;).callbackInfo();\nfor (callbackType in info) {\n    for (methodName in info[callbackType]) {\n        writeOutput(callbackType &amp; &quot;: &quot; &amp; methodName);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Returns a struct containing all callback definitions for this model, keyed by callback type\n(e.g., <code>beforeSave</code>, <code>afterCreate</code>). Each callback type contains an array of callback method names.\n\n","parameters":[],"name":"callbackInfo","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.can","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Non-throwing boolean policy check for conditionals and views (views run in\nthe controller's <code>variables</code> scope, so <code>can()</code> is available in templates\nautomatically):\n<code></code><code>\n<cfif can(\"update\", post)>##linkTo(text=\"Edit\", route=\"editPost\", key=post.id)##</cfif>\n</code><code></code>\nReturns <code>false</code> (deny) for a guest, for an empty record, and for actions the\npolicy has no method for. A missing policy class still throws\n<code>Wheels.Policy.NotDefined</code> in development/testing so typos fail loud; in\nproduction it returns <code>false</code>.\n\n","parameters":[{"type":"string","hint":"The policy method to check.","required":true,"name":"action"},{"type":"any","hint":"The model instance (or model class / model name string) to check against. Empty string denies.","required":false,"name":"record","default":""}],"name":"can","tags":{"category":"Authorization Functions","sectionClass":"controller","section":"Controller","categoryClass":"authorizationfunctions"}},{"returntype":"string","slug":"controller.capitalize","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Capitalize the first character of a sentence\nresult = capitalize(&quot;wheels is a framework&quot;);\n// result -&gt; &quot;Wheels is a framework&quot;\n\n// 2. Capitalize a lowercase word\nresult = capitalize(&quot;hello&quot;);\n// result -&gt; &quot;Hello&quot;\n\n// 3. Returns an already-capitalized string unchanged\nresult = capitalize(&quot;CFWheels&quot;);\n// result -&gt; &quot;CFWheels&quot;\n</code></pre>","hasExtended":true},"hint":"Capitalizes the first character of the supplied string.\n\n","parameters":[{"type":"string","hint":"String to capitalize.","required":true,"name":"text"}],"name":"capitalize","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"void","slug":"tabledefinition.change","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Alter existing columns on a table (default behavior — modifies columns that already exist)\nt = changeTable(name='users');\n\tt.string(columnNames='email', limit=255, allowNull=false);\n\tt.boolean(columnNames='active', default=true, allowNull=false);\nt.change();\n\n// 2. Add new columns to an existing table using addColumns=true\nt = changeTable(name='products');\n\tt.string(columnNames='sku', limit=100, allowNull=false);\n\tt.decimal(columnNames='discountPrice', precision=10, scale=2, allowNull=true);\nt.change(addColumns=true);\n\n// 3. Add a foreign key reference column to an existing table\nt = changeTable(name='orders');\n\tt.references(columnNames='customer', allowNull=false);\nt.change(addColumns=true);\n</code></pre>","hasExtended":true},"hint":"alters existing table in the database\n\n","parameters":[{"type":"boolean","required":false,"name":"addColumns","default":"false"}],"name":"change","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"void","slug":"migration.changeColumn","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Change a string column's length limit\nchangeColumn(table=&quot;members&quot;, columnName=&quot;status&quot;, columnType=&quot;string&quot;, limit=50);\n\n// 2. Change a column type and set a default value\nchangeColumn(table=&quot;orders&quot;, columnName=&quot;quantity&quot;, columnType=&quot;integer&quot;, default=1);\n\n// 3. Change a decimal column with precision and scale\nchangeColumn(table=&quot;products&quot;, columnName=&quot;price&quot;, columnType=&quot;decimal&quot;, precision=10, scale=2, allowNull=false);\n\n// 4. Change a text column and explicitly allow NULL values\nchangeColumn(table=&quot;articles&quot;, columnName=&quot;summary&quot;, columnType=&quot;text&quot;, allowNull=true);\n</code></pre>","hasExtended":true},"hint":"changes a column definition\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The Name of the table where the column is","required":true,"name":"table"},{"type":"string","hint":"The name of the column","required":false,"name":"columnName"},{"type":"string","hint":"Modern alias for `columnName` (matches the plural form every TableDefinition column helper accepts). Pass one or the other — not both.","required":false,"name":"columnNames"},{"type":"string","hint":"The type of the column","required":true,"name":"columnType"},{"type":"string","hint":"The name of the column which this column should be inserted after","required":false,"name":"afterColumn","default":""},{"type":"string","hint":"Name for reference column, see documentation for references function, required if columnType is 'reference'","required":false,"name":"referenceName","default":""},{"type":"any","hint":"Default value for this column","required":false,"name":"default"},{"type":"boolean","hint":"Whether to allow NULL values","required":false,"name":"allowNull"},{"type":"numeric","hint":"Character or integer size limit for column","required":false,"name":"limit"},{"type":"numeric","hint":"(For decimal type) the maximum number of digits allow","required":false,"name":"precision"},{"type":"numeric","hint":"(For decimal type) the number of digits to the right of the decimal point","required":false,"name":"scale"},{"type":"boolean","hint":"if true, attempts to add columns and database will likely throw an error if column already exists","required":false,"name":"addColumns","default":"false"}],"name":"changeColumn","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"string","slug":"model.changedFrom","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the previous value of a changed property\nuser = model(&quot;User&quot;).findByKey(params.userId);\nuser.email = params.newEmail;\n\n// Returns the original email address before it was changed\noldEmail = user.changedFrom(&quot;email&quot;);\n// oldEmail -&gt; &quot;original@example.com&quot;\n\n// 2. Use the dynamic shorthand method (equivalent to the above)\noldEmail = user.emailChangedFrom();\n\n// 3. Check if a property changed before accessing the previous value\nuser = model(&quot;User&quot;).findByKey(params.userId);\nuser.firstName = params.firstName;\n\nif (user.hasChanged(&quot;firstName&quot;)) {\n\toldName = user.changedFrom(&quot;firstName&quot;);\n\t// oldName -&gt; &quot;Jane&quot;\n}\n// Returns empty string if property has not changed or no previous value exists\n</code></pre>","hasExtended":true},"hint":"Returns the previous value of a property that has changed.\nReturns an empty string if no previous value exists.\nWheels will keep a note of the previous property value until the object is saved to the database.\n\n","parameters":[{"type":"string","hint":"Name of property to get the previous value for.","required":true,"name":"property"}],"name":"changedFrom","tags":{"category":"Change Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"changefunctions"}},{"returntype":"string","slug":"model.changedProperties","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Find a member, change some properties, then inspect which ones have changed\nmember = model(&quot;member&quot;).findByKey(params.memberId);\nmember.firstName = params.newFirstName;\nmember.email = params.newEmail;\nchanged = member.changedProperties();\n// changed -&gt; &quot;firstName,email&quot;\n\n// 2. Only save when there are actually unsaved changes\nuser = model(&quot;User&quot;).findByKey(params.userId);\nuser.lastName = params.lastName;\nif (Len(user.changedProperties())) {\n    user.save();\n}\n\n// 3. Use changedProperties() alongside changedFrom() to build an audit log entry\npost = model(&quot;Post&quot;).findByKey(params.postId);\npost.title = params.title;\npost.body = params.body;\nchangedList = post.changedProperties();\nfor (prop in ListToArray(changedList)) {\n    writeOutput(&quot;Property '#prop#' was '#post.changedFrom(prop)#', now '#post[prop]#'.&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Returns a list of the object properties that have been changed but not yet saved to the database.\n\n","parameters":[],"name":"changedProperties","tags":{"category":"Change Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"changefunctions"}},{"returntype":"TableDefinition","slug":"migration.changeTable","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a new string column to an existing table\nt = changeTable(name=&quot;employees&quot;);\nt.string(columnNames=&quot;fullName&quot;, default=&quot;&quot;, allowNull=true, limit=255);\nt.change();\n\n// 2. Modify multiple columns at once (change type and nullability)\nt = changeTable(name=&quot;products&quot;);\nt.integer(columnNames=&quot;stock&quot;, default=0, allowNull=false);\nt.boolean(columnNames=&quot;active&quot;, default=true, allowNull=false);\nt.change();\n\n// 3. Add a new column using addColumns=true so the migration fails gracefully if the column already exists\nt = changeTable(name=&quot;orders&quot;);\nt.datetime(columnNames=&quot;shippedAt&quot;, allowNull=true);\nt.change(addColumns=true);\n</code></pre>","hasExtended":true},"hint":"Creates a table definition object to store modifications to table properties\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"Name of the table to set change properties on","required":true,"name":"name"}],"name":"changeTable","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"string","slug":"controller.channelSSETag","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Generate a 'script' tag that creates an EventSource for a channel.\nConvenience view helper for quickly wiring up SSE in templates.","parameters":[{"type":"string","hint":"The channel name.","required":true,"name":"channel"},{"type":"string","hint":"Named route for the SSE endpoint.","required":false,"name":"route","default":""},{"type":"string","hint":"Controller name (used with action if no route).","required":false,"name":"controller","default":""},{"type":"string","hint":"Action name (default \"stream\").","required":false,"name":"action","default":"stream"},{"type":"string","hint":"Comma-delimited list of event types.","required":false,"name":"events","default":""}],"name":"channelSSETag","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"any","slug":"tabledefinition.char","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single char column to a new table\nt = createTable(name='countries');\n\tt.char(columnNames='code', limit=2, allowNull=false);\n\tt.string(columnNames='name', limit=100, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple char columns at once\nt = createTable(name='products');\n\tt.char(columnNames='sku,barcode', limit=12, allowNull=false);\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a char column with a default value when altering an existing table\nt = changeTable(name='orders');\n\tt.char(columnNames='statusCode', limit=1, default='N', allowNull=false);\nt.change();\n</code></pre>","hasExtended":true},"hint":"adds char columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"limit"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"char","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"controller.checkBox","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic check box bound to a boolean model property\n#checkBox(objectName=&quot;photo&quot;, property=&quot;isPublic&quot;, label=&quot;Display this photo publicly.&quot;)#\n\n// 2. Custom checked and unchecked values (e.g. &quot;yes&quot; / &quot;no&quot; instead of 1 / 0)\n#checkBox(objectName=&quot;user&quot;, property=&quot;agreedToTerms&quot;, checkedValue=&quot;yes&quot;, uncheckedValue=&quot;no&quot;, label=&quot;I agree to the terms of service.&quot;)#\n\n// 3. Check boxes for a nested association (photos belonging to a user)\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(user.photos)#&quot; index=&quot;i&quot;&gt;\n    #checkBox(objectName=&quot;user&quot;, association=&quot;photos&quot;, position=i, property=&quot;isPublic&quot;, label=&quot;Make public: #user.photos[i].title#&quot;)#\n&lt;/cfloop&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a check box form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"Value of check box in its checked state.","required":false,"name":"checkedValue","default":1},{"type":"string","hint":"The value of the check box when it's on the unchecked state.","required":false,"name":"uncheckedValue","default":0},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"checkBox","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.checkBoxTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage with a label and a pre-checked state\n&lt;cfoutput&gt;\n\t#checkBoxTag(name=&quot;subscribe&quot;, value=&quot;1&quot;, label=&quot;Subscribe to our newsletter&quot;, checked=true)#\n&lt;/cfoutput&gt;\n\n// 2. Render an unchecked check box that also submits a value when unchecked\n&lt;cfoutput&gt;\n\t#checkBoxTag(name=&quot;agreeToTerms&quot;, value=&quot;1&quot;, uncheckedValue=&quot;0&quot;, label=&quot;I agree to the terms&quot;)#\n&lt;/cfoutput&gt;\n\n// 3. Loop over a query to render one check box per option, checking those already selected\n// Controller\ntoppings = model(&quot;Topping&quot;).findAll(order=&quot;name&quot;);\nselectedIds = &quot;2,5,9&quot;; // e.g. previously saved topping IDs as a comma-delimited list\n\n// View\n&lt;cfoutput query=&quot;toppings&quot;&gt;\n\t#checkBoxTag(\n\t\tname    = &quot;toppingIds&quot;,\n\t\tvalue   = toppings.id,\n\t\tlabel   = toppings.name,\n\t\tchecked = listFindNoCase(selectedIds, toppings.id) GT 0\n\t)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a check box form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"boolean","hint":"Whether or not the check box should be checked by default.","required":false,"name":"checked","default":false},{"type":"string","hint":"Value of check box in its checked state.","required":false,"name":"value","default":1},{"type":"string","hint":"The value of the check box when it's on the unchecked state.","required":false,"name":"uncheckedValue","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"checkBoxTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"struct","slug":"model.classInfo","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Inspect all metadata for the User model\ninfo = model(&quot;User&quot;).classInfo();\n// info.modelName             -&gt; &quot;User&quot;\n// info.tableName             -&gt; &quot;users&quot;\n// info.primaryKeys           -&gt; &quot;id&quot;\n// info.propertyNames         -&gt; &quot;id,firstName,lastName,email,createdAt,updatedAt&quot;\n// info.properties            -&gt; struct of column/type metadata keyed by property name\n// info.calculatedProperties  -&gt; struct of SQL-expression properties keyed by property name\n// info.associations          -&gt; struct of association definitions (belongsTo, hasMany, etc.)\n// info.validations           -&gt; struct keyed by trigger (onSave, onCreate, onUpdate) with arrays of rules\n// info.enums                 -&gt; struct of enum definitions keyed by property name\n// info.scopes                -&gt; struct of named scope definitions\n// info.callbacks             -&gt; struct of callback arrays keyed by callback type (beforeSave, afterCreate, etc.)\n// info.softDeletion          -&gt; false (true when the model has a deletedAt column)\n\n// 2. List all association names and their types\ninfo = model(&quot;Article&quot;).classInfo();\n\nfor (assocName in info.associations) {\n    assoc = info.associations[assocName];\n    writeOutput(assocName &amp; &quot; (&quot; &amp; assoc.type &amp; &quot;)&quot;);\n}\n\n// 3. Check soft-deletion and enumerate registered callbacks\ninfo = model(&quot;Post&quot;).classInfo();\n\nif (info.softDeletion) {\n    writeOutput(&quot;Post uses soft deletion.&quot;);\n}\n\nfor (callbackType in info.callbacks) {\n    methods = info.callbacks[callbackType];\n    writeOutput(callbackType &amp; &quot;: &quot; &amp; arrayToList(methods));\n}\n\n// 4. Inspect calculated properties defined on the model\ninfo = model(&quot;Order&quot;).classInfo();\n\nfor (propName in info.calculatedProperties) {\n    calcProp = info.calculatedProperties[propName];\n    writeOutput(propName &amp; &quot; =&gt; &quot; &amp; calcProp.sql);\n}\n</code></pre>","hasExtended":true},"hint":"Returns a comprehensive struct of all model metadata suitable for code generation and introspection tools.\nIncludes model name, table name, primary keys, properties, associations, validations, enums, scopes, and callbacks.\n\n","parameters":[],"name":"classInfo","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"controller.clearCachableActions","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Clear all cached action metadata for the current controller.\nclearCachableActions();\n\n// 2. Clear the cached metadata for a single action.\nclearCachableActions(action=&quot;termsOfUse&quot;);\n\n// 3. Clear the cached metadata for a list of specific actions.\nclearCachableActions(action=&quot;browseByUser,browseByTitle&quot;);\n</code></pre>","hasExtended":true},"hint":"Clears cached action metadata for current controller.\n\n","parameters":[{"type":"string","hint":"Optional. A single action or list of actions to clear. If not provided, clears all cached actions of current controller.","required":false,"name":"action","default":""}],"name":"clearCachableActions","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"void","slug":"model.clearChangeInformation","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Clear change tracking for a single property\n// Convert startTime to UTC in an afterFind callback, then tell Wheels to treat\n// the converted value as the &quot;original&quot; so it won't be flagged as changed or\n// saved unnecessarily.\nthis.startTime = dateConvert(&quot;Local2UTC&quot;, this.startTime);\nthis.clearChangeInformation(property=&quot;startTime&quot;);\n\n// 2. Clear change tracking for all properties at once\n// After manually adjusting values in an afterFind callback, reset Wheels'\n// internal state so none of the touched properties appear as dirty.\nthis.clearChangeInformation();\n\n// 3. Typical afterFind callback usage in a model\n// In User.cfc config():\n//   afterFind(&quot;normalizeTimestamps&quot;);\n// The callback method:\nfunction normalizeTimestamps() {\n    if (structKeyExists(this, &quot;createdAt&quot;)) {\n        this.createdAt = dateConvert(&quot;Local2UTC&quot;, this.createdAt);\n    }\n    if (structKeyExists(this, &quot;updatedAt&quot;)) {\n        this.updatedAt = dateConvert(&quot;Local2UTC&quot;, this.updatedAt);\n    }\n    // Mark both properties as clean so hasChanged() returns false\n    // and save() won't push them back to the database.\n    this.clearChangeInformation(property=&quot;createdAt&quot;);\n    this.clearChangeInformation(property=&quot;updatedAt&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Clears all internal knowledge of the current state of the object.\n\n","parameters":[{"type":"string","hint":"string false Name of property to clear information for.","required":false,"name":"property"}],"name":"clearChangeInformation","tags":{"category":"Change Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"changefunctions"}},{"returntype":"void","slug":"model.clearErrors","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Clear all errors on the object\nthis.clearErrors();\n\n// 2. Clear all errors set on the `firstName` property\nthis.clearErrors(property=&quot;firstName&quot;);\n\n// 3. Clear only errors that were set with a specific error name\nthis.clearErrors(name=&quot;invalidFormat&quot;);\n\n// 4. Clear errors on a specific property that were also set with a specific name\nthis.clearErrors(property=&quot;email&quot;, name=&quot;duplicateEmail&quot;);\n</code></pre>","hasExtended":true},"hint":"Clears out all errors set on the object or only the ones set for a specific property or name.\n\n","parameters":[{"type":"string","hint":"Specify a property name here if you want to clear all errors set on that property.","required":false,"name":"property","default":""},{"type":"string","hint":"Specify an error name here if you want to clear all errors set with that error name.","required":false,"name":"name","default":""}],"name":"clearErrors","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"void","slug":"controller.closeSSEStream","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Close an SSE streaming connection.","parameters":[{"type":"any","hint":"The writer object returned by initSSEStream().","required":true,"name":"writer"}],"name":"closeSSEStream","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"struct","slug":"mapper.collection","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\n// 1. Add a search route acting on the photos collection (GET /photos/search)\nmapper()\n    .resources(name=&quot;photos&quot;, nested=true)\n        .collection()\n            .get(&quot;search&quot;)\n        .end()\n    .end()\n.end();\n\n// 2. Add multiple collection routes (GET /articles/featured, POST /articles/bulk-delete)\nmapper()\n    .resources(name=&quot;articles&quot;, nested=true)\n        .collection()\n            .get(&quot;featured&quot;)\n            .post(&quot;bulkDelete&quot;)\n        .end()\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"A collection route doesn't require an id because it acts on a collection of objects.\nphotos/search is an example of a collection route, because it acts on (and displays) a collection of objects.\n\n","parameters":[],"name":"collection","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.colorField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic color picker bound to a model object property\n#colorField(objectName=&quot;product&quot;, property=&quot;themeColor&quot;)#\n\n// 2. Color picker with a custom label and a CSS class\n#colorField(objectName=&quot;user&quot;, property=&quot;profileColor&quot;, label=&quot;Profile Color&quot;, class=&quot;color-picker&quot;)#\n\n// 3. Color pickers for nested properties on a hasMany association (e.g., palette swatches)\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(design.swatches)#&quot; index=&quot;i&quot;&gt;\n\t#colorField(objectName=&quot;design&quot;, association=&quot;swatches&quot;, position=&quot;#i#&quot;, property=&quot;hexValue&quot;, label=&quot;Swatch ##i#&quot;)#\n&lt;/cfloop&gt;</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a color picker form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"colorField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.colorFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic color picker with a default value\n#colorFieldTag(name=&quot;brandColor&quot;, value=&quot;##FF5733&quot;)#\n\n// 2. Color picker with a label and a CSS class\n#colorFieldTag(name=&quot;themeColor&quot;, value=&quot;##336699&quot;, label=&quot;Theme Color&quot;, class=&quot;color-input&quot;)#\n\n// 3. Color picker with label placement and prepend/append wrappers\n#colorFieldTag(name=&quot;highlightColor&quot;, label=&quot;Highlight&quot;, labelPlacement=&quot;before&quot;, prepend=&quot;&lt;div class=&quot;&quot;field&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a color picker form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"colorFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"any","slug":"tabledefinition.column","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a generic string column to a new table\nt = createTable(name='articles');\n\tt.column(columnName='title', columnType='string', limit=255, allowNull=false);\n\tt.column(columnName='body', columnType='text');\n\tt.timestamps();\nt.create();\n\n// 2. Add a column with a default value and precision/scale (for decimals)\nt = createTable(name='products');\n\tt.column(columnName='name', columnType='string', limit=100, allowNull=false);\n\tt.column(columnName='price', columnType='decimal', precision=10, scale=2, default='0.00', allowNull=false);\n\tt.column(columnName='stock', columnType='integer', default='0', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a custom column when altering an existing table\nt = changeTable(name='users');\n\tt.column(columnName='bio', columnType='text', allowNull=true);\nt.change();\n</code></pre>","hasExtended":true},"hint":"Adds a column to table definition.\n\n","parameters":[{"type":"string","required":true,"name":"columnName"},{"type":"string","required":true,"name":"columnType"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"},{"type":"any","required":false,"name":"limit"},{"type":"numeric","required":false,"name":"precision"},{"type":"numeric","required":false,"name":"scale"}],"name":"column","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"any","slug":"model.columnDataForProperty","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all column metadata for a property\ndata = model(&quot;User&quot;).columnDataForProperty(&quot;email&quot;);\n// Returns a struct like:\n// { column: &quot;email&quot;, validationtype: &quot;string&quot;, label: &quot;Email&quot; }\n\n// 2. Inspect metadata before using it\ndata = model(&quot;Product&quot;).columnDataForProperty(&quot;price&quot;);\nif (isStruct(data)) {\n    writeOutput(&quot;Column: &quot; &amp; data.column);\n    writeOutput(&quot;Validation type: &quot; &amp; data.validationtype);\n}\n\n// 3. Handle the false return when the property does not exist on the model\ndata = model(&quot;User&quot;).columnDataForProperty(&quot;nonExistentProp&quot;);\nif (!isStruct(data)) {\n    writeOutput(&quot;Property not found on this model.&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Returns a struct with data for the named property.\n\n","parameters":[{"type":"string","hint":"Name of property to inspect.","required":true,"name":"property"}],"name":"columnDataForProperty","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"model.columnForProperty","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the column name mapped to a model property\ncol = model(&quot;User&quot;).columnForProperty(&quot;firstName&quot;);\n// col -&gt; &quot;first_name&quot;\n\n// 2. Check the column for a property before building a raw SQL fragment\ncol = model(&quot;Order&quot;).columnForProperty(&quot;placedAt&quot;);\nif (col != false) {\n    writeOutput(&quot;Column in the database: &quot; &amp; col);\n}\n\n// 3. Returns false when the property does not exist on the model\ncol = model(&quot;User&quot;).columnForProperty(&quot;nonExistentProperty&quot;);\n// col -&gt; false\n</code></pre>","hasExtended":true},"hint":"Returns the column name mapped for the named model property.\n\n","parameters":[{"type":"string","hint":"Name of property to inspect.","required":true,"name":"property"}],"name":"columnForProperty","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"model.columnNames","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the list of column names for the User model\ncols = model(&quot;User&quot;).columnNames();\n// cols -&gt; &quot;id,firstName,lastName,email,createdAt,updatedAt,deletedAt&quot;\n\n// 2. Check whether a specific column exists in the table\nif (listFindNoCase(model(&quot;User&quot;).columnNames(), &quot;email&quot;)) {\n    writeOutput(&quot;The users table has an email column.&quot;);\n}\n\n// 3. Iterate over every column name\nfor (col in listToArray(model(&quot;User&quot;).columnNames())) {\n    writeOutput(col);\n}\n</code></pre>","hasExtended":true},"hint":"Returns a list of column names in the table mapped to this model.\nThe list is ordered according to the columns' ordinal positions in the database table.\n\n","parameters":[],"name":"columnNames","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"array","slug":"model.columns","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all column names for the User model\ncols = model(&quot;User&quot;).columns();\n// cols -&gt; [&quot;id&quot;, &quot;firstName&quot;, &quot;lastName&quot;, &quot;email&quot;, &quot;createdAt&quot;, &quot;updatedAt&quot;, &quot;deletedAt&quot;]\n\n// 2. Check whether a specific column exists in the table\ncols = model(&quot;User&quot;).columns();\nif (arrayFindNoCase(cols, &quot;deletedAt&quot;)) {\n    writeOutput(&quot;Soft-delete column is present&quot;);\n}\n\n// 3. Iterate over all columns and output their names\ncols = model(&quot;User&quot;).columns();\nfor (col in cols) {\n    writeOutput(col);\n}\n</code></pre>","hasExtended":true},"hint":"Returns an array of columns names for the table associated with this class.\nDoes not include calculated properties that will be generated by the Wheels ORM.\n\n","parameters":[],"name":"columns","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"model.compareTo","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if two model objects are the same instance\nuser1 = model(&quot;User&quot;).findByKey(1);\nuser2 = model(&quot;User&quot;).findByKey(1);\nuser3 = user1;\n\nisSame = user1.compareTo(user2);\n// isSame -&gt; false (two separate fetches produce distinct instances)\n\nisSame = user1.compareTo(user3);\n// isSame -&gt; true (user3 is the same object reference as user1)\n\n// 2. Guard against processing the same object twice in a loop\nusers = model(&quot;User&quot;).findAll(returnAs=&quot;objects&quot;);\ncurrentUser = model(&quot;User&quot;).findByKey(session.userId);\n\nfor (u in users) {\n    if (!u.compareTo(currentUser)) {\n        // process all users except the currently logged-in one\n        sendNotification(u);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Pass in another model object to see if the two objects are the same.\n\n","parameters":[{"type":"component","required":true,"name":"object"}],"name":"compareTo","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"struct","slug":"mapper.constraints","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Constrain a dynamic segment to digits only\n    .constraints(id=&quot;[0-9]+&quot;)\n        .resources(name=&quot;articles&quot;)\n    .end()\n\n    // 2. Constrain multiple segments — numeric id and lowercase-only slug\n    .constraints(id=&quot;[0-9]+&quot;, slug=&quot;[a-z\\-]+&quot;)\n        .get(name=&quot;article&quot;, to=&quot;articles##show&quot;)\n        .get(name=&quot;articleBySlug&quot;, to=&quot;articles##showBySlug&quot;)\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Set variable patterns to use for matching.\n\n","parameters":[],"name":"constraints","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"void","slug":"controller.contentFor","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Store sidebar content for use in the layout\n&lt;cfsavecontent variable=&quot;mySidebar&quot;&gt;\n  &lt;nav&gt;Recent Posts&lt;/nav&gt;\n&lt;/cfsavecontent&gt;\n&lt;cfset contentFor(sidebar=mySidebar)&gt;\n\n&lt;!--- In your layout, output the stored section ---&gt;\n&lt;cfoutput&gt;\n  #includeContent(&quot;sidebar&quot;)#\n  #includeContent()#\n&lt;/cfoutput&gt;\n\n// 2. Push content onto a stack — multiple calls append by default\n&lt;cfsavecontent variable=&quot;firstScript&quot;&gt;\n  &lt;script src=&quot;/js/base.js&quot;&gt;&lt;/script&gt;\n&lt;/cfsavecontent&gt;\n&lt;cfset contentFor(scripts=firstScript)&gt;\n\n&lt;cfsavecontent variable=&quot;secondScript&quot;&gt;\n  &lt;script src=&quot;/js/page.js&quot;&gt;&lt;/script&gt;\n&lt;/cfsavecontent&gt;\n&lt;cfset contentFor(scripts=secondScript)&gt;\n\n&lt;!--- Both scripts are rendered in order ---&gt;\n&lt;cfoutput&gt;#includeContent(&quot;scripts&quot;)#&lt;/cfoutput&gt;\n\n// 3. Prepend content to an existing section using position=&quot;first&quot;\n&lt;cfsavecontent variable=&quot;criticalScript&quot;&gt;\n  &lt;script src=&quot;/js/critical.js&quot;&gt;&lt;/script&gt;\n&lt;/cfsavecontent&gt;\n&lt;cfset contentFor(position=&quot;first&quot;, scripts=criticalScript)&gt;\n\n// 4. Overwrite an entire section with overwrite=&quot;all&quot;\n&lt;cfsavecontent variable=&quot;replacementSidebar&quot;&gt;\n  &lt;nav&gt;Admin Sidebar&lt;/nav&gt;\n&lt;/cfsavecontent&gt;\n&lt;cfset contentFor(overwrite=&quot;all&quot;, sidebar=replacementSidebar)&gt;\n\n// 5. Overwrite a specific position in the stack (position=1, overwrite=true)\n&lt;cfsavecontent variable=&quot;updatedScript&quot;&gt;\n  &lt;script src=&quot;/js/updated.js&quot;&gt;&lt;/script&gt;\n&lt;/cfsavecontent&gt;\n&lt;cfset contentFor(position=1, overwrite=true, scripts=updatedScript)&gt;\n</code></pre>","hasExtended":true},"hint":"Used to store a section's output for rendering within a layout.\nThis content store acts as a stack, so you can store multiple pieces of content for a given section.\n\n","parameters":[{"type":"any","hint":"The position in the section's stack where you want the content placed. Valid values are `first`, `last`, or the numeric position.","required":false,"name":"position","default":"last"},{"type":"any","hint":"Whether or not to overwrite any of the content. Valid values are `false`, `true`, or `all`.","required":false,"name":"overwrite","default":"false"}],"name":"contentFor","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.contentForLayout","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Include the view's generated content inside a layout file\n// In `app/views/layout.cfm`, place this where the page body should appear\n&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;My App&lt;/title&gt;\n&lt;/head&gt;\n&lt;body&gt;\n    #contentForLayout()#\n&lt;/body&gt;\n&lt;/html&gt;\n\n// 2. Combine with includeContent to render named sections alongside the body\n// In `app/views/layout.cfm`\n&lt;html&gt;\n&lt;head&gt;\n    #includeContent(&quot;head&quot;)#\n&lt;/head&gt;\n&lt;body&gt;\n    #contentForLayout()#\n    #includeContent(&quot;footer&quot;)#\n&lt;/body&gt;\n&lt;/html&gt;\n</code></pre>","hasExtended":true},"hint":"Includes content for the body section, which equates to the output generated by the view template run by the request.\n\n","parameters":[],"name":"contentForLayout","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"struct","slug":"mapper.controller","availableIn":["mapper"],"extended":{"docs":"","hasExtended":false},"hint":"Considered deprecated as this doesn't conform to RESTful routing principles; Try not to use this.\n\n","parameters":[{"type":"string","required":true,"name":"controller"},{"type":"string","required":false,"name":"name","default":"[runtime expression]"},{"type":"string","required":false,"name":"path","default":"[runtime expression]"}],"name":"controller","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"any","slug":"controller.controller","availableIn":["controller","model","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Create a controller object for testing (no params)\nusersController = controller(&quot;users&quot;);\n\n// 2. Create a controller object with simulated request params for testing\nparams = {controller = &quot;users&quot;, action = &quot;show&quot;, key = 1};\nusersController = controller(name = &quot;users&quot;, params = params);\n\n// 3. Use with processAction to test an action end-to-end\nparams = {controller = &quot;users&quot;, action = &quot;index&quot;};\nusersController = controller(name = &quot;users&quot;, params = params);\nusersController.processAction();\nbody = usersController.response();\n</code></pre>","hasExtended":true},"hint":"Creates and returns a controller object with your own custom name and params.\nUsed primarily for testing purposes.\n\n","parameters":[{"type":"string","hint":"Name of the controller to create.","required":true,"name":"name"},{"type":"struct","hint":"The params struct (combination of form and URL variables).","required":false,"name":"params","default":"[runtime expression]"}],"name":"controller","tags":{"category":"Miscellaneous Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"model.count","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Count all rows in the authors table\nauthorCount = model(&quot;author&quot;).count();\n\n// 2. Count authors whose last name starts with &quot;A&quot;\nauthorOnACount = model(&quot;author&quot;).count(where=&quot;lastName LIKE 'A%'&quot;);\n\n// 3. Count authors who have written books with titles starting with &quot;A&quot; (requires a hasMany association from author to book)\nauthorWithBooksOnACount = model(&quot;author&quot;).count(include=&quot;books&quot;, where=&quot;books.title LIKE 'A%'&quot;);\n\n// 4. Count posts grouped by status, returning a query with one row per status\nstatusCounts = model(&quot;post&quot;).count(group=&quot;status&quot;);\n// statusCounts is a query with columns: count, status\n\n// 5. Count the number of comments on a specific post using a dynamic counter method\n// (requires a hasMany association from post to comment)\naPost = model(&quot;post&quot;).findByKey(params.postId);\ncommentCount = aPost.commentCount();\n</code></pre>","hasExtended":true},"hint":"Returns the number of rows that match the arguments (or all rows if no arguments are passed in).\nUses the SQL function <code>COUNT</code>.\nIf no records can be found to perform the calculation on, <code>0</code> is returned.\n\n","parameters":[{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"},{"type":"string","hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"group"}],"name":"count","tags":{"category":"Statistics Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"statisticsfunctions"}},{"returntype":"void","slug":"tabledefinition.create","availableIn":["tabledefinition"],"extended":{"docs":"","hasExtended":false},"hint":"creates the table in the database\n\n","parameters":[],"name":"create","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"any","slug":"model.create","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Create a new author and save it to the database\nnewAuthor = model(&quot;author&quot;).create(params.author);\n\n// 2. Create using named arguments\nnewAuthor = model(&quot;author&quot;).create(firstName=&quot;John&quot;, lastName=&quot;Doe&quot;);\n\n// 3. Merge named arguments with a properties struct\nnewAuthor = model(&quot;author&quot;).create(active=1, properties=params.author);\n\n// 4. Skip validation when creating (e.g. for seeding trusted data)\nnewAuthor = model(&quot;author&quot;).create(properties=params.author, validate=false);\n\n// 5. Create inside a transaction that is rolled back (useful for dry-run testing)\nnewAuthor = model(&quot;author&quot;).create(properties=params.author, transaction=&quot;rollback&quot;);\n\n// 6. Allow explicit createdAt / updatedAt values when importing legacy data\nnewAuthor = model(&quot;author&quot;).create(\n\tfirstName=&quot;Jane&quot;,\n\tlastName=&quot;Smith&quot;,\n\tcreatedAt=&quot;2020-01-15 08:00:00&quot;,\n\tallowExplicitTimestamps=true\n);\n\n// 7. Scoped create via a hasOne / hasMany association\n// (calls model(&quot;order&quot;).create(customerId=aCustomer.id, shipping=params.shipping) internally)\naCustomer = model(&quot;customer&quot;).findByKey(params.customerId);\nanOrder = aCustomer.createOrder(shipping=params.shipping);\n</code></pre>","hasExtended":true},"hint":"Creates a new object, saves it to the database (if the validation permits it), and returns it.\nIf the validation fails, the unsaved object (with errors added to it) is still returned.\nProperty names and values can be passed in either using named arguments or as a struct to the <code>properties</code> argument.\n\n","parameters":[{"type":"struct","hint":"The properties you want to set on the object (can also be passed in as named arguments).","required":false,"name":"properties","default":"[runtime expression]"},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"boolean","hint":"Set to `false` to skip validations for this operation.","required":false,"name":"validate","default":true},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":true},{"type":"boolean","hint":"Set this to `true` to allow explicit assignment of `createdAt` or `updatedAt` properties","required":false,"name":"allowExplicitTimestamps","default":false}],"name":"create","tags":{"category":"Create Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"createfunctions"}},{"returntype":"string","slug":"migrator.createMigration","availableIn":["migrator"],"extended":{"docs":"<pre><code class='javascript'>// 1. Create a blank migration file (uses timestamp prefix by default)\nresult = application.wheels.migrator.createMigration(&quot;CreateUsersTable&quot;);\n// result -&gt; &quot;The migration 20240815123045_CreateUsersTable.cfc file was created&quot;\n\n// 2. Create a migration from a built-in template (e.g. create-table)\nresult = application.wheels.migrator.createMigration(\n\tmigrationName=&quot;CreatePostsTable&quot;,\n\ttemplateName=&quot;create-table&quot;\n);\n\n// 3. Create a migration using a sequential numeric prefix instead of a timestamp\nresult = application.wheels.migrator.createMigration(\n\tmigrationName=&quot;AddIndexToUsers&quot;,\n\tmigrationPrefix=&quot;numeric&quot;\n);\n// result -&gt; &quot;The migration 001_AddIndexToUsers.cfc file was created&quot;\n</code></pre>","hasExtended":true},"hint":"Creates a migration file. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n","parameters":[{"type":"string","required":true,"name":"migrationName"},{"type":"string","required":false,"name":"templateName","default":""},{"type":"string","required":false,"name":"migrationPrefix","default":"timestamp"}],"name":"createMigration","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"TableDefinition","slug":"migration.createTable","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Create a users table with standard columns and timestamps\nt = createTable(name=&quot;users&quot;);\n\tt.string(columnNames=&quot;firstName,lastName&quot;, default=&quot;&quot;, allowNull=false, limit=50);\n\tt.string(columnNames=&quot;email&quot;, default=&quot;&quot;, allowNull=false, limit=255);\n\tt.string(columnNames=&quot;passwordHash&quot;, default=&quot;&quot;, allowNull=true, limit=500);\n\tt.boolean(columnNames=&quot;verified&quot;, default=false);\n\tt.integer(columnNames=&quot;roleId&quot;, default=0, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Create a table with a custom string primary key (disabling the auto integer id)\nt = createTable(name=&quot;tokens&quot;, id=false);\n\tt.primaryKey(name=&quot;id&quot;, allowNull=false, type=&quot;string&quot;, limit=36);\n\tt.string(columnNames=&quot;userId&quot;, allowNull=false, limit=36);\n\tt.datetime(columnNames=&quot;expiresAt&quot;, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Create a join table with composite primary keys and force=true to recreate if it already exists\nt = createTable(name=&quot;userRoles&quot;, id=false, force=true);\n\tt.primaryKey(name=&quot;userId&quot;, allowNull=false, limit=11);\n\tt.primaryKey(name=&quot;roleId&quot;, allowNull=false, limit=11);\nt.create();\n</code></pre>","hasExtended":true},"hint":"Creates a table definition object to store table properties\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The name of the table to create","required":true,"name":"name"},{"type":"boolean","hint":"whether to drop the table before creating it","required":false,"name":"force","default":"false"},{"type":"boolean","hint":"Whether to create a default primarykey or not","required":false,"name":"id","default":"true"},{"type":"string","hint":"Name of the primary key field to create","required":false,"name":"primaryKey","default":"id"}],"name":"createTable","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"ViewDefinition","slug":"migration.createView","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Create a simple database view that joins users and roles\nv = createView(name=&quot;userRoles&quot;);\nv.selectStatement(sql=&quot;SELECT u.id, u.firstName, u.lastName, r.name AS roleName FROM users u INNER JOIN roles r ON u.roleId = r.id&quot;);\nv.create();\n\n// 2. Create a view for active (non-deleted) users using method chaining\ncreateView(name=&quot;activeUsers&quot;)\n    .selectStatement(sql=&quot;SELECT id, firstName, lastName, email FROM users WHERE deletedAt IS NULL&quot;)\n    .create();\n\n// 3. Full up/down migration using createView and dropView\ncomponent extends=&quot;wheels.migrator.Migration&quot; {\n    function up() {\n        createView(name=&quot;publishedArticles&quot;)\n            .selectStatement(sql=&quot;SELECT id, title, body, authorId, publishedAt FROM articles WHERE publishedAt IS NOT NULL&quot;)\n            .create();\n    }\n    function down() {\n        dropView(name=&quot;publishedArticles&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Creates a view definition object to store view properties\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"Name of the view to change properties on","required":true,"name":"name"}],"name":"createView","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"string","slug":"controller.csrfMetaTags","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Include CSRF meta tags in your layout's &lt;head&gt; section\n//    so that JavaScript AJAX requests can read the token and send it\n//    as a request header when POSTing data to your application.\n&lt;head&gt;\n  &lt;title&gt;My App&lt;/title&gt;\n  #csrfMetaTags()#\n&lt;/head&gt;\n\n// 2. Reading the token in JavaScript (e.g. with fetch) using the meta tags above\n//    The rendered HTML will contain two meta tags like:\n//    &lt;meta name=&quot;csrf-param&quot; content=&quot;authenticityToken&quot;&gt;\n//    &lt;meta name=&quot;csrf-token&quot; content=&quot;&lt;generated-token&gt;&quot;&gt;\n//\n//    In your JavaScript you can then do:\n//    const token = document.querySelector('meta[name=&quot;csrf-token&quot;]').getAttribute('content');\n//    fetch('/posts', { method: 'POST', headers: { 'authenticityToken': token }, body: ... });\n</code></pre>","hasExtended":true},"hint":"Include this in your layouts' <code>head</code> sections to include meta tags containing the authenticity token for use by JavaScript AJAX requests needing to <code>POST</code> data to your application.\n\n","parameters":[],"name":"csrfMetaTags","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.cycle","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Alternate CSS classes on table rows\n// Outputs &quot;odd&quot; on the first row, &quot;even&quot; on the second, &quot;odd&quot; on the third, etc.\n&lt;table&gt;\n\t&lt;thead&gt;\n\t\t&lt;tr&gt;\n\t\t\t&lt;th&gt;Name&lt;/th&gt;\n\t\t\t&lt;th&gt;Phone&lt;/th&gt;\n\t\t&lt;/tr&gt;\n\t&lt;/thead&gt;\n\t&lt;tbody&gt;\n\t\t&lt;cfoutput query=&quot;employees&quot;&gt;\n\t\t\t&lt;tr class=&quot;#cycle(&quot;odd,even&quot;)#&quot;&gt;\n\t\t\t\t&lt;td&gt;#employees.name#&lt;/td&gt;\n\t\t\t\t&lt;td&gt;#employees.phone#&lt;/td&gt;\n\t\t\t&lt;/tr&gt;\n\t\t&lt;/cfoutput&gt;\n\t&lt;/tbody&gt;\n&lt;/table&gt;\n\n// 2. Use named cycles when running multiple cycles simultaneously\n// Cycle &quot;row&quot; and &quot;highlight&quot; advance independently\n&lt;cfoutput query=&quot;employees&quot;&gt;\n\t&lt;cfset rowClass = cycle(values=&quot;even,odd&quot;, name=&quot;row&quot;)&gt;\n\t&lt;cfset hlClass = cycle(values=&quot;highlight,normal,normal&quot;, name=&quot;highlight&quot;)&gt;\n\t&lt;tr class=&quot;#rowClass# #hlClass#&quot;&gt;\n\t\t&lt;td&gt;#employees.name#&lt;/td&gt;\n\t&lt;/tr&gt;\n&lt;/cfoutput&gt;\n\n// 3. Reset a cycle so it starts over from the first value\n&lt;cfoutput query=&quot;departments&quot; group=&quot;departmentId&quot;&gt;\n\t&lt;div class=&quot;#cycle(values=&quot;even,odd&quot;, name=&quot;row&quot;)#&quot;&gt;\n\t\t&lt;ul&gt;\n\t\t\t&lt;cfoutput&gt;\n\t\t\t\t&lt;cfset rank = cycle(values=&quot;president,vice-president,director,manager,specialist,intern&quot;, name=&quot;position&quot;)&gt;\n\t\t\t\t&lt;li class=&quot;#rank#&quot;&gt;#employees.name#&lt;/li&gt;\n\t\t\t&lt;/cfoutput&gt;\n\t\t&lt;/ul&gt;\n\t&lt;/div&gt;\n\t&lt;cfset resetCycle(&quot;position&quot;)&gt;\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Cycles through list values every time it is called.\n\n","parameters":[{"type":"string","hint":"List of values to cycle through.","required":true,"name":"values"},{"type":"string","hint":"Name to give the cycle. Useful when you use multiple cycles on a page.","required":false,"name":"name","default":"default"}],"name":"cycle","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"model.dataSource","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Override the data source for a model (basic usage).\n// In models/User.cfc\nconfig() {\n\t// Tell Wheels to use the data source named `users_source` instead of\n\t// the default one whenever this model makes SQL calls.\n\tdataSource(&quot;users_source&quot;);\n}\n\n// 2. Override the data source with explicit credentials.\n// In models/LegacyOrder.cfc\nconfig() {\n\tdataSource(datasource=&quot;legacy_db&quot;, username=&quot;app_reader&quot;, password=&quot;s3cr3t&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Use this method to override the data source connection information for this model.\n\n","parameters":[{"type":"string","hint":"The data source name to connect to.","required":true,"name":"datasource"},{"type":"string","hint":"The username for the data source.","required":false,"name":"username","default":""},{"type":"string","hint":"The password for the data source.","required":false,"name":"password","default":""}],"name":"dataSource","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"tabledefinition.date","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single date column to a new table\nt = createTable(name='events');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.date(columnNames='eventDate', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple date columns at once\nt = createTable(name='subscriptions');\n\tt.string(columnNames='plan', limit=100, allowNull=false);\n\tt.date(columnNames='startDate,endDate', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a date column with a default value to an existing table\nt = changeTable(name='users');\n\tt.date(columnNames='birthDate', allowNull=true);\nt.change();\n</code></pre>","hasExtended":true},"hint":"Adds date columns to table definition.\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"date","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"controller.dateField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic date field bound to a model object property\n#dateField(objectName=&quot;event&quot;, property=&quot;startDate&quot;)#\n\n// 2. Date field with a custom label, min/max constraints, and a CSS class\n#dateField(objectName=&quot;event&quot;, property=&quot;startDate&quot;, label=&quot;Start Date&quot;, min=&quot;2024-01-01&quot;, max=&quot;2024-12-31&quot;, class=&quot;date-picker&quot;)#\n\n// 3. Date fields for nested properties on a hasMany association (e.g., schedule items)\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(project.milestones)#&quot; index=&quot;i&quot;&gt;\n\t#dateField(objectName=&quot;project&quot;, association=&quot;milestones&quot;, position=&quot;#i#&quot;, property=&quot;dueDate&quot;, label=&quot;Due Date ##i#&quot;)#\n&lt;/cfloop&gt;</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a date field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"Minimum allowed date (YYYY-MM-DD format).","required":false,"name":"min"},{"type":"string","hint":"Maximum allowed date (YYYY-MM-DD format).","required":false,"name":"max"},{"type":"string","required":false,"name":"step"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"dateField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.dateFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic date field with a name and label\n#dateFieldTag(name=&quot;startDate&quot;, label=&quot;Start Date&quot;)#\n\n// 2. Pre-filled date value with min/max constraints\n#dateFieldTag(name=&quot;eventDate&quot;, value=&quot;2024-06-15&quot;, min=&quot;2024-01-01&quot;, max=&quot;2024-12-31&quot;, label=&quot;Event Date&quot;)#\n\n// 3. Date field with extra HTML attributes passed through\n#dateFieldTag(name=&quot;dueDate&quot;, label=&quot;Due Date&quot;, class=&quot;form-control&quot;, id=&quot;due-date-input&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a date field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"Minimum allowed date (YYYY-MM-DD format).","required":false,"name":"min"},{"type":"string","hint":"Maximum allowed date (YYYY-MM-DD format).","required":false,"name":"max"},{"type":"string","required":false,"name":"step"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"dateFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.dateSelect","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>&lt;!--- Basic date select bound to a model object ---&gt;\n#dateSelect(objectName=&quot;user&quot;, property=&quot;dateOfBirth&quot;)#\n\n&lt;!--- Show fields to select only month and year ---&gt;\n#dateSelect(objectName=&quot;order&quot;, property=&quot;expirationDate&quot;, order=&quot;month,year&quot;)#\n\n&lt;!--- Display month as numbers and include a blank option ---&gt;\n#dateSelect(objectName=&quot;event&quot;, property=&quot;startDate&quot;, monthDisplay=&quot;numbers&quot;, includeBlank=true)#\n\n&lt;!--- Restrict year range and use abbreviated month names ---&gt;\n#dateSelect(objectName=&quot;reservation&quot;, property=&quot;checkInDate&quot;, startYear=2024, endYear=2030, monthDisplay=&quot;abbreviations&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing three <code>select</code> form controls for month, day, and year based on the supplied <code>objectName</code> and <code>property</code>.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":false,"name":"objectName","default":""},{"type":"string","hint":"The name of the property to use in the form control.","required":false,"name":"property","default":""},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a `hasMany` relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"Use to change the order of or exclude date `select` tags.","required":false,"name":"order","default":"month,day,year"},{"type":"string","hint":"Use to change the character that is displayed between the date `select` tags.","required":false,"name":"separator","default":" "},{"type":"numeric","hint":"First year in `select` list.","required":false,"name":"startYear","default":2021},{"type":"numeric","hint":"Last year in `select` list.","required":false,"name":"endYear","default":2031},{"type":"string","hint":"Pass in names, numbers, or abbreviations to control display.","required":false,"name":"monthDisplay","default":"names"},{"type":"string","required":false,"name":"monthNames","default":"January,February,March,April,May,June,July,August,September,October,November,December"},{"type":"string","required":false,"name":"monthAbbreviations","default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"},{"type":"any","hint":"Whether to include a blank option in the `select` form control. Pass `true` to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":false},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using `aroundLeft` or `aroundRight`.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The `class` name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"boolean","hint":"Set to false to not combine the select parts into a single DateTime object.","required":false,"name":"combine"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"dateSelect","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.dateSelectTags","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic date selection - the &quot;Tag&quot; version accepts `name` and `selected` directly instead of binding to a model object\n#dateSelectTags(name=&quot;dateStart&quot;, selected=params.dateStart)#\n\n// 2. Show only month and year fields (omit day)\n#dateSelectTags(name=&quot;expiration&quot;, selected=params.expiration, order=&quot;month,year&quot;)#\n\n// 3. Custom year range with a blank option and a label\n#dateSelectTags(name=&quot;birthdate&quot;, selected=params.birthdate, startYear=1920, endYear=2024, includeBlank=true, label=&quot;Date of Birth&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing three <code>select</code> form controls (month, day, and year) based on a name and value.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value of option that should be selected by default.","required":false,"name":"selected","default":""},{"type":"string","hint":"Use to change the order of or exclude date `select` tags.","required":false,"name":"order","default":"month,day,year"},{"type":"string","hint":"Use to change the character that is displayed between the date `select` tags.","required":false,"name":"separator","default":" "},{"type":"numeric","hint":"First year in `select` list.","required":false,"name":"startYear","default":2021},{"type":"numeric","hint":"Last year in `select` list.","required":false,"name":"endYear","default":2031},{"type":"string","hint":"Pass in names, numbers, or abbreviations to control display.","required":false,"name":"monthDisplay","default":"names"},{"type":"string","hint":"[see:dateSelect].","required":false,"name":"monthNames","default":"January,February,March,April,May,June,July,August,September,October,November,December"},{"type":"string","hint":"[see:dateSelect].","required":false,"name":"monthAbbreviations","default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"boolean","hint":"Set to false to not combine the select parts into a single DateTime object.","required":false,"name":"combine"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"date","required":false,"name":"$now","default":"[runtime expression]"}],"name":"dateSelectTags","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"any","slug":"tabledefinition.datetime","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single datetime column to a new table\nt = createTable(name='orders');\n\tt.string(columnNames='status', limit=50, allowNull=false);\n\tt.datetime(columnNames='placedAt', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple datetime columns at once\nt = createTable(name='appointments');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.datetime(columnNames='startAt,endAt', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a nullable datetime column with a default to an existing table\nt = changeTable(name='posts');\n\tt.datetime(columnNames='publishedAt', allowNull=true, default='NOW()');\nt.change();\n</code></pre>","hasExtended":true},"hint":"adds datetime columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"datetime","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"controller.dateTimeSelect","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic date and time select for an article's published date\n#dateTimeSelect(objectName=&quot;article&quot;, property=&quot;publishedAt&quot;)#\n\n// 2. Show only month, day, hour, and minute (exclude year and second)\n#dateTimeSelect(objectName=&quot;appointment&quot;, property=&quot;dateTimeStart&quot;, dateOrder=&quot;month,day&quot;, timeOrder=&quot;hour,minute&quot;)#\n\n// 3. Use 12-hour time format with a blank option and a custom year range\n#dateTimeSelect(objectName=&quot;event&quot;, property=&quot;startsAt&quot;, twelveHour=true, includeBlank=true, startYear=2020, endYear=2030)#\n\n// 4. Display month as numbers, step minutes by 15, and add a label\n#dateTimeSelect(objectName=&quot;meeting&quot;, property=&quot;scheduledAt&quot;, monthDisplay=&quot;numbers&quot;, minuteStep=15, label=&quot;Scheduled Date &amp; Time&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing six <code>select</code> form controls (three for date selection and the remaining three for time selection) based on the supplied objectName and property.\n\n","parameters":[{"type":"string","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"Use to change the order of or exclude date select tags.","required":false,"name":"dateOrder","default":"month,day,year"},{"type":"string","hint":"Use to change the character that is displayed between the date select tags.","required":false,"name":"dateSeparator","default":" "},{"type":"numeric","hint":"First year in select list.","required":false,"name":"startYear","default":2021},{"type":"numeric","hint":"Last year in select list.","required":false,"name":"endYear","default":2031},{"type":"string","hint":"Pass in names, numbers, or abbreviations to control display.","required":false,"name":"monthDisplay","default":"names"},{"type":"string","required":false,"name":"monthNames","default":"January,February,March,April,May,June,July,August,September,October,November,December"},{"type":"string","required":false,"name":"monthAbbreviations","default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"},{"type":"string","hint":"Use to change the order of or exclude time select tags.","required":false,"name":"timeOrder","default":"hour,minute,second"},{"type":"string","hint":"Use to change the character that is displayed between the time select tags.","required":false,"name":"timeSeparator","default":":"},{"type":"numeric","hint":"Pass in 10 to only show minute 10, 20, 30, etc.","required":false,"name":"minuteStep","default":1},{"type":"numeric","hint":"Pass in 10 to only show seconds 10, 20, 30, etc","required":false,"name":"secondStep","default":1},{"type":"string","hint":"Use to change the character that is displayed between the first and second set of select tags.","required":false,"name":"separator","default":" - "},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":false},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"boolean","hint":"Set to false to not combine the select parts into a single DateTime object.","required":false,"name":"combine"},{"type":"boolean","hint":"Whether to display the hours in 24 or 12 hour format. 12 hour format has AM/PM drop downs","required":false,"name":"twelveHour","default":false},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"dateTimeSelect","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.dateTimeSelectTags","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage - the &quot;Tag&quot; version accepts `name` and `selected` directly instead of binding to a model object\n#dateTimeSelectTags(name=&quot;dateTimeStart&quot;, selected=params.dateTimeStart)#\n\n// 2. Show only month/day for the date portion and hour/minute for the time portion\n#dateTimeSelectTags(name=&quot;dateTimeStart&quot;, selected=params.dateTimeStart, dateOrder=&quot;month,day&quot;, timeOrder=&quot;hour,minute&quot;)#\n\n// 3. Custom year range, 15-minute steps, 12-hour format, and a label\n#dateTimeSelectTags(name=&quot;scheduledAt&quot;, selected=params.scheduledAt, startYear=2020, endYear=2030, minuteStep=15, twelveHour=true, label=&quot;Scheduled Date &amp; Time&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing six <code>select</code> form controls (three for date selection and the remaining three for time selection) based on a name.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value of option that should be selected by default.","required":false,"name":"selected","default":""},{"type":"string","hint":"Use to change the order of or exclude date select tags.","required":false,"name":"dateOrder","default":"month,day,year"},{"type":"string","hint":"Use to change the character that is displayed between the date select tags.","required":false,"name":"dateSeparator","default":" "},{"type":"numeric","hint":"First year in `select` list.","required":false,"name":"startYear","default":2021},{"type":"numeric","hint":"Last year in `select` list.","required":false,"name":"endYear","default":2031},{"type":"string","hint":"Pass in names, numbers, or abbreviations to control display.","required":false,"name":"monthDisplay","default":"names"},{"type":"string","hint":"[see:dateSelect].","required":false,"name":"monthNames","default":"January,February,March,April,May,June,July,August,September,October,November,December"},{"type":"string","hint":"[see:dateSelect].","required":false,"name":"monthAbbreviations","default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"},{"type":"string","hint":"Use to change the order of or exclude time select tags.","required":false,"name":"timeOrder","default":"hour,minute,second"},{"type":"string","hint":"Use to change the character that is displayed between the time select tags.","required":false,"name":"timeSeparator","default":":"},{"type":"numeric","hint":"Pass in 10 to only show minute 10, 20, 30, etc.","required":false,"name":"minuteStep","default":1},{"type":"numeric","hint":"Pass in 10 to only show seconds 10, 20, 30, etc.","required":false,"name":"secondStep","default":1},{"type":"string","hint":"Use to change the character that is displayed between the first and second set of select tags.","required":false,"name":"separator","default":" - "},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"boolean","hint":"Set to false to not combine the select parts into a single DateTime object.","required":false,"name":"combine"},{"type":"boolean","hint":"whether to display the hours in 24 or 12 hour format. 12 hour format has AM/PM drop downs","required":false,"name":"twelveHour","default":false},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"dateTimeSelectTags","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.daySelectTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage: render a day-of-month select for a standalone form (not bound to a model)\n#daySelectTag(name=&quot;day&quot;, selected=params.day)#\n\n// 2. Pre-select day 15 and include a blank prompt at the top\n#daySelectTag(name=&quot;birthDay&quot;, selected=15, includeBlank=&quot;-- Select Day --&quot;)#\n\n// 3. Wrap the control with a label and surrounding HTML via prepend/append\n#daySelectTag(name=&quot;day&quot;, selected=params.day, label=&quot;Day&quot;, prepend=&quot;&lt;div class=&quot;&quot;field&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a <code>select</code> form control for the days of the month based on the supplied name.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"The day that should be selected initially.","required":false,"name":"selected","default":""},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"date","required":false,"name":"$now","default":"[runtime expression]"}],"name":"daySelectTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"any","slug":"tabledefinition.decimal","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single decimal column to a new table\nt = createTable(name='products');\n\tt.string(columnNames='name', limit=255, allowNull=false);\n\tt.decimal(columnNames='price', precision=10, scale=2, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple decimal columns at once\nt = createTable(name='measurements');\n\tt.string(columnNames='label', limit=100, allowNull=false);\n\tt.decimal(columnNames='length,width,height', precision=8, scale=4, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a nullable decimal column with a default to an existing table\nt = changeTable(name='orders');\n\tt.decimal(columnNames='discount', precision=5, scale=2, allowNull=true, default='0.00');\nt.change();\n</code></pre>","hasExtended":true},"hint":"adds decimal columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"},{"type":"numeric","required":false,"name":"precision"},{"type":"numeric","required":false,"name":"scale"}],"name":"decimal","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"struct","slug":"mapper.delete","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // Route name:  articleReview\n    // Example URL: /articles/987/reviews/12542\n    // Controller:  Reviews\n    // Action:      delete\n    .delete(name=&quot;articleReview&quot;, pattern=&quot;articles/[articleKey]/reviews/[key]&quot;, to=&quot;reviews##delete&quot;)\n\n    // Route name:  cookedBooks\n    // Example URL: /cooked-books\n    // Controller:  CookedBooks\n    // Action:      delete\n    .delete(name=&quot;cookedBooks&quot;, controller=&quot;cookedBooks&quot;, action=&quot;delete&quot;)\n\n    // Route name:  logout\n    // Example URL: /logout\n    // Controller:  Sessions\n    // Action:      delete\n    .delete(name=&quot;logout&quot;, to=&quot;sessions##delete&quot;)\n\n    // Route name:  clientsStatus\n    // Example URL: /statuses/4918\n    // Controller:  clients.Statuses\n    // Action:      delete\n    .delete(name=&quot;statuses&quot;, to=&quot;statuses##delete&quot;, package=&quot;clients&quot;)\n\n    // Route name:  blogComment\n    // Example URL: /comments/5432\n    // Controller:  blog.Comments\n    // Action:      delete\n    .delete(\n        name=&quot;comment&quot;,\n        pattern=&quot;comments/[key]&quot;,\n        to=&quot;comments##delete&quot;,\n        package=&quot;blog&quot;\n    )\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Create a route that matches a URL requiring an HTTP <code>DELETE</code> method. We recommend using this matcher to expose actions that delete database records.\n\n","parameters":[{"type":"string","hint":"Camel-case name of route to reference when build links and form actions (e.g., `blogPost`).","required":false,"name":"name"},{"type":"string","hint":"Overrides the URL pattern that will match the route. The default value is a dasherized version of `name` (e.g., a `name` of `blogPost` generates a pattern of `blog-post`).","required":false,"name":"pattern"},{"type":"string","hint":"Set `controller##action` combination to map the route to. You may use either this argument or a combination of `controller` and `action`.","required":false,"name":"to"},{"type":"string","hint":"Map the route to a given controller. This must be passed along with the `action` argument.","required":false,"name":"controller"},{"type":"string","hint":"Map the route to a given action within the `controller`. This must be passed along with the `controller` argument.","required":false,"name":"action"},{"type":"string","hint":"Indicates a subfolder that the controller will be referenced from (but not added to the URL pattern). For example, if you set this to `admin`, the controller will be located at `admin/YourController.cfc`, but the URL path will not contain `admin/`.","required":false,"name":"package"},{"type":"string","hint":"If this route is within a nested resource, you can set this argument to `member` or `collection`. A `member` route contains a reference to the resource's `key`, while a `collection` route does not.","required":false,"name":"on"},{"type":"string","hint":"Redirect via 302 to this URL when this route is matched. Has precedence over controller/action. Use either an absolute link like `/about/`, or a full canonical link.","required":false,"name":"redirect"}],"name":"delete","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"boolean","slug":"model.delete","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get a post object and then delete it from the database.\npost = model(&quot;Post&quot;).findByKey(33);\npost.delete();\n\n// 2. Permanently delete a record even if the model uses soft deletes.\nuser = model(&quot;User&quot;).findByKey(params.userId);\nuser.delete(softDelete=false);\n\n// 3. Delete a record without running callbacks (e.g. skip `beforeDelete` / `afterDelete`).\ncomment = model(&quot;Comment&quot;).findByKey(params.commentId);\ncomment.delete(callbacks=false);\n\n// 4. If you have a `hasMany` association setup from `post` to `comment`, you can do a scoped call. (The `deleteComment` method below will call `comment.delete()` internally.)\npost = model(&quot;Post&quot;).findByKey(params.postId);\ncomment = model(&quot;Comment&quot;).findByKey(params.commentId);\npost.deleteComment(comment);\n</code></pre>","hasExtended":true},"hint":"Deletes the object, which means the row is deleted from the database (unless prevented by a <code>beforeDelete</code> callback).\nReturns <code>true</code> on successful deletion of the row, <code>false</code> otherwise.\n\n","parameters":[{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":true},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":false},{"type":"boolean","hint":"Set to `false` to permanently delete a record, even if it has a soft delete column.","required":false,"name":"softDelete","default":true}],"name":"delete","tags":{"category":"CRUD Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"crudfunctions"}},{"returntype":"numeric","slug":"model.deleteAll","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Delete all inactive users without instantiating them (skips callbacks and validations).\nrecordsDeleted = model(&quot;User&quot;).deleteAll(where=&quot;inactive=1&quot;);\n\n// 2. Delete all inactive users and run their beforeDelete / afterDelete callbacks.\nrecordsDeleted = model(&quot;User&quot;).deleteAll(where=&quot;inactive=1&quot;, instantiate=true);\n\n// 3. Permanently delete soft-deleted records (bypass the soft-delete column).\nrecordsDeleted = model(&quot;User&quot;).deleteAll(where=&quot;inactive=1&quot;, softDelete=false);\n\n// 4. If you have a `hasMany` association from `Post` to `Comment`, you can use a scoped call. (The `deleteAllComments` method below calls `model(&quot;Comment&quot;).deleteAll(where=&quot;postId=#post.id#&quot;)` internally.)\npost = model(&quot;Post&quot;).findByKey(params.postId);\nhowManyDeleted = post.deleteAllComments();\n</code></pre>","hasExtended":true},"hint":"Deletes all records that match the <code>where</code> argument.\nBy default, objects will not be instantiated and therefore callbacks and validations are not invoked.\nYou can change this behavior by passing in <code>instantiate=true</code>.\nReturns the number of records that were deleted.\n\n","parameters":[{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"boolean","hint":"Whether or not to instantiate the object(s) first. When objects are not instantiated, any callbacks and validations set on them will be skipped.","required":false,"name":"instantiate","default":false},{"type":"struct","hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","required":false,"name":"useIndex","default":"[runtime expression]"},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":true},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":false},{"type":"boolean","hint":"Set to `false` to permanently delete a record, even if it has a soft delete column.","required":false,"name":"softDelete","default":true}],"name":"deleteAll","tags":{"category":"Delete Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"deletefunctions"}},{"returntype":"boolean","slug":"model.deleteByKey","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Delete the user with the primary key value of 1.\nresult = model(&quot;User&quot;).deleteByKey(1);\n// result -&gt; true (if the row was deleted), false otherwise\n\n// 2. Permanently delete a soft-deletable record (bypass soft delete).\nresult = model(&quot;User&quot;).deleteByKey(key=1, softDelete=false);\n\n// 3. Delete using a composite primary key (comma-separated values).\nresult = model(&quot;OrderItem&quot;).deleteByKey(&quot;42,7&quot;);\n\n// 4. Delete within a transaction that can be rolled back (useful for testing).\nresult = model(&quot;User&quot;).deleteByKey(key=1, transaction=&quot;rollback&quot;);\n</code></pre>","hasExtended":true},"hint":"Finds the record with the supplied key and deletes it.\nReturns <code>true</code> on successful deletion of the row, <code>false</code> otherwise.\n\n","parameters":[{"type":"any","hint":"Primary key value(s) of the record to fetch. Separate with comma if passing in multiple primary key values. Accepts a string, list, or a numeric value.","required":true,"name":"key"},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":true},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":false},{"type":"boolean","hint":"Set to `false` to permanently delete a record, even if it has a soft delete column.","required":false,"name":"softDelete","default":true}],"name":"deleteByKey","tags":{"category":"Delete Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"deletefunctions"}},{"returntype":"boolean","slug":"model.deleteOne","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Delete the user who signed up most recently.\nresult = model(&quot;User&quot;).deleteOne(order=&quot;signupDate DESC&quot;);\n\n// 2. Delete the oldest unpaid invoice for a given customer.\nresult = model(&quot;Invoice&quot;).deleteOne(\n\twhere=&quot;customerId=#params.customerId# AND status='unpaid'&quot;,\n\torder=&quot;createdAt ASC&quot;\n);\n\n// 3. Permanently delete a soft-deletable record (bypass soft-delete behaviour).\nresult = model(&quot;User&quot;).deleteOne(\n\twhere=&quot;status='banned'&quot;,\n\torder=&quot;createdAt ASC&quot;,\n\tsoftDelete=false\n);\n\n// 4. If you have a `hasOne` association set up from `User` to `Profile` you can do a scoped call.\n// The `deleteProfile` method will call `model(&quot;Profile&quot;).deleteOne(where=&quot;userId=#aUser.id#&quot;)` internally.\naUser = model(&quot;User&quot;).findByKey(params.userId);\naUser.deleteProfile();\n</code></pre>","hasExtended":true},"hint":"Gets an object based on conditions and deletes it.\n\n","parameters":[{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"order","default":""},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":true},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":false},{"type":"struct","hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","required":false,"name":"useIndex","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to permanently delete a record, even if it has a soft delete column.","required":false,"name":"softDelete","default":true}],"name":"deleteOne","tags":{"category":"Delete Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"deletefunctions"}},{"returntype":"string","slug":"controller.deobfuscateParam","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Deobfuscate a URL parameter to get the original numeric ID\n// (Wheels automatically obfuscates numeric URL params when obfuscateUrls is enabled)\noriginalId = deobfuscateParam(&quot;b7ab9a50&quot;);\n// originalId -&gt; &quot;35&quot;\n\n// 2. Round-trip: obfuscate a value, then deobfuscate it back\nobfuscated = obfuscateParam(&quot;100&quot;);\noriginal = deobfuscateParam(obfuscated);\n// original -&gt; &quot;100&quot;\n\n// 3. Non-obfuscated values (e.g. already plain integers) are returned as-is\npassthrough = deobfuscateParam(&quot;42&quot;);\n// passthrough -&gt; &quot;42&quot;\n</code></pre>","hasExtended":true},"hint":"Deobfuscates a value.\n\n","parameters":[{"type":"string","hint":"The value to deobfuscate.","required":true,"name":"param"}],"name":"deobfuscateParam","tags":{"category":"Miscellaneous Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.distanceOfTimeInWords","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Compare two dates about a month apart\nrightNow = Now();\naWhileAgo = DateAdd(&quot;d&quot;, -30, rightNow);\nwriteOutput(distanceOfTimeInWords(aWhileAgo, rightNow));\n// -&gt; &quot;about 1 month&quot;\n\n// 2. Show a short gap with seconds included\njustNow = Now();\nfiveSecondsAgo = DateAdd(&quot;s&quot;, -5, justNow);\nwriteOutput(distanceOfTimeInWords(fiveSecondsAgo, justNow, includeSeconds=true));\n// -&gt; &quot;less than 5 seconds&quot;\n\n// 3. Show various time ranges\nnow = Now();\nwriteOutput(distanceOfTimeInWords(DateAdd(&quot;n&quot;, -2, now), now));\n// -&gt; &quot;2 minutes&quot;\n\nwriteOutput(distanceOfTimeInWords(DateAdd(&quot;h&quot;, -3, now), now));\n// -&gt; &quot;about 3 hours&quot;\n\nwriteOutput(distanceOfTimeInWords(DateAdd(&quot;d&quot;, -5, now), now));\n// -&gt; &quot;5 days&quot;\n\nwriteOutput(distanceOfTimeInWords(DateAdd(&quot;yyyy&quot;, -2, now), now));\n// -&gt; &quot;over 2 years&quot;\n</code></pre>","hasExtended":true},"hint":"Pass in two dates to this method, and it will return a string describing the difference between them.\n\n","parameters":[{"type":"date","hint":"Date to compare from.","required":true,"name":"fromTime"},{"type":"date","hint":"Date to compare to.","required":true,"name":"toTime"},{"type":"boolean","hint":"Whether or not to include the number of seconds in the returned string.","required":false,"name":"includeSeconds","default":false}],"name":"distanceOfTimeInWords","tags":{"category":"Date Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"datefunctions"}},{"returntype":"struct","slug":"migrator.doctor","availableIn":["migrator"],"extended":{"docs":"","hasExtended":false},"hint":"Returns a comprehensive health report on the migrator state. Pure\nread — no mutation. Used by <code>wheels migrate doctor</code> to surface\norphans, gaps, and pending migrations in one pass.\nResult struct:\n- healthy: boolean — true iff no orphans AND no pending\n- currentVersion: string — highest applied version (may be orphan)\n- orphans: array — DB versions with no matching file\n- pending: array — local files not yet applied\n- summary: struct with .total, .applied, .pending, .orphan counts\n- message: human-readable one-paragraph summary\nSee issue #2780 / PR #2798 for the orphan detection foundation.\n\n","parameters":[],"name":"doctor","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"void","slug":"migration.down","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Reverse a table creation by dropping the table\n// Called automatically when rolling back this migration\nfunction down() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\tdropTable(&quot;employees&quot;);\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (structKeyExists(state, &quot;exception&quot;)) {\n\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\tthrow(\n\t\t\t\terrorCode = &quot;1&quot;,\n\t\t\t\tdetail    = state.exception.detail,\n\t\t\t\tmessage   = state.exception.message,\n\t\t\t\ttype      = &quot;any&quot;\n\t\t\t);\n\t\t} else {\n\t\t\ttransaction action=&quot;commit&quot;;\n\t\t}\n\t}\n}\n\n// 2. Reverse an addColumn() call by removing the column\nfunction down() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\tremoveColumn(table=&quot;users&quot;, columnName=&quot;biography&quot;);\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (structKeyExists(state, &quot;exception&quot;)) {\n\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\tthrow(\n\t\t\t\terrorCode = &quot;1&quot;,\n\t\t\t\tdetail    = state.exception.detail,\n\t\t\t\tmessage   = state.exception.message,\n\t\t\t\ttype      = &quot;any&quot;\n\t\t\t);\n\t\t} else {\n\t\t\ttransaction action=&quot;commit&quot;;\n\t\t}\n\t}\n}\n\n// 3. Paired up() and down() inside a full migration component\ncomponent extends=&quot;[extends]&quot; hint=&quot;Add status column to orders&quot; {\n\n\tfunction up() {\n\t\tvar state = {};\n\t\ttransaction {\n\t\t\ttry {\n\t\t\t\taddColumn(table=&quot;orders&quot;, columnType=&quot;string&quot;, columnName=&quot;status&quot;, limit=50, default=&quot;pending&quot;);\n\t\t\t} catch (any e) {\n\t\t\t\tstate.exception = e;\n\t\t\t}\n\n\t\t\tif (structKeyExists(state, &quot;exception&quot;)) {\n\t\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\t\tthrow(\n\t\t\t\t\terrorCode = &quot;1&quot;,\n\t\t\t\t\tdetail    = state.exception.detail,\n\t\t\t\t\tmessage   = state.exception.message,\n\t\t\t\t\ttype      = &quot;any&quot;\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\ttransaction action=&quot;commit&quot;;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction down() {\n\t\tvar state = {};\n\t\ttransaction {\n\t\t\ttry {\n\t\t\t\tremoveColumn(table=&quot;orders&quot;, columnName=&quot;status&quot;);\n\t\t\t} catch (any e) {\n\t\t\t\tstate.exception = e;\n\t\t\t}\n\n\t\t\tif (structKeyExists(state, &quot;exception&quot;)) {\n\t\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\t\tthrow(\n\t\t\t\t\terrorCode = &quot;1&quot;,\n\t\t\t\t\tdetail    = state.exception.detail,\n\t\t\t\t\tmessage   = state.exception.message,\n\t\t\t\t\ttype      = &quot;any&quot;\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\ttransaction action=&quot;commit&quot;;\n\t\t\t}\n\t\t}\n\t}\n\n}\n</code></pre>","hasExtended":true},"hint":"Migrates down: will be executed when migrating your schema backward\nAlong with up(), these are the two main functions in any migration file\nOnly available in a migration CFC\n\n","parameters":[],"name":"down","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.dropForeignKey","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Drop a foreign key constraint by its explicit name\n// In the down() function, remove a foreign key added in up()\ndropForeignKey(table=&quot;orders&quot;, keyName=&quot;FK_orders_customers&quot;);\n\n// 2. Drop a foreign key that was created via addReference()\n// addReference() creates keys named FK_&lt;table&gt;_&lt;pluralizedReference&gt;\n// So addReference(table=&quot;comments&quot;, referenceName=&quot;post&quot;) creates &quot;FK_comments_posts&quot;\ndropForeignKey(table=&quot;comments&quot;, keyName=&quot;FK_comments_posts&quot;);\n\n// 3. Use inside a migration's down() to reverse an addForeignKey() call\n// up() called: addForeignKey(table=&quot;profiles&quot;, referenceTable=&quot;users&quot;, column=&quot;userId&quot;, referenceColumn=&quot;id&quot;)\n// down() reverses it:\ndropForeignKey(table=&quot;profiles&quot;, keyName=&quot;FK_profiles_users&quot;);\n</code></pre>","hasExtended":true},"hint":"Drops a foreign key constraint from the database\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name to perform the operation on","required":true,"name":"table"},{"type":"string","hint":"the name of the key to drop","required":true,"name":"keyName"}],"name":"dropForeignKey","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.dropReference","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Drop the foreign key from comments.postId back to posts.id\n// Removes the constraint named FK_comments_posts\ndropReference(table=&quot;comments&quot;, referenceName=&quot;post&quot;);\n\n// 2. Drop a foreign key from order_items back to orders\n// Removes the constraint named FK_order_items_orders\ndropReference(table=&quot;order_items&quot;, referenceName=&quot;order&quot;);\n\n// 3. Use dropReference in the down() of a migration that added a reference in up()\n// In your migration CFC:\n//\n// public void function up() {\n//     addReference(table=&quot;comments&quot;, referenceName=&quot;post&quot;);\n// }\n//\n// public void function down() {\n//     dropReference(table=&quot;comments&quot;, referenceName=&quot;post&quot;);\n// }\n</code></pre>","hasExtended":true},"hint":"Drop a foreign key constraint from the database, using the reference name that was used to create it\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name to perform the operation on","required":true,"name":"table"},{"type":"string","hint":"the name of the reference to drop","required":false,"name":"referenceName"},{"type":"string","hint":"Alias for `referenceName` (consistent with the modern migrator surface — `columnName` / `columnNames` are accepted alongside the legacy form).","required":false,"name":"columnName"},{"type":"string","hint":"Plural alias for `referenceName`. When both `columnName` and `columnNames` are supplied, `columnNames` wins.","required":false,"name":"columnNames"}],"name":"dropReference","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.dropTable","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Drop a table in the down() migration (reversing a createTable in up())\ncomponent extends=&quot;wheels.migrator.Migration&quot; hint=&quot;Add products table&quot; {\n\n\tfunction up() {\n\t\tt = createTable(name=&quot;products&quot;);\n\t\tt.string(columnNames=&quot;name&quot;, allowNull=false);\n\t\tt.decimal(columnNames=&quot;price&quot;, precision=10, scale=2);\n\t\tt.boolean(columnNames=&quot;active&quot;, default=1);\n\t\tt.timestamps();\n\t\tt.create();\n\t}\n\n\tfunction down() {\n\t\tdropTable(&quot;products&quot;);\n\t}\n\n}\n\n// 2. Drop multiple tables in a single down() migration\ncomponent extends=&quot;wheels.migrator.Migration&quot; hint=&quot;Add orders and line items tables&quot; {\n\n\tfunction up() {\n\t\tt = createTable(name=&quot;lineItems&quot;);\n\t\tt.integer(columnNames=&quot;orderId&quot;);\n\t\tt.integer(columnNames=&quot;productId&quot;);\n\t\tt.integer(columnNames=&quot;quantity&quot;);\n\t\tt.timestamps();\n\t\tt.create();\n\n\t\tt = createTable(name=&quot;orders&quot;);\n\t\tt.integer(columnNames=&quot;userId&quot;);\n\t\tt.string(columnNames=&quot;status&quot;);\n\t\tt.timestamps();\n\t\tt.create();\n\t}\n\n\tfunction down() {\n\t\tdropTable(&quot;lineItems&quot;);\n\t\tdropTable(&quot;orders&quot;);\n\t}\n\n}\n</code></pre>","hasExtended":true},"hint":"Drops a table from the database\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"Name of the table to drop","required":true,"name":"name"}],"name":"dropTable","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.dropView","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Drop a view in the down() migration (reversing a createView in up())\ncomponent extends=&quot;wheels.migrator.Migration&quot; hint=&quot;Add active users view&quot; {\n\n\tfunction up() {\n\t\tcreateView(name=&quot;activeUsers&quot;)\n\t\t\t.selectStatement(sql=&quot;SELECT id, firstName, lastName, email FROM users WHERE deletedAt IS NULL&quot;)\n\t\t\t.create();\n\t}\n\n\tfunction down() {\n\t\tdropView(name=&quot;activeUsers&quot;);\n\t}\n\n}\n\n// 2. Drop multiple views in a single down() migration\ncomponent extends=&quot;wheels.migrator.Migration&quot; hint=&quot;Add reporting views&quot; {\n\n\tfunction up() {\n\t\tcreateView(name=&quot;publishedArticles&quot;)\n\t\t\t.selectStatement(sql=&quot;SELECT id, title, authorId, publishedAt FROM articles WHERE publishedAt IS NOT NULL&quot;)\n\t\t\t.create();\n\n\t\tcreateView(name=&quot;activeAuthors&quot;)\n\t\t\t.selectStatement(sql=&quot;SELECT id, firstName, lastName FROM users WHERE deletedAt IS NULL&quot;)\n\t\t\t.create();\n\t}\n\n\tfunction down() {\n\t\tdropView(name=&quot;publishedArticles&quot;);\n\t\tdropView(name=&quot;activeAuthors&quot;);\n\t}\n\n}\n</code></pre>","hasExtended":true},"hint":"drops a view from the database\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"Name of the view to drop","required":true,"name":"name"}],"name":"dropView","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"string","slug":"controller.emailField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic email field bound to an object property\n#emailField(objectName=&quot;user&quot;, property=&quot;emailAddress&quot;)#\n\n// 2. Email field with a custom label and a CSS class\n#emailField(label=&quot;Email Address&quot;, objectName=&quot;user&quot;, property=&quot;emailAddress&quot;, class=&quot;form-control&quot;)#\n\n// 3. Nested email field for a contacts association (hasMany)\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(account.contacts)#&quot; index=&quot;i&quot;&gt;\n\t#emailField(label=&quot;Contact Email ##i#&quot;, objectName=&quot;account&quot;, association=&quot;contacts&quot;, position=i, property=&quot;email&quot;)#\n&lt;/cfloop&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing an email field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"emailField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.emailFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic email field with a name and pre-filled value\n#emailFieldTag(name=&quot;userEmail&quot;, value=&quot;hello@example.com&quot;)#\n\n// 2. Email field with a label\n#emailFieldTag(label=&quot;Email Address&quot;, name=&quot;userEmail&quot;, value=params.userEmail)#\n\n// 3. Email field with a CSS class and placeholder passed as extra HTML attributes\n#emailFieldTag(name=&quot;contactEmail&quot;, value=&quot;&quot;, class=&quot;form-control&quot;, placeholder=&quot;you@example.com&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing an email field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"emailFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"struct","slug":"mapper.end","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    .namespace(&quot;admin&quot;)\n        .resources(&quot;products&quot;)\n    .end() // Ends the `namespace` block.\n\n    .scope(package=&quot;public&quot;)\n        .resources(name=&quot;products&quot;, nested=true)\n          .resources(&quot;variations&quot;)\n        .end() // Ends the nested `resources` block.\n    .end() // Ends the `scope` block.\n.end(); // Ends the `mapper` block.\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Call this to end a nested routing block or the entire route configuration. This method is chained on a sequence of routing mapper method calls started by <code>mapper()</code>.\n\n","parameters":[],"name":"end","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.endFormTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Close a form opened with startFormTag\n#startFormTag(action=&quot;create&quot;)#\n    &lt;!--- your form controls ---&gt;\n#endFormTag()#\n\n// 2. Append a note after the closing form tag\n#startFormTag(action=&quot;update&quot;, method=&quot;post&quot;)#\n    &lt;!--- your form controls ---&gt;\n#endFormTag(append=&quot;&lt;p&gt;All fields are required.&lt;/p&gt;&quot;)#\n\n// 3. Wrap the closing tag with surrounding markup using prepend and append\n#startFormTag(route=&quot;userSearch&quot;)#\n    &lt;!--- your form controls ---&gt;\n#endFormTag(prepend=&quot;&lt;/div&gt;&quot;, append=&quot;&lt;/section&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing the closing <code>form</code> tag.\n\n","parameters":[{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"endFormTag","tags":{"category":"General Form Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"generalformfunctions"}},{"returntype":"void","slug":"model.enum","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Map a `status` property to a comma-delimited list of allowed string values.\n//    Wheels auto-validates that `status` is one of the listed values,\n//    creates `isDraft()`, `isPublished()`, and `isArchived()` checker methods,\n//    and registers `draft()`, `published()`, and `archived()` query scopes.\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tenum(property=&quot;status&quot;, values=&quot;draft,published,archived&quot;);\n\t}\n}\n\n// 2. Map a `priority` property using a struct so that the stored database value\n//    differs from the human-readable name (0, 1, 2 are stored; low/medium/high are the names).\n//    Generated methods: `isLow()`, `isMedium()`, `isHigh()`.\n//    Generated scopes:  `model(&quot;Task&quot;).low()`, `model(&quot;Task&quot;).medium()`, `model(&quot;Task&quot;).high()`.\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tenum(property=&quot;priority&quot;, values={low: 0, medium: 1, high: 2});\n\t}\n}\n\n// 3. Using the generated checker methods and scopes at runtime.\n//    `isPublished()` returns true/false; `published()` scopes a finder to that status.\npost = model(&quot;Post&quot;).findByKey(key=42);\nif (post.isPublished()) {\n\twriteOutput(&quot;This post is live.&quot;);\n}\n\n// Find all published posts using the auto-generated scope.\npublishedPosts = model(&quot;Post&quot;).published().findAll();\n</code></pre>","hasExtended":true},"hint":"Maps a property to a set of named values (like Rails enums).\nGenerates boolean checker methods (<code>is<Value>()</code>), scopes for each value,\nand validates that the property value is one of the allowed values.\n\n","parameters":[{"type":"string","hint":"The name of the model property to map as an enum.","required":true,"name":"property"},{"type":"any","hint":"Either a comma-delimited list of string values (e.g. `\"draft,published,archived\"`) or a struct mapping names to stored values (e.g. `{low: 0, medium: 1, high: 2}`).","required":true,"name":"values"}],"name":"enum","tags":{"category":"Enum Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"enumfunctions"}},{"returntype":"struct","slug":"model.enumInfo","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Inspect all enum definitions on the Order model\ninfo = model(&quot;Order&quot;).enumInfo();\n// info -&gt; {\n//   status: {\n//     property: &quot;status&quot;,\n//     names: &quot;draft,published,archived&quot;,\n//     values: {draft: &quot;draft&quot;, published: &quot;published&quot;, archived: &quot;archived&quot;}\n//   }\n// }\n\n// 2. List all enum-mapped properties\ninfo = model(&quot;Order&quot;).enumInfo();\nfor (propName in info) {\n    writeOutput(propName &amp; &quot;: &quot; &amp; info[propName].names);\n}\n// status: draft,published,archived\n// priority: low,medium,high\n\n// 3. Use enum metadata to build a select list for a form\ninfo = model(&quot;Order&quot;).enumInfo();\nstatusEnum = info[&quot;status&quot;];\nfor (enumName in listToArray(statusEnum.names)) {\n    storedValue = statusEnum.values[enumName];\n    writeOutput(enumName &amp; &quot; -&gt; &quot; &amp; storedValue);\n}\n// draft -&gt; draft\n// published -&gt; published\n// archived -&gt; archived\n</code></pre>","hasExtended":true},"hint":"Returns a struct containing all enum definitions for this model.\nEach key is the property name, and the value contains <code>values</code> (name-to-stored-value mapping) and <code>names</code> (list of enum names).\n\n","parameters":[],"name":"enumInfo","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"controller.env","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Read a required environment variable\ndbUrl = env(&quot;DATABASE_URL&quot;);\n// dbUrl -&gt; &quot;postgres://user:pass@localhost/myapp&quot; (or &quot;&quot; if not set)\n\n// 2. Provide a default when the variable may be absent\nsmtpHost = env(&quot;SMTP_HOST&quot;, &quot;localhost&quot;);\n// smtpHost -&gt; &quot;localhost&quot; when SMTP_HOST is not defined in .env or system env\n\n// 3. Guard application startup based on an environment variable\nappSecret = env(&quot;APP_SECRET_KEY&quot;);\nif (!Len(appSecret)) {\n\tthrow(type=&quot;App.ConfigError&quot;, message=&quot;APP_SECRET_KEY must be set.&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Returns the value of an environment variable. Checks application.env (loaded from .env files) first, then falls back to system environment variables (server.system.environment). Returns the default if the variable is not found in either location.\n\n\nnamed argument <code>default</code> is also accepted for backwards compatibility\nwith pre-rename callers.","parameters":[{"type":"string","hint":"The environment variable name to look up.","required":true,"name":"name"},{"type":"any","hint":"Value to return if the variable is not found. The legacy","required":false,"name":"defaultValue","default":""}],"name":"env","tags":{"category":"Miscellaneous Functions","sectionClass":"configuration","section":"Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"numeric","slug":"model.errorCount","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check the total number of errors on an object\nif (author.errorCount() GTE 10) {\n    // Too many errors — bail out early\n}\n\n// 2. Check how many errors are associated with a specific property\nif (author.errorCount(property=&quot;email&quot;) gt 0) {\n    // The email property has at least one error\n}\n\n// 3. Count errors that were set with a specific error name\ncount = author.errorCount(name=&quot;invalidFormat&quot;);\n// count -&gt; 2 (two errors share the &quot;invalidFormat&quot; name)\n</code></pre>","hasExtended":true},"hint":"Returns the number of errors this object has associated with it.\nSpecify property or name if you wish to count only specific errors.\n\n","parameters":[{"type":"string","hint":"Specify a property name here if you want to count only errors set on a specific property.","required":false,"name":"property","default":""},{"type":"string","hint":"Specify an error name here if you want to count only errors set with a specific error name.","required":false,"name":"name","default":""}],"name":"errorCount","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"string","slug":"controller.errorMessageOn","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Display the first error message (if any) on the email property\n#errorMessageOn(objectName=&quot;user&quot;, property=&quot;email&quot;)#\n// -&gt; &lt;span class=&quot;error-message&quot;&gt;Email is not a valid email address.&lt;/span&gt;\n// -&gt; (empty string when no error exists on that property)\n\n// 2. Prepend and append custom text around the error message\n#errorMessageOn(objectName=&quot;user&quot;, property=&quot;username&quot;, prependText=&quot;Problem:&quot;, appendText=&quot;Please try again.&quot;)#\n// -&gt; &lt;span class=&quot;error-message&quot;&gt;Problem: Username has already been taken. Please try again.&lt;/span&gt;\n\n// 3. Wrap the message in a div with a custom CSS class instead of the default span\n#errorMessageOn(objectName=&quot;post&quot;, property=&quot;title&quot;, wrapperElement=&quot;div&quot;, class=&quot;field-error&quot;)#\n// -&gt; &lt;div class=&quot;field-error&quot;&gt;Title can't be blank.&lt;/div&gt;\n</code></pre>","hasExtended":true},"hint":"Returns the error message, if one exists, on the object's property.\nIf multiple error messages exist, the first one is returned.\n\n","parameters":[{"type":"string","hint":"The variable name of the object to display the error message for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to display the error message for.","required":true,"name":"property"},{"type":"string","hint":"String to prepend to the error message.","required":false,"name":"prependText","default":""},{"type":"string","hint":"String to append to the error message.","required":false,"name":"appendText","default":""},{"type":"string","hint":"HTML element to wrap the error message in.","required":false,"name":"wrapperElement","default":"span"},{"type":"string","hint":"CSS `class` to set on the wrapper element.","required":false,"name":"class","default":"error-message"},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"errorMessageOn","tags":{"category":"Error Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"errorfunctions"}},{"returntype":"string","slug":"controller.errorMessagesFor","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Display all error messages for a user object\n#errorMessagesFor(objectName=&quot;user&quot;)#\n// -&gt; &lt;ul class=&quot;error-messages&quot;&gt;&lt;li&gt;Email is not a valid email address.&lt;/li&gt;&lt;li&gt;Username can't be blank.&lt;/li&gt;&lt;/ul&gt;\n// -&gt; (empty string when the object has no errors)\n\n// 2. Use a custom CSS class on the wrapping ul element\n#errorMessagesFor(objectName=&quot;user&quot;, class=&quot;form-errors&quot;)#\n// -&gt; &lt;ul class=&quot;form-errors&quot;&gt;&lt;li&gt;Email is not a valid email address.&lt;/li&gt;&lt;/ul&gt;\n\n// 3. Suppress duplicate error messages\n#errorMessagesFor(objectName=&quot;user&quot;, showDuplicates=false)#\n// -&gt; &lt;ul class=&quot;error-messages&quot;&gt;&lt;li&gt;can't be blank.&lt;/li&gt;&lt;/ul&gt;\n// (only one &quot;can't be blank.&quot; entry even if multiple fields have the same message)\n\n// 4. Include errors from associated objects as well\n#errorMessagesFor(objectName=&quot;order&quot;, includeAssociations=true)#\n// -&gt; &lt;ul class=&quot;error-messages&quot;&gt;&lt;li&gt;Name can't be blank.&lt;/li&gt;&lt;li&gt;Line items quantity must be greater than zero.&lt;/li&gt;&lt;/ul&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a list (<code>ul</code> tag with a default <code>class</code> of <code>error-messages</code>) containing all the error messages for all the properties of the object.\nReturns an empty string if no errors exist.\n\n","parameters":[{"type":"string","hint":"The variable name of the object to display error messages for.","required":true,"name":"objectName"},{"type":"string","hint":"CSS `class` to set on the `ul` element.","required":false,"name":"class","default":"error-messages"},{"type":"boolean","hint":"Whether or not to show duplicate error messages.","required":false,"name":"showDuplicates","default":true},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"boolean","required":false,"name":"includeAssociations","default":true}],"name":"errorMessagesFor","tags":{"category":"Error Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"errorfunctions"}},{"returntype":"array","slug":"model.errorsOn","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all errors associated with the emailAddress property\nerrors = user.errorsOn(&quot;emailAddress&quot;);\n// errors -&gt; [{property: &quot;emailAddress&quot;, message: &quot;is invalid&quot;, name: &quot;&quot;}, ...]\n\n// 2. Get only errors on emailAddress that were set with a specific error name\nerrors = user.errorsOn(property=&quot;emailAddress&quot;, name=&quot;formatCheck&quot;);\n// errors -&gt; [{property: &quot;emailAddress&quot;, message: &quot;must be a valid email&quot;, name: &quot;formatCheck&quot;}]\n\n// 3. Check errors on a property and loop over them\nerrors = user.errorsOn(&quot;username&quot;);\nfor (error in errors) {\n    writeOutput(error.message);\n}\n</code></pre>","hasExtended":true},"hint":"Returns an array of all errors associated with the supplied property (and error name if passed in).\n\n","parameters":[{"type":"string","hint":"Specify the property name to return errors for here.","required":true,"name":"property"},{"type":"string","hint":"If you want to return only errors on the property set with a specific error name you can specify it here.","required":false,"name":"name","default":""}],"name":"errorsOn","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"array","slug":"model.errorsOnBase","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all general (base) errors for a model object after validation\nuser = model(&quot;User&quot;).new(params.user);\nuser.valid();\nerrors = user.errorsOnBase();\n// errors -&gt; [{property: &quot;&quot;, message: &quot;Account has been suspended&quot;, name: &quot;&quot;}]\n\n// 2. Filter base errors by a specific error name\nuser.addErrorToBase(message=&quot;Account has been suspended&quot;, name=&quot;suspended&quot;);\nuser.addErrorToBase(message=&quot;Please accept the terms&quot;, name=&quot;terms&quot;);\nsuspendedErrors = user.errorsOnBase(name=&quot;suspended&quot;);\n// suspendedErrors -&gt; [{property: &quot;&quot;, message: &quot;Account has been suspended&quot;, name: &quot;suspended&quot;}]\n\n// 3. Check for base errors and display them\nerrors = user.errorsOnBase();\nif (arrayLen(errors)) {\n    for (e in errors) {\n        writeOutput(e.message);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Returns an array of all errors associated with the object as a whole (not related to any specific property).\n\n","parameters":[{"type":"string","hint":"Specify an error name here to only return errors for that error name.","required":false,"name":"name","default":""}],"name":"errorsOnBase","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"string","slug":"controller.excerpt","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Extract text around a matching phrase with a custom radius\nresult = excerpt(text=&quot;CFWheels is a Rails-like MVC framework for Adobe ColdFusion and Lucee&quot;, phrase=&quot;framework&quot;, radius=5);\n// result -&gt; &quot;...MVC framework for Ad...&quot;\n\n// 2. Use the default radius of 100 characters\nresult = excerpt(text=&quot;CFWheels is a powerful MVC framework built for ColdFusion developers who want to move fast.&quot;, phrase=&quot;powerful&quot;);\n// result -&gt; &quot;CFWheels is a powerful MVC framework built for ColdFusion developers who want to move fast.&quot;\n\n// 3. Customize the excerpt string used to indicate truncated text\nresult = excerpt(text=&quot;The quick brown fox jumps over the lazy dog&quot;, phrase=&quot;fox&quot;, radius=5, excerptString=&quot; [...]&quot;);\n// result -&gt; &quot; [...]brown fox jumps [...]&quot;\n</code></pre>","hasExtended":true},"hint":"Extracts an excerpt from text that matches the first instance of a given phrase.\n\n","parameters":[{"type":"string","hint":"The text to extract an excerpt from.","required":true,"name":"text"},{"type":"string","hint":"The phrase to extract.","required":true,"name":"phrase"},{"type":"numeric","hint":"Number of characters to extract surrounding the phrase.","required":false,"name":"radius","default":100},{"type":"string","hint":"String to replace first and / or last characters with.","required":false,"name":"excerptString","default":"..."}],"name":"excerpt","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"void","slug":"migration.execute","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Run a raw SQL statement during a migration\nexecute(sql = &quot;UPDATE users SET active = 1 WHERE active IS NULL&quot;);\n\n// 2. Create a database view with raw SQL\nexecute(sql = &quot;CREATE VIEW active_users AS SELECT * FROM users WHERE active = 1&quot;);\n\n// 3. Use execute() inside up() and down() to apply and reverse a custom SQL change\ncomponent extends=&quot;wheels.migrator.Migration&quot; {\n    function up() {\n        execute(sql = &quot;ALTER TABLE orders ADD COLUMN notes TEXT&quot;);\n    }\n    function down() {\n        execute(sql = &quot;ALTER TABLE orders DROP COLUMN notes&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Executes a raw sql query\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"Arbitrary SQL String","required":true,"name":"sql"}],"name":"execute","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"boolean","slug":"model.exists","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if any record exists in the table\nanyUsers = model(&quot;User&quot;).exists();\n\n// 2. Check if a record with a specific primary key exists\nresult = model(&quot;User&quot;).exists(key=params.key);\n\n// 3. Check if a record matching a WHERE condition exists\njoeExists = model(&quot;User&quot;).exists(where=&quot;firstName = 'Joe'&quot;);\n\n// 4. Use the result in a conditional\nif (model(&quot;User&quot;).exists(key=params.userId)) {\n\t// record was found, proceed\n}\n\n// 5. Include soft-deleted records in the check\ndeletedExists = model(&quot;User&quot;).exists(where=&quot;email='old@example.com'&quot;, includeSoftDeletes=true);\n\n// 6. If you have a `belongsTo` association from `Comment` to `Post`, you can do a scoped call. (The `hasPost` method below calls `model(&quot;Post&quot;).exists(comment.postId)` internally.)\ncomment = model(&quot;Comment&quot;).findByKey(params.commentId);\ncommentHasAPost = comment.hasPost();\n\n// 7. If you have a `hasOne` association from `User` to `Profile`, you can do a scoped call. (The `hasProfile` method below calls `model(&quot;Profile&quot;).exists(where=&quot;userId=#user.id#&quot;)` internally.)\nuser = model(&quot;User&quot;).findByKey(params.userId);\nuserHasProfile = user.hasProfile();\n\n// 8. If you have a `hasMany` association from `Post` to `Comment`, you can do a scoped call. (The `hasComments` method below calls `model(&quot;Comment&quot;).exists(where=&quot;postId=#post.id#&quot;)` internally.)\npost = model(&quot;Post&quot;).findByKey(params.postId);\npostHasComments = post.hasComments();\n</code></pre>","hasExtended":true},"hint":"Checks if a record exists in the table.\nYou can pass in either a primary key value to the <code>key</code> argument or a string to the <code>where</code> argument.\nIf you don't pass in either of those, it will simply check if any record exists in the table.\n\n","parameters":[{"type":"any","hint":"Primary key value(s) of the record. Separate with comma if passing in multiple primary key values. Accepts a string, list, or a numeric value.","required":false,"name":"key"},{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where"},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes"}],"name":"exists","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.fileField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic file upload field bound to an object and property\n#fileField(objectName=&quot;photo&quot;, property=&quot;imageFile&quot;)#\n\n// 2. Provide a custom label for the file field\n#fileField(label=&quot;Profile Photo&quot;, objectName=&quot;user&quot;, property=&quot;avatar&quot;)#\n\n// 3. Display file upload fields for a hasMany association using nested properties\n&lt;fieldset&gt;\n\t&lt;legend&gt;Screenshots&lt;/legend&gt;\n\t&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(site.screenshots)#&quot; index=&quot;i&quot;&gt;\n\t\t#fileField(label=&quot;File ##i#&quot;, objectName=&quot;site&quot;, association=&quot;screenshots&quot;, position=i, property=&quot;file&quot;)#\n\t\t#textField(label=&quot;Caption ##i#&quot;, objectName=&quot;site&quot;, association=&quot;screenshots&quot;, position=i, property=&quot;caption&quot;)#\n\t&lt;/cfloop&gt;\n&lt;/fieldset&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a file field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"fileField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.fileFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic file upload field with a label\n#fileFieldTag(name=&quot;photo&quot;, label=&quot;Profile Photo&quot;)#\n\n// 2. File upload field with a CSS class and no label\n#fileFieldTag(name=&quot;attachment&quot;, class=&quot;upload-input&quot;)#\n\n// 3. File upload field with label placement and wrapper HTML\n#fileFieldTag(name=&quot;resume&quot;, label=&quot;Upload Resume&quot;, labelPlacement=&quot;before&quot;, prepend=&quot;&lt;div class='field'&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a file form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"fileFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"array","slug":"controller.filterChain","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the entire filter chain for the current controller\nmyFilterChain = filterChain();\n// myFilterChain -&gt; array of structs, each with keys: through, type, only, except, arguments\n// e.g. [{ through: &quot;checkLogin&quot;, type: &quot;before&quot;, only: &quot;&quot;, except: &quot;&quot; }, ...]\n\n// 2. Get only the before-filters\nbeforeFilters = filterChain(type=&quot;before&quot;);\nfor (f in beforeFilters) {\n    writeOutput(f.through);\n}\n\n// 3. Get only the after-filters\nafterFilters = filterChain(type=&quot;after&quot;);\nwriteOutput(arrayLen(afterFilters));\n</code></pre>","hasExtended":true},"hint":"Returns an array of all the filters set on current controller in the order in which they will be executed.\n\n","parameters":[{"type":"string","hint":"Use this argument to return only before or after filters.","required":false,"name":"type","default":"all"}],"name":"filterChain","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"void","slug":"controller.filters","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Run `restrictAccess` before every action in this controller (declared inside config()).\nfilters(&quot;restrictAccess&quot;);\n\n// 2. Run two before-filters on every action except `home` and `login`.\nfilters(through=&quot;isLoggedIn, checkIPAddress&quot;, except=&quot;home, login&quot;);\n\n// 3. Run `auditLog` after only the `create`, `update`, and `delete` actions.\nfilters(through=&quot;auditLog&quot;, type=&quot;after&quot;, only=&quot;create, update, delete&quot;);\n\n// 4. Prepend a filter so it runs before any already-registered filters.\nfilters(through=&quot;maintenanceCheck&quot;, placement=&quot;prepend&quot;);\n\n// Note: filter functions must be declared as `private` in the controller\n// to prevent them from being routed as public actions.\n// Example controller setup:\n// component extends=&quot;Controller&quot; {\n//     function config() {\n//         filters(&quot;restrictAccess&quot;);\n//     }\n//     private function restrictAccess() {\n//         if (!isLoggedIn()) {\n//             redirectTo(route=&quot;login&quot;);\n//         }\n//     }\n// }\n</code></pre>","hasExtended":true},"hint":"Tells Wheels to run a function before an action is run or after an action has been run.\n\n","parameters":[{"type":"string","hint":"Function(s) to execute before or after the action(s).","required":true,"name":"through"},{"type":"string","hint":"Whether to run the function(s) before or after the action(s).","required":false,"name":"type","default":"before"},{"type":"string","hint":"Pass in a list of action names (or one action name) to tell Wheels that the filter function(s) should only be run on these actions.","required":false,"name":"only","default":""},{"type":"string","hint":"Pass in a list of action names (or one action name) to tell Wheels that the filter function(s) should be run on all actions except the specified ones.","required":false,"name":"except","default":""},{"type":"string","hint":"Pass in `prepend` to prepend the function(s) to the filter chain instead of appending.","required":false,"name":"placement","default":"append"}],"name":"filters","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"any","slug":"model.findAll","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all users ordered by last name\nusers = model(&quot;user&quot;).findAll(order=&quot;lastName ASC&quot;);\n\n// 2. Get only 5 users in a random order\nfiveRandomUsers = model(&quot;user&quot;).findAll(maxRows=5, order=&quot;random&quot;);\n\n// 3. Include a belongsTo association and filter with a WHERE clause\narticles = model(&quot;article&quot;).findAll(include=&quot;author&quot;, where=&quot;published=1&quot;, order=&quot;createdAt DESC&quot;);\n\n// 4. Include a hasMany association in the opposite direction\nbobsArticles = model(&quot;author&quot;).findAll(include=&quot;articles&quot;, where=&quot;firstName='Bob'&quot;);\n\n// 5. Use pagination (records 26-50) with a nested include (song belongsTo album, album belongsTo artist)\nsongs = model(&quot;song&quot;).findAll(include=&quot;album(artist)&quot;, page=2, perPage=25);\n\n// 6. Return results as an array of model objects instead of a query\nactiveUsers = model(&quot;user&quot;).findAll(where=&quot;active=1&quot;, order=&quot;lastName ASC&quot;, returnAs=&quot;objects&quot;);\nfor (user in activeUsers) {\n\twriteOutput(user.firstName &amp; &quot; &quot; &amp; user.lastName);\n}\n\n// 7. Return results as an array of structs\nuserStructs = model(&quot;user&quot;).findAll(where=&quot;active=1&quot;, returnAs=&quot;structs&quot;);\n\n// 8. Use a dynamic finder to get all books released in a certain year\n// (same as model(&quot;book&quot;).findAll(where=&quot;releaseYear=#params.year#&quot;))\nbooks = model(&quot;book&quot;).findAllByReleaseYear(params.year);\n\n// 9. Use a dynamic finder with multiple criteria\n// (same as model(&quot;book&quot;).findAll(where=&quot;releaseYear=#params.year# AND type='#params.type#'&quot;))\nbooks = model(&quot;book&quot;).findAllByReleaseYearAndType(&quot;#params.year#,#params.type#&quot;);\n\n// 10. Use a scoped call via a hasMany association (calls findAll internally with a where clause)\npost = model(&quot;post&quot;).findByKey(params.postId);\ncomments = post.comments();\n\n// 11. Use GROUP BY with a calculated property (generates HAVING instead of WHERE)\n// Order model has a calculated property: property(name=&quot;totalAmount&quot;, sql=&quot;SUM(amount)&quot;)\nids = model(&quot;order&quot;).findAll(group=&quot;productId&quot;, where=&quot;totalAmount &gt; 1000&quot;, select=&quot;productId&quot;);\n\n// 12. Include soft-deleted records\nallUsers = model(&quot;user&quot;).findAll(includeSoftDeletes=true, order=&quot;lastName ASC&quot;);\n\n// 13. Cache the query results for 10 minutes\ncachedUsers = model(&quot;user&quot;).findAll(where=&quot;active=1&quot;, cache=10);\n\n// 14. Return the generated SQL string instead of running the query\nsql = model(&quot;user&quot;).findAll(where=&quot;active=1&quot;, order=&quot;lastName ASC&quot;, returnAs=&quot;sql&quot;);\n// sql -&gt; &quot;SELECT ... FROM users WHERE active = 1 ORDER BY last_name ASC&quot;\n\n// 15. Use index hints (MySQL and SQL Server only)\nindexes = {\n\tauthor=&quot;idx_authors_name&quot;,\n\tpost=&quot;idx_posts_created&quot;\n};\nposts = model(&quot;author&quot;).findAll(\n\twhere=&quot;firstName LIKE '#params.q#%' OR subject LIKE '#params.q#%'&quot;,\n\tinclude=&quot;posts&quot;,\n\tuseIndex=indexes\n);\n</code></pre>","hasExtended":true},"hint":"Returns records from the database table mapped to this model according to the arguments passed in (use the <code>where</code> argument to decide which records to get, use the <code>order</code> argument to set the order in which those records should be returned, and so on).\nThe records will be returned as either a <code>cfquery</code> result set, an array of objects, or an array of structs (depending on what the <code>returnAs</code> argument is set to).\n\n","parameters":[{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"order","default":""},{"type":"string","hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"group","default":""},{"type":"string","hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","required":false,"name":"select","default":""},{"type":"string","hint":"List of calculated property names (declared via `property(name=\"...\", sql=\"...\", select=false)`) to additively opt into this finder's `SELECT` clause. Unlike `select`, this does not replace the default column list — the named calculated properties are merged on top of all default columns, so the rest of the record is still returned. Useful for pulling a `select=false` computed property back in on a single finder without spelling out every other column. Unknown names throw `Wheels.CalculatedPropertyNotFound` in `development`/`testing` and are ignored in `production`.","required":false,"name":"includeCalculated","default":""},{"type":"boolean","hint":"Whether to add the `DISTINCT` keyword to your `SELECT` clause. Wheels will, when necessary, add this automatically (when using pagination and a `hasMany` association is used in the `include` argument, to name one example).","required":false,"name":"distinct","default":"false"},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"numeric","hint":"Maximum number of records to retrieve. Passed on to the `maxRows` `cfquery` attribute. The default, `-1`, means that all records will be retrieved.","required":false,"name":"maxRows","default":"-1"},{"type":"numeric","hint":"If you want to paginate records, you can do so by specifying a page number here. For example, getting records 11-20 would be page number 2 when `perPage` is kept at the default setting (10 records per page). The default, 0, means that records won't be paginated and that the `perPage` and `count` arguments will be ignored.","required":false,"name":"page","default":"0"},{"type":"numeric","hint":"When using pagination, you can specify how many records you want to fetch per page here. This argument is only used when the `page` argument has been passed in.","required":false,"name":"perPage","default":10},{"type":"numeric","hint":"When using pagination and you know in advance how many records you want to paginate through, you can pass in that value here. Doing so will prevent Wheels from running a `COUNT` query to get this value. This argument is only used when the `page` argument has been passed in.","required":false,"name":"count","default":"0"},{"type":"string","hint":"Handle to use for the query. This is used when you're paginating multiple queries and need to reference them individually in the `paginationLinks()` function. It's also used to set the name of the query in the debug output (which otherwise defaults to `userFindAllQuery` for example).","required":false,"name":"handle","default":"query"},{"type":"any","hint":"If you want to cache the query, you can do so by specifying the number of minutes you want to cache the query for here. If you set it to `true`, the default cache time will be used (60 minutes).","required":false,"name":"cache","default":""},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"string","hint":"Set to `objects` to return an array of objects, set to `structs` to return an array of structs, set to `query` to return a query result set, or set to 'sql' to return the executed SQL query as a string.","required":false,"name":"returnAs","default":"query"},{"type":"boolean","hint":"When `returnAs` is set to `objects`, you can set this argument to `false` to prevent returning objects fetched from associations specified in the `include` argument. This is useful when you only need to include associations for use in the `WHERE` clause only and want to avoid the performance hit that comes with object creation.","required":false,"name":"returnIncluded","default":true},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":"true"},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"},{"type":"struct","hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","required":false,"name":"useIndex","default":"[runtime expression]"},{"type":"string","hint":"Override the default datasource","required":false,"name":"dataSource","default":"[runtime expression]"},{"type":"numeric","required":false,"name":"$limit","default":"0"},{"type":"numeric","required":false,"name":"$offset","default":"0"},{"type":"boolean","required":false,"name":"$forUpdate","default":"false"},{"type":"boolean","required":false,"name":"$useRequestCache","default":"true"}],"name":"findAll","tags":{"category":"Read Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"readfunctions"}},{"returntype":"string","slug":"model.findAllKeys","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get a comma-delimited list of all primary key values for the Artist model\nprimaryKeyList = model(&quot;artist&quot;).findAllKeys();\n// primaryKeyList -&gt; &quot;1,2,3,4,5&quot;\n\n// 2. Get keys for active artists only, enclosed in single quotes, separated by a pipe\nprimaryKeyList = model(&quot;artist&quot;).findAllKeys(quoted=true, delimiter=&quot;|&quot;, where=&quot;active=1&quot;);\n// primaryKeyList -&gt; &quot;'1'|'3'|'5'&quot;\n\n// 3. Use the result directly in a SQL IN clause for a subsequent query\nkeyList = model(&quot;artist&quot;).findAllKeys(quoted=true, where=&quot;genreId=7&quot;);\nalbums = model(&quot;album&quot;).findAll(where=&quot;artistId IN (#keyList#)&quot;);\n</code></pre>","hasExtended":true},"hint":"Returns all primary key values in a list.\nIn addition to <code>quoted</code> and <code>delimiter</code> you can pass in any argument that <code>findAll()</code> accepts.\n\n","parameters":[{"type":"boolean","hint":"Set to `true` to enclose each value in single-quotation marks.","required":false,"name":"quoted","default":"false"},{"type":"string","hint":"The delimiter character to separate the list items with.","required":false,"name":"delimiter","default":","}],"name":"findAllKeys","tags":{"category":"Read Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"readfunctions"}},{"returntype":"any","slug":"model.findByKey","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the author with the primary key value `99` as an object\nauth = model(&quot;author&quot;).findByKey(99);\n\n// 2. Get an author based on a form/URL value and handle the not-found case\nauth = model(&quot;author&quot;).findByKey(params.key);\nif (!isObject(auth)) {\n    flashInsert(message=&quot;Author #params.key# was not found&quot;);\n    redirectTo(back=true);\n}\n\n// 3. Fetch only selected columns for a record\nuser = model(&quot;user&quot;).findByKey(key=params.id, select=&quot;id,firstName,email&quot;);\n\n// 4. Include a belongsTo association when fetching by key\norder = model(&quot;order&quot;).findByKey(key=params.orderId, include=&quot;customer&quot;);\n\n// 5. Cache the lookup for 10 minutes and include soft-deleted records\nproduct = model(&quot;product&quot;).findByKey(key=params.id, cache=10, includeSoftDeletes=true);\n\n// 6. Use a scoped call via a belongsTo association (calls `model(&quot;post&quot;).findByKey(comment.postId)` internally)\ncomment = model(&quot;comment&quot;).findByKey(params.commentId);\npost = comment.post();\n</code></pre>","hasExtended":true},"hint":"Fetches the requested record by primary key and returns it as an object.\nReturns <code>false</code> if no record is found.\nYou can override this behavior to return a <code>cfquery</code> result set instead, similar to what's described in the documentation for <code>findOne()</code>.\n\n","parameters":[{"type":"any","hint":"Primary key value(s) of the record. Separate with comma if passing in multiple primary key values. Accepts a string, list, or a numeric value.","required":true,"name":"key"},{"type":"string","hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","required":false,"name":"select","default":""},{"type":"string","hint":"List of calculated property names (declared via `property(name=\"...\", sql=\"...\", select=false)`) to additively opt into this finder's `SELECT` clause. Unlike `select`, this does not replace the default column list — the named calculated properties are merged on top of all default columns, so the rest of the record is still returned. Useful for pulling a `select=false` computed property back in on a single finder without spelling out every other column. Unknown names throw `Wheels.CalculatedPropertyNotFound` in `development`/`testing` and are ignored in `production`.","required":false,"name":"includeCalculated","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"string","hint":"Handle to use for the query. This is used to set the name of the query in the debug output (which otherwise defaults to `userFindOneQuery` for example).","required":false,"name":"handle","default":"query"},{"type":"any","hint":"If you want to cache the query, you can do so by specifying the number of minutes you want to cache the query for here. If you set it to `true`, the default cache time will be used (60 minutes).","required":false,"name":"cache","default":""},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"string","hint":"Set to `objects` to return an array of objects, set to `structs` to return an array of structs, set to `query` to return a query result set, or set to 'sql' to return the executed SQL query as a string.","required":false,"name":"returnAs","default":"object"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":"true"},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"},{"type":"string","hint":"Override the default datasource","required":false,"name":"dataSource","default":"[runtime expression]"}],"name":"findByKey","tags":{"category":"Read Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"readfunctions"}},{"returntype":"void","slug":"model.findEach","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Send a newsletter email to every subscriber one at a time\nmodel(&quot;Subscriber&quot;).findEach(callback = function(subscriber) {\n    sendEmail(\n        to = subscriber.email,\n        subject = &quot;Monthly Newsletter&quot;,\n        template = &quot;/emails/newsletter&quot;,\n        subscriber = subscriber\n    );\n});\n\n// 2. Process users as structs and write a report entry for each one\nmodel(&quot;User&quot;).findEach(\n    where = &quot;active = 1&quot;,\n    order = &quot;lastName ASC&quot;,\n    returnAs = &quot;struct&quot;,\n    callback = function(user) {\n        writeLog(&quot;Processing user: #user.firstName# #user.lastName#&quot;);\n    }\n);\n\n// 3. Archive old orders in smaller batches to reduce memory pressure\nmodel(&quot;Order&quot;).findEach(\n    where = &quot;createdAt &lt; '#DateFormat(DateAdd('yyyy', -2, Now()), 'yyyy-mm-dd')#'&quot;,\n    batchSize = 250,\n    callback = function(order) {\n        order.archived = true;\n        order.save();\n    }\n);\n</code></pre>","hasExtended":true},"hint":"Processes large result sets one record at a time without loading everything into memory.\nInternally paginates through records and invokes the callback for each individual record.\nThe callback receives a model object (when <code>returnAs</code> is <code>\"object\"</code>) or a struct representing one row.\n\n","parameters":[{"type":"numeric","hint":"Number of records to load per internal database query. Defaults to 1000.","required":false,"name":"batchSize","default":1000},{"type":"any","hint":"A function/closure to call for each record. Receives a single argument: the record (object or struct).","required":true,"name":"callback"},{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"order","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"string","hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","required":false,"name":"select","default":""},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize"},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":false},{"type":"string","hint":"Whether each record is an \"object\" (default) or \"struct\".","required":false,"name":"returnAs","default":"object"}],"name":"findEach","tags":{"category":"Read Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"readfunctions"}},{"returntype":"any","slug":"model.findFirst","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the first user record (ordered by primary key ascending)\nuser = model(&quot;User&quot;).findFirst();\n// Returns the model object with the lowest primary key value, or false if no records exist.\n\n// 2. Get the first user ordered by a specific property\nuser = model(&quot;User&quot;).findFirst(property=&quot;createdAt&quot;);\n// Returns the oldest user (lowest createdAt value).\n\n// 3. Get the first active user ordered by last name, then first name\nuser = model(&quot;User&quot;).findFirst(properties=&quot;lastName,firstName&quot;, where=&quot;active = 1&quot;);\n// Equivalent to: ORDER BY lastName ASC, firstName ASC with a WHERE clause applied.\n// Returns a model object, or false if no matching record is found.\n</code></pre>","hasExtended":true},"hint":"Fetches the first record ordered by primary key value.\nUse the <code>property</code> argument to order by something else.\nReturns a model object.\n\n","parameters":[{"type":"string","hint":"Name of the property to order by. This argument is also aliased as `properties`.","required":false,"name":"property","default":"[runtime expression]"},{"type":"string","required":false,"name":"$sort","default":"ASC"}],"name":"findFirst","tags":{"category":"Read Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"readfunctions"}},{"returntype":"void","slug":"model.findInBatches","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Process all users in batches of 500 (default), logging each batch\nmodel(&quot;User&quot;).findInBatches(callback=function(batch) {\n\twriteOutput(&quot;Processing &quot; &amp; batch.recordCount &amp; &quot; users&quot;);\n});\n\n// 2. Process active orders in batches of 200, filtered with a WHERE clause\nmodel(&quot;Order&quot;).findInBatches(\n\tbatchSize=200,\n\twhere=&quot;status='active'&quot;,\n\torder=&quot;createdAt ASC&quot;,\n\tcallback=function(batch) {\n\t\t// batch is a cfquery result set by default\n\t\tfor (local.i = 1; local.i &lt;= batch.recordCount; local.i++) {\n\t\t\twriteOutput(batch.orderId[local.i] &amp; &quot;: &quot; &amp; batch.total[local.i]);\n\t\t}\n\t}\n);\n\n// 3. Receive each batch as an array of model objects instead of a query\nmodel(&quot;User&quot;).findInBatches(\n\tbatchSize=100,\n\treturnAs=&quot;objects&quot;,\n\twhere=&quot;active=1&quot;,\n\tcallback=function(batch) {\n\t\tfor (user in batch) {\n\t\t\tuser.sendNewsletter();\n\t\t}\n\t}\n);\n\n// 4. Receive each batch as an array of structs\nmodel(&quot;Product&quot;).findInBatches(\n\tbatchSize=250,\n\treturnAs=&quot;structs&quot;,\n\tselect=&quot;id,name,price&quot;,\n\tcallback=function(batch) {\n\t\tfor (product in batch) {\n\t\t\twriteOutput(product.name &amp; &quot; costs &quot; &amp; product.price);\n\t\t}\n\t}\n);\n\n// 5. Include soft-deleted records while processing in batches\nmodel(&quot;User&quot;).findInBatches(\n\tincludeSoftDeletes=true,\n\tcallback=function(batch) {\n\t\twriteOutput(&quot;Batch has &quot; &amp; batch.recordCount &amp; &quot; records (including deleted)&quot;);\n\t}\n);\n</code></pre>","hasExtended":true},"hint":"Processes large result sets in batches without loading everything into memory at once.\nThe callback receives a query result set (or array of objects/structs) for each batch.\n\n","parameters":[{"type":"numeric","hint":"Number of records per batch. Defaults to 500.","required":false,"name":"batchSize","default":500},{"type":"any","hint":"A function/closure to call for each batch. Receives a single argument: the batch (query, array of objects, or array of structs depending on `returnAs`).","required":true,"name":"callback"},{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"order","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"string","hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","required":false,"name":"select","default":""},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize"},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":false},{"type":"string","hint":"Set to \"query\" (default), \"objects\", or \"structs\" for the batch format.","required":false,"name":"returnAs","default":"query"}],"name":"findInBatches","tags":{"category":"Read Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"readfunctions"}},{"returntype":"any","slug":"model.findLastOne","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the last user record (ordered by primary key descending)\nlastUser = model(&quot;User&quot;).findLastOne();\n// Returns a User object for the record with the highest primary key, or false if none exist.\n\n// 2. Get the most recently created post by ordering on a different property\nlatestPost = model(&quot;Post&quot;).findLastOne(property=&quot;createdAt&quot;);\n// Returns the Post object with the latest createdAt value.\n\n// 3. Get the last active product, using a where clause alongside the property order\nlastActive = model(&quot;Product&quot;).findLastOne(property=&quot;updatedAt&quot;, where=&quot;isActive = 1&quot;);\n// Returns the most recently updated active product, or false if none exist.\n</code></pre>","hasExtended":true},"hint":"Fetches the last record ordered by primary key value.\nUse the <code>property</code> argument to order by something else.\nReturns a model object. Formerly known as findLast.\n\n","parameters":[{"type":"string","hint":"Name of the property to order by. This argument is also aliased as `properties`.","required":false,"name":"property"}],"name":"findLastOne","tags":{"category":"Read Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"readfunctions"}},{"returntype":"any","slug":"model.findOne","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the most recent order as an object from the database\norder = model(&quot;Order&quot;).findOne(order=&quot;datePurchased DESC&quot;);\n\n// 2. Use a where clause to find the first user with a specific email address\nuser = model(&quot;User&quot;).findOne(where=&quot;email='someone@example.com'&quot;);\n\n// 3. Use a dynamic finder to get the first person with the last name Smith.\n// Equivalent to: model(&quot;User&quot;).findOne(where=&quot;lastName='Smith'&quot;)\nperson = model(&quot;User&quot;).findOneByLastName(&quot;Smith&quot;);\n\n// 4. Use a dynamic finder to match on two columns.\n// Equivalent to: model(&quot;User&quot;).findOne(where=&quot;email='someone@example.com' AND password='mypass'&quot;)\nuser = model(&quot;User&quot;).findOneByEmailAndPassword(&quot;someone@example.com&quot;, &quot;mypass&quot;);\n\n// 5. Return false when no matching record is found (the default returnAs=&quot;object&quot; behavior)\nuser = model(&quot;User&quot;).findOne(where=&quot;email='unknown@example.com'&quot;);\nif (!isObject(user)) {\n    writeOutput(&quot;No user found.&quot;);\n}\n\n// 6. Return as a query result set instead of an object\nuserQuery = model(&quot;User&quot;).findOne(where=&quot;role='admin'&quot;, returnAs=&quot;query&quot;);\n\n// 7. Use a scoped call via a hasOne association from User to Profile.\n// The profile() method calls model(&quot;Profile&quot;).findOne(where=&quot;userId=#user.id#&quot;) internally.\nuser = model(&quot;User&quot;).findByKey(params.userId);\nprofile = user.profile();\n\n// 8. Use a scoped call via a hasMany association from Post to Comment.\n// The findOneComment() method calls model(&quot;Comment&quot;).findOne(where=&quot;postId=#post.id#&quot;) internally.\npost = model(&quot;Post&quot;).findByKey(params.postId);\ncomment = post.findOneComment(where=&quot;approved=1&quot;);\n</code></pre>","hasExtended":true},"hint":"Fetches the first record found based on the <code>WHERE</code> and <code>ORDER BY</code> clauses.\nWith the default settings (i.e. the <code>returnAs</code> argument set to <code>object</code>), a model object will be returned if the record is found and the boolean value <code>false</code> if not.\nInstead of using the <code>where</code> argument, you can create cleaner code by making use of a concept called Dynamic Finders.\n\n","parameters":[{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"order","default":""},{"type":"string","hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","required":false,"name":"select","default":""},{"type":"string","hint":"List of calculated property names (declared via `property(name=\"...\", sql=\"...\", select=false)`) to additively opt into this finder's `SELECT` clause. Unlike `select`, this does not replace the default column list — the named calculated properties are merged on top of all default columns, so the rest of the record is still returned. Useful for pulling a `select=false` computed property back in on a single finder without spelling out every other column. Unknown names throw `Wheels.CalculatedPropertyNotFound` in `development`/`testing` and are ignored in `production`.","required":false,"name":"includeCalculated","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"string","hint":"Handle to use for the query. This is used to set the name of the query in the debug output (which otherwise defaults to `userFindOneQuery` for example).","required":false,"name":"handle","default":"query"},{"type":"any","hint":"If you want to cache the query, you can do so by specifying the number of minutes you want to cache the query for here. If you set it to `true`, the default cache time will be used (60 minutes).","required":false,"name":"cache","default":""},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"string","hint":"Set to `objects` to return an array of objects, set to `structs` to return an array of structs, set to `query` to return a query result set, or set to 'sql' to return the executed SQL query as a string.","required":false,"name":"returnAs","default":"object"},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"},{"type":"struct","hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","required":false,"name":"useIndex","default":"[runtime expression]"},{"type":"string","hint":"Override the default datasource","required":false,"name":"dataSource","default":"[runtime expression]"}],"name":"findOne","tags":{"category":"Read Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"readfunctions"}},{"returntype":"string","slug":"controller.firstPageLink","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>//--------------------------------------------------------------------\n// Example 1: Basic usage — show a &quot;First&quot; link at the top of a\n// paginated list; renders a disabled span when already on page 1\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts = model(&quot;Post&quot;).findAll(page=params.page, perPage=10, order=&quot;createdAt DESC&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #firstPageLink()#\n    #previousPageLink()#\n    #pageNumberLinks()#\n    #nextPageLink()#\n    #lastPageLink()#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom link text and CSS classes\n\n// View code\n&lt;cfoutput&gt;\n    #firstPageLink(\n        text=&quot;&amp;laquo;&amp;laquo; First&quot;,\n        class=&quot;page-link&quot;,\n        disabledClass=&quot;page-link disabled&quot;\n    )#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 3: Hide the disabled element entirely when on the first page\n\n// View code\n&lt;cfoutput&gt;\n    #firstPageLink(showDisabled=false)#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 4: Use a named route so page numbers appear in the URL path\n// instead of as a query-string param (e.g. /articles/page/3)\n\n// Route setup in app/config/routes.cfm\nmapper()\n    .get(name=&quot;paginatedArticles&quot;, pattern=&quot;articles/page/[page]&quot;, to=&quot;articles##index&quot;)\n    .get(name=&quot;articles&quot;, pattern=&quot;articles&quot;, to=&quot;articles##index&quot;)\n.end();\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\narticles = model(&quot;Article&quot;).findAll(page=params.page, perPage=20, order=&quot;title&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #firstPageLink(route=&quot;paginatedArticles&quot;, pageNumberAsParam=false)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Creates a link to the first page, or a disabled span when already on the first page.\n\n","parameters":[{"type":"string","hint":"The text for the link.","required":false,"name":"text","default":"First"},{"type":"string","hint":"The handle given to the query that the pagination should be displayed for.","required":false,"name":"handle","default":"query"},{"type":"string","hint":"The name of the param that holds the current page number.","required":false,"name":"name","default":"page"},{"type":"string","hint":"CSS class for the link element.","required":false,"name":"class","default":""},{"type":"string","hint":"CSS class for the disabled span element.","required":false,"name":"disabledClass","default":"disabled"},{"type":"boolean","hint":"Whether to render a disabled span when already on the first page.","required":false,"name":"showDisabled","default":true},{"type":"boolean","hint":"Decides whether to link the page number as a param or as part of a route.","required":false,"name":"pageNumberAsParam","default":true},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"firstPageLink","tags":{"category":"Pagination Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"paginationfunctions"}},{"returntype":"any","slug":"controller.flash","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the current value of a specific key in the Flash\nnotice = flash(&quot;notice&quot;);\n// notice -&gt; &quot;Your profile was updated successfully.&quot;\n\n// 2. Get the entire Flash as a struct when no key is passed\nflashContents = flash();\n// flashContents -&gt; {notice: &quot;Record saved.&quot;, error: &quot;Something went wrong.&quot;}\n\n// 3. Check for a key before reading it to avoid an empty-string fallback\nif (flashKeyExists(&quot;error&quot;)) {\n    errorMessage = flash(&quot;error&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Returns the value of a specific key in the Flash (or the entire Flash as a struct if no key is passed in).\n\n","parameters":[{"type":"string","hint":"The key to get the value for.","required":false,"name":"key"}],"name":"flash","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"void","slug":"controller.flashClear","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Clear all flash data\nflashClear();\n\n// 2. Insert some messages, then clear them all before redirecting\nflashInsert(notice=&quot;Record saved.&quot;);\nflashInsert(warning=&quot;Check your settings.&quot;);\n// Oops — wipe everything and start fresh\nflashClear();\n// flash() is now an empty struct: {}\n\n// 3. Clear flash conditionally inside a controller action\nfunction checkout() {\n    if (!isLoggedIn()) {\n        flashClear();\n        flashInsert(error=&quot;You must be logged in to check out.&quot;);\n        redirectTo(action=&quot;login&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Deletes everything from the Flash.\n\n","parameters":[],"name":"flashClear","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"numeric","slug":"controller.flashCount","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check how many keys are currently in the Flash\ncount = flashCount();\n// count -&gt; 0 (Flash is empty), or a positive integer when keys exist\n\n// 2. Only render a Flash notice section when there is something to show\nif (flashCount()) {\n    writeOutput(&quot;You have &quot; &amp; flashCount() &amp; &quot; flash message(s).&quot;);\n}\n\n// 3. Use alongside flashIsEmpty() — flashCount() powers the isEmpty check\nflashInsert(notice=&quot;Saved successfully&quot;, warning=&quot;Check your email&quot;);\ncount = flashCount();\n// count -&gt; 2\n</code></pre>","hasExtended":true},"hint":"Returns how many keys exist in the Flash.\n\n","parameters":[],"name":"flashCount","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"any","slug":"controller.flashDelete","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Delete a key from the Flash\nflashDelete(key=&quot;errorMessage&quot;);\n\n// 2. Check the return value — true if the key existed, false if it did not\nwasPresent = flashDelete(key=&quot;notice&quot;);\n// wasPresent -&gt; true  (key existed and was removed)\n// wasPresent -&gt; false (key did not exist in the Flash)\n\n// 3. Conditionally act on whether the key was actually removed\nif (flashDelete(key=&quot;warning&quot;)) {\n    // key existed; it has now been removed from the Flash\n} else {\n    // key was not present; nothing was changed\n}\n</code></pre>","hasExtended":true},"hint":"Deletes a specific key from the Flash.\nReturns <code>true</code> if the key exists.\n\n","parameters":[{"type":"string","hint":"The key to delete","required":true,"name":"key"}],"name":"flashDelete","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"void","slug":"controller.flashInsert","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Insert a single key / value into the Flash\nflashInsert(notice=&quot;Your profile has been updated.&quot;);\n\n// 2. Insert multiple keys at once\nflashInsert(success=&quot;Account created.&quot;, hint=&quot;Check your email to confirm.&quot;);\n\n// 3. Read back a Flash value in the next action or view\n// (After a redirect, in the destination action or its view:)\nmsg = flash(&quot;notice&quot;);\n// msg -&gt; &quot;Your profile has been updated.&quot;\n</code></pre>","hasExtended":true},"hint":"Inserts a new key / value into the Flash.\n\n","parameters":[],"name":"flashInsert","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"boolean","slug":"controller.flashIsEmpty","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check whether the Flash is empty before rendering a notice area\nif (!flashIsEmpty()) {\n    writeOutput(flash(&quot;notice&quot;));\n}\n\n// 2. Insert a message and confirm the Flash is no longer empty\nflashInsert(notice=&quot;Record saved successfully.&quot;);\nempty = flashIsEmpty();\n// empty -&gt; false\n\n// 3. After clearing the Flash, confirm it is empty again\nflashClear();\nempty = flashIsEmpty();\n// empty -&gt; true\n</code></pre>","hasExtended":true},"hint":"Returns whether or not the Flash is empty.\n\n","parameters":[],"name":"flashIsEmpty","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"void","slug":"controller.flashKeep","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Keep the entire Flash for the next request\nflashKeep();\n\n// 2. Keep the &quot;error&quot; key in the Flash for the next request\nflashKeep(&quot;error&quot;);\n\n// 3. Keep both the &quot;error&quot; and &quot;success&quot; keys in the Flash for the next request\nflashKeep(&quot;error,success&quot;);\n</code></pre>","hasExtended":true},"hint":"Make the entire Flash or specific key in it stick around for one more request.\n\n","parameters":[{"type":"string","required":false,"name":"key","default":""}],"name":"flashKeep","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"boolean","slug":"controller.flashKeyExists","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check for an &quot;error&quot; key before reading it\nif (flashKeyExists(&quot;error&quot;)) {\n    errorMessage = flash(&quot;error&quot;);\n}\n\n// 2. Conditionally display a success notice\nif (flashKeyExists(&quot;success&quot;)) {\n    writeOutput(flash(&quot;success&quot;));\n}\n\n// 3. Guard before deleting a specific flash key\nif (flashKeyExists(&quot;notice&quot;)) {\n    flashDelete(&quot;notice&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Checks if a specific key exists in the Flash.\n\n","parameters":[{"type":"string","hint":"The key to check.","required":true,"name":"key"}],"name":"flashKeyExists","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"string","slug":"controller.flashMessages","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Display all Flash messages in a view\n// In the controller action:\nflashInsert(success=&quot;Your post was successfully submitted.&quot;);\nflashInsert(alert=&quot;Don't forget to tweet about this post!&quot;);\nflashInsert(error=&quot;This is an error message.&quot;);\n\n// In the layout or view:\nwriteOutput(flashMessages());\n\n// Generates (keys sorted alphabetically):\n// &lt;div class=&quot;flash-messages&quot;&gt;\n//   &lt;p class=&quot;alert-message&quot;&gt;Don't forget to tweet about this post!&lt;/p&gt;\n//   &lt;p class=&quot;error-message&quot;&gt;This is an error message.&lt;/p&gt;\n//   &lt;p class=&quot;success-message&quot;&gt;Your post was successfully submitted.&lt;/p&gt;\n// &lt;/div&gt;\n\n\n// 2. Show only a single Flash key using the `key` alias\nwriteOutput(flashMessages(key=&quot;success&quot;));\n\n// Generates:\n// &lt;div class=&quot;flash-messages&quot;&gt;\n//   &lt;p class=&quot;success-message&quot;&gt;Your post was successfully submitted.&lt;/p&gt;\n// &lt;/div&gt;\n\n\n// 3. Show a specific set of keys in a defined order using `keys`\nwriteOutput(flashMessages(keys=&quot;success,alert&quot;));\n\n// Generates (in the order supplied, not alphabetically):\n// &lt;div class=&quot;flash-messages&quot;&gt;\n//   &lt;p class=&quot;success-message&quot;&gt;Your post was successfully submitted.&lt;/p&gt;\n//   &lt;p class=&quot;alert-message&quot;&gt;Don't forget to tweet about this post!&lt;/p&gt;\n// &lt;/div&gt;\n\n\n// 4. Always render the container div, even when the Flash is empty\nwriteOutput(flashMessages(includeEmptyContainer=true));\n\n// Generates:\n// &lt;div class=&quot;flash-messages&quot;&gt;&lt;/div&gt;\n\n\n// 5. Use a custom CSS class on the outer container\nwriteOutput(flashMessages(class=&quot;notifications&quot;));\n\n// Generates:\n// &lt;div class=&quot;notifications&quot;&gt;\n//   &lt;p class=&quot;alert-message&quot;&gt;Don't forget to tweet about this post!&lt;/p&gt;\n//   &lt;p class=&quot;error-message&quot;&gt;This is an error message.&lt;/p&gt;\n//   &lt;p class=&quot;success-message&quot;&gt;Your post was successfully submitted.&lt;/p&gt;\n// &lt;/div&gt;\n</code></pre>","hasExtended":true},"hint":"Displays a marked-up listing of messages that exist in the Flash.\n\n","parameters":[{"type":"string","hint":"The key (or list of keys) to show the value for. You can also use the `key` argument instead for better readability when accessing a single key.","required":false,"name":"keys"},{"type":"string","hint":"HTML `class` to set on the `div` element that contains the messages.","required":false,"name":"class","default":"flash-messages"},{"type":"boolean","hint":"Includes the `div` container even if the Flash is empty.","required":false,"name":"includeEmptyContainer","default":"false"},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"flashMessages","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"tabledefinition.float","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single float column to a new table\nt.float(&quot;price&quot;);\n\n// 2. Add a float column with a default value\nt.float(columnNames=&quot;rating&quot;, default=&quot;0.0&quot;);\n\n// 3. Add multiple float columns at once\nt.float(&quot;latitude,longitude&quot;);\n\n// 4. Add a float column that does not allow NULL values\nt.float(columnNames=&quot;score&quot;, allowNull=false);\n\n// 5. Use float() within a createTable migration\nt = createTable(&quot;measurements&quot;);\nt.float(&quot;temperature&quot;);\nt.float(columnNames=&quot;humidity,pressure&quot;, default=&quot;0.0&quot;);\nt.timestamps();\nt.create();\n</code></pre>","hasExtended":true},"hint":"adds float columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default","default":""},{"type":"boolean","required":false,"name":"allowNull","default":"true"}],"name":"float","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"struct","slug":"migrator.forgetVersion","availableIn":["migrator"],"extended":{"docs":"","hasExtended":false},"hint":"Removes a row from <code>wheels_migrator_versions</code> without running\ndown(). Only orphan versions (those with no matching local file)\ncan be forgotten — for legitimate rollbacks, use <code>migrate down</code>.\nReturns: {success, removed, message}\n\n","parameters":[{"type":"string","hint":"The version string to forget (digits only after sanitisation).","required":true,"name":"version"}],"name":"forgetVersion","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"string","slug":"controller.generateUUID","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Generate a UUID and store it in a variable\nnewId = generateUUID();\n// newId -&gt; &quot;550e8400-e29b-41d4-a716-446655440000&quot; (36-character UUID)\n\n// 2. Use generateUUID() to assign a unique identifier before saving a record\npost = model(&quot;Post&quot;).new(title=&quot;Hello World&quot;);\npost.externalId = generateUUID();\npost.save();\n\n// 3. Generate a UUID compatible with SQL Server's uniqueidentifier column\n// Useful when inserting records that need a GUID primary key\ntoken = generateUUID();\n// token -&gt; &quot;a1b2c3d4-e5f6-7890-abcd-ef1234567890&quot;\n</code></pre>","hasExtended":true},"hint":"Generates a 36-character UUID compatible with SQL Server's uniqueidentifier.\n\n","parameters":[],"name":"generateUUID","tags":{"category":"UUID Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"uuidfunctions"}},{"returntype":"any","slug":"controller.get","availableIn":["controller","model","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the current value of a global Wheels setting\nsetting = get(&quot;tableNamePrefix&quot;);\n// setting -&gt; &quot;&quot; (or whatever prefix has been configured)\n\n// 2. Get the current value of a different global setting\ndsName = get(&quot;dataSourceName&quot;);\n// dsName -&gt; &quot;myAppDB&quot;\n\n// 3. Get the default for a specific function argument\n// (useful for inspecting function-level defaults set via set())\nmsg = get(functionName=&quot;validatesConfirmationOf&quot;, name=&quot;message&quot;);\n// msg -&gt; &quot;[property] should match confirmation&quot;\n</code></pre>","hasExtended":true},"hint":"Returns the current setting for the supplied Wheels setting or the current default for the supplied Wheels function argument.\n\n","parameters":[{"type":"string","hint":"Variable name to get setting for.","required":true,"name":"name"},{"type":"string","hint":"Function name to get setting for.","required":false,"name":"functionName","default":""}],"name":"get","tags":{"category":"Miscellaneous Functions","sectionClass":"configuration","section":"Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"struct","slug":"mapper.get","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Basic GET route using the `to` shorthand (controller##action)\n    // Route name:  post\n    // Example URL: /posts/my-post-title\n    // Controller:  Posts\n    // Action:      show\n    .get(name=&quot;post&quot;, pattern=&quot;posts/[slug]&quot;, to=&quot;posts##show&quot;)\n\n    // 2. Route using separate `controller` and `action` arguments\n    // Route name:  posts\n    // Example URL: /posts\n    // Controller:  Posts\n    // Action:      index\n    .get(name=&quot;posts&quot;, controller=&quot;posts&quot;, action=&quot;index&quot;)\n\n    // 3. Custom URL pattern that differs from the route name\n    // Route name:  authors\n    // Example URL: /the-scribes\n    // Controller:  Authors\n    // Action:      index\n    .get(name=&quot;authors&quot;, pattern=&quot;the-scribes&quot;, to=&quot;authors##index&quot;)\n\n    // 4. Package (subfolder) scoping — keeps the package out of the URL\n    // Route name:  commerceCart\n    // Example URL: /cart\n    // Controller:  commerce.Carts\n    // Action:      show\n    .get(name=&quot;cart&quot;, to=&quot;carts##show&quot;, package=&quot;commerce&quot;)\n\n    // 5. Multi-line format for readability, with package scoping\n    // Route name:  extranetEditProfile\n    // Example URL: /profile/edit\n    // Controller:  extranet.Profiles\n    // Action:      edit\n    .get(\n        name=&quot;editProfile&quot;,\n        pattern=&quot;profile/edit&quot;,\n        to=&quot;profiles##edit&quot;,\n        package=&quot;extranet&quot;\n    )\n\n    // 6. Permanent redirect — useful for renamed or moved URLs\n    // Example URL: /old-about  -&gt;  302 redirect to /about\n    .get(name=&quot;oldAbout&quot;, pattern=&quot;old-about&quot;, redirect=&quot;/about&quot;)\n\n    // 7. GET routes scoped inside a nested resource\n    .resources(name=&quot;users&quot;, nested=true)\n        // Route name:  activatedUsers\n        // Example URL: /users/activated\n        // Controller:  Users\n        // Action:      activated\n        .get(name=&quot;activated&quot;, to=&quot;users##activated&quot;, on=&quot;collection&quot;)\n\n        // Route name:  preferencesUser\n        // Example URL: /users/391/preferences\n        // Controller:  Preferences\n        // Action:      index\n        .get(name=&quot;preferences&quot;, to=&quot;preferences##index&quot;, on=&quot;member&quot;)\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Create a route that matches a URL requiring an HTTP <code>GET</code> method. We recommend only using this matcher to expose actions that display data. See <code>post</code>, <code>patch</code>, <code>delete</code>, and <code>put</code> for matchers that are appropriate for actions that change data in your database.\n\n","parameters":[{"type":"string","hint":"Camel-case name of route to reference when build links and form actions (e.g., `blogPost`).","required":false,"name":"name"},{"type":"string","hint":"Overrides the URL pattern that will match the route. The default value is a dasherized version of `name` (e.g., a `name` of `blogPost` generates a pattern of `blog-post`).","required":false,"name":"pattern"},{"type":"string","hint":"Set `controller##action` combination to map the route to. You may use either this argument or a combination of `controller` and `action`.","required":false,"name":"to"},{"type":"string","hint":"Map the route to a given controller. This must be passed along with the `action` argument.","required":false,"name":"controller"},{"type":"string","hint":"Map the route to a given action within the `controller`. This must be passed along with the `controller` argument.","required":false,"name":"action"},{"type":"string","hint":"Indicates a subfolder that the controller will be referenced from (but not added to the URL pattern). For example, if you set this to `admin`, the controller will be located at `admin/YourController.cfc`, but the URL path will not contain `admin/`.","required":false,"name":"package"},{"type":"string","hint":"If this route is within a nested resource, you can set this argument to `member` or `collection`. A `member` route contains a reference to the resource's `key`, while a `collection` route does not.","required":false,"name":"on"},{"type":"string","hint":"Redirect via 302 to this URL when this route is matched. Has precedence over controller/action. Use either an absolute link like `/about/`, or a full canonical link.","required":false,"name":"redirect"}],"name":"get","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"array","slug":"migrator.getAvailableMigrations","availableIn":["migrator"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all available migrations and find the latest version\nmigrations = application.wheels.migrator.getAvailableMigrations();\n\nif (arrayLen(migrations)) {\n    latestVersion = migrations[arrayLen(migrations)].version;\n} else {\n    latestVersion = 0;\n}\n\n// 2. List pending (not yet run) migrations\nmigrations = application.wheels.migrator.getAvailableMigrations();\n\nfor (migration in migrations) {\n    if (migration.status != &quot;migrated&quot;) {\n        writeOutput(migration.version &amp; &quot; - &quot; &amp; migration.name);\n    }\n}\n\n// 3. Use a custom migrations path\nmigrations = application.wheels.migrator.getAvailableMigrations(path=expandPath(&quot;/app/db/migrate/&quot;));\n</code></pre>","hasExtended":true},"hint":"Searches db/migrate folder for migrations. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n\n$getVersionsPreviouslyMigrated). Callers that already hold the list\n(doctor, info, migrateTo) pass it through to avoid re-running the\ntracking-table probe chain; when empty it is computed here.","parameters":[{"type":"string","hint":"Path to Migration Files: defaults to /app/migrator/migrations/","required":false,"name":"path","default":"[runtime expression]"},{"type":"string","hint":"Optional precomputed applied-versions list (from","required":false,"name":"previousMigrationList","default":""}],"name":"getAvailableMigrations","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"string","slug":"migrator.getCurrentMigrationVersion","availableIn":["migrator"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get current database version\ncurrentVersion = application.wheels.migrator.getCurrentMigrationVersion();\n// currentVersion -&gt; &quot;20240315120000&quot;  (timestamp-style version string, or &quot;0&quot; if no migrations have run)\n\n// 2. Display version status in a maintenance view\ncurrentVersion = application.wheels.migrator.getCurrentMigrationVersion();\nif (currentVersion == &quot;0&quot;) {\n    writeOutput(&quot;No migrations have been applied yet.&quot;);\n} else {\n    writeOutput(&quot;Database is at version: &quot; &amp; currentVersion);\n}\n</code></pre>","hasExtended":true},"hint":"Returns current database version. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n","parameters":[],"name":"getCurrentMigrationVersion","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"array","slug":"controller.getEmails","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Assert that exactly one email was sent during the action (in a test)\nprocessSignup();\nemails = getEmails();\nassert(&quot;arrayLen(emails) eq 1&quot;);\nassert(&quot;emails[1].to eq 'newuser@example.com'&quot;);\nassert(&quot;emails[1].subject eq 'Welcome!'&quot;);\n\n// 2. Inspect all emails sent during a request\nemails = getEmails();\nfor (email in emails) {\n\twriteOutput(email.to &amp; &quot; — &quot; &amp; email.subject);\n}\n\n// 3. Return an empty array when no emails were sent\nemails = getEmails();\n// emails -&gt; []\n</code></pre>","hasExtended":true},"hint":"Primarily used for testing to get information about emails sent during the request.\n\n","parameters":[],"name":"getEmails","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"array","slug":"controller.getFiles","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Assert that exactly one file was sent during the action (in a test)\nprocessDownload();\nfiles = getFiles();\nassert(&quot;arrayLen(files) eq 1&quot;);\nassert(&quot;files[1].name eq 'report.pdf'&quot;);\n\n// 2. Inspect all files sent during a request\nfiles = getFiles();\nfor (file in files) {\n\twriteOutput(file.name &amp; &quot; — &quot; &amp; file.type);\n}\n\n// 3. Return an empty array when no files were sent\nfiles = getFiles();\n// files -&gt; []\n</code></pre>","hasExtended":true},"hint":"Primarily used for testing to get information about files sent during the request.\n\n","parameters":[],"name":"getFiles","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"struct","slug":"controller.getRedirect","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Assert that a redirect was performed to a specific URL (in a test)\nprocessDelete();\nredirect = getRedirect();\nassert(&quot;structCount(redirect) gt 0&quot;);\nassert(&quot;redirect.url eq '/users'&quot;);\n\n// 2. Inspect the full redirect struct after an action runs\nsubmitLogin();\nredirect = getRedirect();\n// redirect.url        -&gt; &quot;/dashboard&quot;\n// redirect.statusCode -&gt; 302\n// redirect.addToken   -&gt; false\n\n// 3. Confirm no redirect was performed (action rendered a view instead)\nshowProfile();\nredirect = getRedirect();\n// redirect -&gt; {}\n</code></pre>","hasExtended":true},"hint":"Primarily used for testing to establish whether the current request has performed a redirect.\n\n","parameters":[],"name":"getRedirect","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"mapper.getRoutes","availableIn":["mapper"],"extended":{"docs":"","hasExtended":false},"hint":"","parameters":[],"name":"getRoutes","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"string","slug":"model.getTableNamePrefix","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Use the table name prefix when running a custom query inside a model method\nfunction getDisabledUsers() {\n\tlocal.q = queryExecute(\n\t\t&quot;SELECT * FROM #this.getTableNamePrefix()#users WHERE disabled = 1&quot;,\n\t\t[],\n\t\t{datasource: get(&quot;dataSourceName&quot;)}\n\t);\n\treturn local.q;\n}\n\n// 2. Log the configured prefix to verify model setup\nprefix = model(&quot;User&quot;).getTableNamePrefix();\n// prefix -&gt; &quot;app_&quot; (or &quot;&quot; if none is set)\n</code></pre>","hasExtended":true},"hint":"Returns the table name prefix set for the table.\n\n","parameters":[],"name":"getTableNamePrefix","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"struct","slug":"mapper.group","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\n// 1. Group routes under a shared path prefix (open/close style)\nmapper()\n    .group(path=&quot;admin&quot;)\n        // Route URL: /admin/dashboard\n        .get(name=&quot;dashboard&quot;, to=&quot;dashboard##index&quot;)\n        // Route URL: /admin/reports\n        .get(name=&quot;reports&quot;, to=&quot;reports##index&quot;)\n    .end()\n.end();\n\n// 2. Group with both a path prefix and a name prefix\nmapper()\n    .group(path=&quot;account&quot;, name=&quot;account&quot;)\n        // Route name:  accountSettings\n        // Example URL: /account/settings\n        .get(name=&quot;settings&quot;, to=&quot;settings##show&quot;)\n\n        // Route name:  accountBilling\n        // Example URL: /account/billing\n        .get(name=&quot;billing&quot;, to=&quot;billing##show&quot;)\n    .end()\n.end();\n\n// 3. Group with regex constraints applied to all child routes\nmapper()\n    .group(path=&quot;products&quot;, constraints={id: &quot;\\d+&quot;})\n        // Only matches numeric :id segments\n        .get(name=&quot;productShow&quot;, pattern=&quot;[id]&quot;, to=&quot;products##show&quot;)\n        .put(name=&quot;productUpdate&quot;, pattern=&quot;[id]&quot;, to=&quot;products##update&quot;)\n    .end()\n.end();\n\n// 4. Group using a callback function (auto-closes the group)\nmapper()\n    .group(\n        path    = &quot;reports&quot;,\n        name    = &quot;report&quot;,\n        callback = function(mapper) {\n            // Route name:  reportSales\n            // Example URL: /reports/sales\n            mapper.get(name=&quot;sales&quot;, to=&quot;reports##sales&quot;);\n\n            // Route name:  reportExpenses\n            // Example URL: /reports/expenses\n            mapper.get(name=&quot;expenses&quot;, to=&quot;reports##expenses&quot;);\n        }\n    )\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Group routes together with shared attributes like path prefix, name prefix, and constraints without implying a controller package or namespace. Unlike <code>namespace()</code> (which maps to a subfolder and URL prefix) or <code>package()</code> (which maps to a subfolder), <code>group()</code> is a pure organizational grouping mechanism.\n\n","parameters":[{"type":"string","hint":"Name to prepend to child route names for use when building links, forms, and other URLs.","required":false,"name":"name"},{"type":"string","hint":"URL path prefix to apply to all child routes.","required":false,"name":"path"},{"type":"struct","hint":"Variable patterns (regex constraints) to apply to all child routes.","required":false,"name":"constraints"},{"type":"any","hint":"A callback function to define nested routes within this group. If provided, the group is automatically closed when the callback completes.","required":false,"name":"callback"}],"name":"group","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.h","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Safely output user-supplied text in a view template\nwriteOutput(h(user.name));\n// If user.name is &quot;&lt;script&gt;alert('xss')&lt;/script&gt;&quot;, outputs the\n// HTML-encoded form: &amp;lt;script&amp;gt;alert(&amp;##x27;xss&amp;##x27;)&amp;lt;/script&amp;gt;\n\n// 2. Encode a variable inline in a cfoutput block\n//   Instead of: &lt;cfoutput&gt;##user.bio##&lt;/cfoutput&gt;\n//   Use:        &lt;cfoutput&gt;##h(user.bio)##&lt;/cfoutput&gt;\nencodedBio = h(user.bio);\n\n// 3. Encode a non-string value (converted to string automatically)\nrating = 4.5;\nwriteOutput(h(rating));\n// rating -&gt; &quot;4.5&quot;\n</code></pre>","hasExtended":true},"hint":"Encodes a value for safe HTML output. Use in templates to prevent XSS:\n<code>#h(user.name)#</code> instead of <code>#user.name#</code>.\n\n","parameters":[{"type":"any","hint":"The value to encode for HTML output. Converted to string if not already.","required":true,"name":"value"}],"name":"h","tags":{"category":"Sanitization Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"sanitizationfunctions"}},{"returntype":"boolean","slug":"model.hasChanged","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if a specific property has changed before saving\nmember = model(&quot;member&quot;).findByKey(params.memberId);\nmember.email = params.newEmail;\n\nif (member.hasChanged(&quot;email&quot;)) {\n    // Send a confirmation email before committing the change\n    sendEmailChangeNotification(member);\n}\n\n// 2. Check if any property has changed (no argument)\nuser = model(&quot;User&quot;).findByKey(params.userId);\nuser.setProperties(params.user);\n\nif (user.hasChanged()) {\n    // At least one property differs from the persisted state\n    user.save();\n}\n\n// 3. Use the dynamic shorthand — automatically generated per property\norder = model(&quot;Order&quot;).findByKey(params.orderId);\norder.status = &quot;shipped&quot;;\n\nif (order.statusHasChanged()) {\n    // Equivalent to: order.hasChanged(&quot;status&quot;)\n    notifyCustomer(order);\n}\n\n// 4. New (unsaved) objects always return true — no persisted record exists yet\nnewPost = model(&quot;Post&quot;).new(title=&quot;Hello&quot;);\nwriteOutput(newPost.hasChanged()); // -&gt; true\n</code></pre>","hasExtended":true},"hint":"Returns <code>true</code> if the specified property (or any if none was passed in) has been changed but not yet saved to the database.\nWill also return <code>true</code> if the object is new and no record for it exists in the database.\n\n","parameters":[{"type":"string","hint":"Name of property to check for change.","required":false,"name":"property","default":""}],"name":"hasChanged","tags":{"category":"Change Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"changefunctions"}},{"returntype":"boolean","slug":"model.hasErrors","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if a post object has any errors at all\nif (post.hasErrors()) {\n    // Redirect user back to the form to correct errors\n}\n\n// 2. Check if a specific property has errors\nif (post.hasErrors(property=&quot;title&quot;)) {\n    // The title field has at least one error\n}\n\n// 3. Check if any errors were set with a specific name\nif (post.hasErrors(name=&quot;uniquenessViolation&quot;)) {\n    // Handle uniqueness error specifically\n}\n</code></pre>","hasExtended":true},"hint":"Returns <code>true</code> if the object has any errors.\nYou can also limit to only check a specific property or name for errors.\n\n","parameters":[{"type":"string","hint":"Name of the property to check if there are any errors set on.","required":false,"name":"property","default":""},{"type":"string","hint":"Error name to check if there are any errors set with.","required":false,"name":"name","default":""}],"name":"hasErrors","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"void","slug":"model.hasMany","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage – a Post has many comments (foreign key `postId` lives on the `comments` table)\n// In models/Post.cfc config()\nhasMany(&quot;comments&quot;);\n\n// 2. Set up a many-to-many shortcut so readers can access publications directly\n// In models/Reader.cfc config()\nhasMany(name=&quot;subscriptions&quot;, shortcut=&quot;publications&quot;);\n\n// 3. Automatically delete all associated comments (bypassing object instantiation) when the parent is deleted\n// In models/Post.cfc config()\nhasMany(name=&quot;comments&quot;, dependent=&quot;deleteAll&quot;);\n\n// 4. Instantiate and call each comment's beforeDelete callback when deleting dependents\n// In models/Post.cfc config()\nhasMany(name=&quot;comments&quot;, dependent=&quot;delete&quot;);\n\n// 5. Override the many-to-many shortcut chain when association names differ from model names\n// In models/Customer.cfc config()\nhasMany(name=&quot;subscriptions&quot;, shortcut=&quot;magazines&quot;, through=&quot;publication,subscriptions&quot;);\n// In models/Subscription.cfc config()\nbelongsTo(&quot;customer&quot;);\nbelongsTo(&quot;publication&quot;);\n// In models/Publication.cfc config()\nhasMany(&quot;subscriptions&quot;);\n\n// 6. Specify a custom foreign key when not following Wheels naming conventions\n// In models/Author.cfc config()\nhasMany(name=&quot;articles&quot;, foreignKey=&quot;writtenByAuthorId&quot;);\n\n// 7. Use an inner join instead of the default outer join when including the association\n// In models/Category.cfc config()\nhasMany(name=&quot;products&quot;, joinType=&quot;inner&quot;);\n\n// 8. Polymorphic hasMany – a model acts as a parent for a shared `comments` child model\n// In models/Photo.cfc config() (the `as` value matches the `polymorphic` interface name on the child)\nhasMany(name=&quot;comments&quot;, as=&quot;commentable&quot;);\n// In models/Comment.cfc config()\nbelongsTo(name=&quot;commentable&quot;, polymorphic=true);\n</code></pre>","hasExtended":true},"hint":"Sets up a <code>hasMany</code> association between this model and the specified one.\n\n","parameters":[{"type":"string","hint":"Gives the association a name that you refer to when working with the association (in the `include` argument to `findAll`, to name one example).","required":true,"name":"name"},{"type":"string","hint":"Name of associated model (usually not needed if you follow Wheels conventions because the model name will be deduced from the `name` argument).","required":false,"name":"modelName","default":""},{"type":"string","hint":"Foreign key property name (usually not needed if you follow Wheels conventions since the foreign key name will be deduced from the `name` argument).","required":false,"name":"foreignKey","default":""},{"type":"string","hint":"Column name to join to if not the primary key (usually not needed if you follow Wheels conventions since the join key will be the table's primary key/keys).","required":false,"name":"joinKey","default":""},{"type":"string","hint":"Use to set the join type when joining associated tables. Possible values are `inner` (for `INNER JOIN`) and `outer` (for `LEFT OUTER JOIN`).","required":false,"name":"joinType","default":"outer"},{"type":"string","hint":"Defines how to handle dependent model objects when you delete an object from this model. `delete` / `deleteAll` deletes the record(s) (`deleteAll` bypasses object instantiation). `remove` / `removeAll` sets the forein key field(s) to `NULL` (`removeAll` bypasses object instantiation).","required":false,"name":"dependent","default":false},{"type":"string","hint":"Set this argument to create an additional dynamic method that gets the object(s) from the other side of a many-to-many association.","required":false,"name":"shortcut","default":""},{"type":"string","hint":"Set this argument if you need to override Wheels conventions when using the `shortcut` argument. Accepts a list of two association names representing the chain from the opposite side of the many-to-many relationship to this model.","required":false,"name":"through","default":"[runtime expression]"},{"type":"string","hint":"Set this argument to declare a polymorphic `hasMany` association. The child model stores the parent type in a `{as}Type` column alongside the foreign key `{as}Id`.","required":false,"name":"as","default":""}],"name":"hasMany","tags":{"category":"Association Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"associationfunctions"}},{"returntype":"string","slug":"controller.hasManyCheckBox","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Show check boxes for associating authors with the current book\n&lt;cfloop query=&quot;authors&quot;&gt;\n    #hasManyCheckBox(\n        label=authors.fullName,\n        objectName=&quot;book&quot;,\n        association=&quot;bookAuthors&quot;,\n        keys=&quot;#book.key()#,#authors.id#&quot;\n    )#\n&lt;/cfloop&gt;\n\n// 2. Wrap each checkbox and label in a div using prepend/append\n&lt;cfloop query=&quot;authors&quot;&gt;\n    #hasManyCheckBox(\n        label=authors.fullName,\n        labelPlacement=&quot;after&quot;,\n        objectName=&quot;book&quot;,\n        association=&quot;bookAuthors&quot;,\n        keys=&quot;#book.key()#,#authors.id#&quot;,\n        prepend=&quot;&lt;div class=&quot;&quot;author-option&quot;&quot;&gt;&quot;,\n        append=&quot;&lt;/div&gt;&quot;\n    )#\n&lt;/cfloop&gt;\n\n// 3. Supply an explicit ID and custom error styling\n&lt;cfloop query=&quot;tags&quot;&gt;\n    #hasManyCheckBox(\n        label=tags.name,\n        objectName=&quot;post&quot;,\n        association=&quot;postTags&quot;,\n        keys=&quot;#post.key()#,#tags.id#&quot;,\n        id=&quot;tag-#tags.id#&quot;,\n        errorElement=&quot;span&quot;,\n        errorClass=&quot;field-error&quot;\n    )#\n&lt;/cfloop&gt;\n</code></pre>","hasExtended":true},"hint":"Used as a shortcut to output the proper form elements for an association.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name of the variable containing the parent object to represent with this form field.","required":true,"name":"objectName"},{"type":"string","hint":"Name of the association set in the parent object to represent with this form field.","required":true,"name":"association"},{"type":"string","hint":"Primary keys associated with this form field. Note that these keys should be listed in the order that they appear in the database table.","required":true,"name":"keys"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using `aroundLeft` or `aroundRight`.","required":false,"name":"labelPlacement"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend"},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append"},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel"},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel"},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement"},{"type":"string","hint":"The `class` name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"string","hint":"Optional. Explicit ID for the generated checkbox input. If not provided, an ID will be generated automatically.","required":false,"name":"id"}],"name":"hasManyCheckBox","tags":{"category":"Form Association Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formassociationfunctions"}},{"returntype":"string","slug":"controller.hasManyRadioButton","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Show radio buttons for selecting a default address for the current author (loops over a query of addresses)\n&lt;cfoutput&gt;\n\t&lt;cfloop query=&quot;addresses&quot;&gt;\n\t\t#hasManyRadioButton(\n\t\t\tobjectName=&quot;author&quot;,\n\t\t\tassociation=&quot;addresses&quot;,\n\t\t\tproperty=&quot;isDefault&quot;,\n\t\t\tkeys=&quot;#author.key()#,#addresses.id#&quot;,\n\t\t\ttagValue=&quot;1&quot;,\n\t\t\tlabel=addresses.title\n\t\t)#\n\t&lt;/cfloop&gt;\n&lt;/cfoutput&gt;\n\n// 2. Same loop, but mark the radio button as checked when the property is blank (no default set yet)\n&lt;cfoutput&gt;\n\t&lt;cfloop query=&quot;addresses&quot;&gt;\n\t\t#hasManyRadioButton(\n\t\t\tobjectName=&quot;author&quot;,\n\t\t\tassociation=&quot;addresses&quot;,\n\t\t\tproperty=&quot;isDefault&quot;,\n\t\t\tkeys=&quot;#author.key()#,#addresses.id#&quot;,\n\t\t\ttagValue=&quot;1&quot;,\n\t\t\tcheckIfBlank=true,\n\t\t\tlabel=addresses.title\n\t\t)#\n\t&lt;/cfloop&gt;\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Used as a shortcut to output the proper form elements for an association.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name of the variable containing the parent object to represent with this form field.","required":true,"name":"objectName"},{"type":"string","hint":"Name of the association set in the parent object to represent with this form field.","required":true,"name":"association"},{"type":"string","hint":"Name of the property in the child object to represent with this form field.","required":true,"name":"property"},{"type":"string","hint":"Primary keys associated with this form field. Note that these keys should be listed in the order that they appear in the database table.","required":true,"name":"keys"},{"type":"string","hint":"The value of the radio button when selected.","required":true,"name":"tagValue"},{"type":"boolean","hint":"Whether or not to check this form field as a default if there is a blank value set for the property.","required":false,"name":"checkIfBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"hasManyRadioButton","tags":{"category":"Form Association Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formassociationfunctions"}},{"returntype":"void","slug":"model.hasOne","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Specify that instances of this model have one profile. (The associated model's table, not the current one, should have the foreign key column.)\nhasOne(&quot;profile&quot;);\n\n// 2. Same as above but setting `joinType` to `inner`, meaning this model should always have a matching record in the `profiles` table.\nhasOne(name=&quot;profile&quot;, joinType=&quot;inner&quot;);\n\n// 3. Automatically delete the associated `profile` record whenever this object is deleted.\nhasOne(name=&quot;profile&quot;, dependent=&quot;delete&quot;);\n\n// 4. Declare a polymorphic `hasOne` association so that multiple models can each have one image via a shared interface.\nhasOne(name=&quot;image&quot;, as=&quot;imageable&quot;);\n</code></pre>","hasExtended":true},"hint":"Sets up a <code>hasOne</code> association between this model and the specified one.\n\n","parameters":[{"type":"string","hint":"Gives the association a name that you refer to when working with the association (in the `include` argument to `findAll`, to name one example).","required":true,"name":"name"},{"type":"string","hint":"Name of associated model (usually not needed if you follow Wheels conventions because the model name will be deduced from the `name` argument).","required":false,"name":"modelName","default":""},{"type":"string","hint":"Foreign key property name (usually not needed if you follow Wheels conventions since the foreign key name will be deduced from the `name` argument).","required":false,"name":"foreignKey","default":""},{"type":"string","hint":"Column name to join to if not the primary key (usually not needed if you follow Wheels conventions since the join key will be the table's primary key/keys).","required":false,"name":"joinKey","default":""},{"type":"string","hint":"Use to set the join type when joining associated tables. Possible values are `inner` (for `INNER JOIN`) and `outer` (for `LEFT OUTER JOIN`).","required":false,"name":"joinType","default":"outer"},{"type":"string","hint":"Defines how to handle dependent model objects when you delete an object from this model. `delete` / `deleteAll` deletes the record(s) (`deleteAll` bypasses object instantiation). `remove` / `removeAll` sets the forein key field(s) to `NULL` (`removeAll` bypasses object instantiation).","required":false,"name":"dependent","default":false},{"type":"string","hint":"Set this argument to declare a polymorphic `hasOne` association. The child model stores the parent type in a `{as}Type` column alongside the foreign key `{as}Id`.","required":false,"name":"as","default":""}],"name":"hasOne","tags":{"category":"Association Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"associationfunctions"}},{"returntype":"boolean","slug":"model.hasProperty","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check whether a property exists on a new object after setting it\nemployee = model(&quot;Employee&quot;).new();\nemployee.firstName = &quot;Jane&quot;;\nemployee.hasProperty(&quot;firstName&quot;); // -&gt; true\nemployee.hasProperty(&quot;salary&quot;);    // -&gt; false (not set on this object)\n\n// 2. Use the equivalent dynamic method (has&lt;PropertyName&gt;)\nemployee.hasFirstName(); // -&gt; true\nemployee.hasSalary();    // -&gt; false\n\n// 3. Guard logic before accessing a property\nuser = model(&quot;User&quot;).findOne(where=&quot;email='jane@example.com'&quot;);\nif (user.hasProperty(&quot;avatarUrl&quot;)) {\n    writeOutput(user.avatarUrl);\n}\n</code></pre>","hasExtended":true},"hint":"Returns <code>true</code> if the specified property name exists on the model.\n\n","parameters":[{"type":"string","hint":"Name of property to inspect.","required":true,"name":"property"}],"name":"hasProperty","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.hAttr","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Safely encode a user-supplied string inside an HTML attribute\nuserBio = &quot;Say &quot;&quot;hello&quot;&quot; &amp; &lt;wave&gt;&quot;;\nwriteOutput('&lt;div title=&quot;#hAttr(userBio)#&quot;&gt;Hover me&lt;/div&gt;');\n&lt;!--- Renders: &lt;div title=&quot;Say &amp;#x22;hello&amp;#x22; &amp;amp; &amp;lt;wave&amp;gt;&quot;&gt;Hover me&lt;/div&gt; ---&gt;\n\n// 2. Use directly in a view template to prevent XSS in attribute values\nwriteOutput('&lt;input type=&quot;text&quot; placeholder=&quot;#hAttr(params.search)#&quot;&gt;');\n</code></pre>","hasExtended":true},"hint":"Encodes a value for safe use inside an HTML attribute.\nUse when building attribute values manually:\n&lt;div title=\"#hAttr(user.bio)#\"&gt;.\n\n","parameters":[{"type":"any","hint":"The value to encode for HTML attribute context.","required":true,"name":"value"}],"name":"hAttr","tags":{"category":"Sanitization Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"sanitizationfunctions"}},{"returntype":"struct","slug":"mapper.health","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Register the default health check route at /health.\n    // Responds with {&quot;status&quot;:&quot;ok&quot;,&quot;timestamp&quot;:&quot;...&quot;} — no controller needed.\n    .health()\n\n    .root(to=&quot;home##index&quot;)\n    .wildcard()\n.end();\n\n// 2. Override the URL path and route name.\n// Accessible at /healthz instead of /health.\nmapper()\n    .health(path=&quot;healthz&quot;, name=&quot;healthz&quot;)\n    .root(to=&quot;home##index&quot;)\n.end();\n\n// 3. Delegate to a custom controller action for advanced health checks\n// (e.g. database ping, cache connectivity).\nmapper()\n    .health(to=&quot;system##health&quot;)\n    .root(to=&quot;home##index&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Register a health check route at <code>/health</code> (or a custom path). Returns a JSON response with status and timestamp by default, or delegates to a custom controller action.\nThis is useful for container orchestration (Kubernetes liveness/readiness probes), load balancer health checks, and monitoring tools.\n\n","parameters":[{"type":"string","hint":"Set `controller##action` combination for a custom health check handler. If not provided, a default handler returns `{\"status\":\"ok\",\"timestamp\":\"...\"}`.","required":false,"name":"to","default":"wheels#health"},{"type":"string","hint":"Override the URL path. Defaults to `\"health\"`.","required":false,"name":"path","default":"health"},{"type":"string","hint":"Override the route name. Defaults to `\"health\"`.","required":false,"name":"name","default":"health"}],"name":"health","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.hiddenField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage: embed the user's id as a hidden field\n#hiddenField(objectName=&quot;user&quot;, property=&quot;id&quot;)#\n// -&gt; &lt;input type=&quot;hidden&quot; id=&quot;user-id&quot; name=&quot;user[id]&quot; value=&quot;42&quot;&gt;\n\n// 2. Carry a token value using a class attribute for JavaScript hooks\n#hiddenField(objectName=&quot;user&quot;, property=&quot;csrfToken&quot;, class=&quot;js-token&quot;)#\n// -&gt; &lt;input type=&quot;hidden&quot; id=&quot;user-csrf-token&quot; name=&quot;user[csrfToken]&quot; class=&quot;js-token&quot; value=&quot;abc123&quot;&gt;\n\n// 3. Nested form — pass the parent's id through a hasMany association\n#hiddenField(objectName=&quot;order&quot;, property=&quot;id&quot;, association=&quot;lineItems&quot;, position=&quot;1&quot;)#\n// -&gt; &lt;input type=&quot;hidden&quot; id=&quot;order-line-items-1-id&quot; name=&quot;order[lineItems][1][id]&quot; value=&quot;7&quot;&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a hidden field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"hiddenField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.hiddenFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage with a name and value\n#hiddenFieldTag(name=&quot;userId&quot;, value=user.id)#\n// -&gt; &lt;input type=&quot;hidden&quot; name=&quot;userId&quot; value=&quot;42&quot;&gt;\n\n// 2. Embed a CSRF token in a standalone form\n#hiddenFieldTag(name=&quot;csrfToken&quot;, value=session.csrfToken)#\n// -&gt; &lt;input type=&quot;hidden&quot; name=&quot;csrfToken&quot; value=&quot;a1b2c3d4...&quot;&gt;\n\n// 3. Pass extra HTML attributes via additional arguments\n#hiddenFieldTag(name=&quot;returnTo&quot;, value=&quot;/dashboard&quot;, id=&quot;returnToField&quot;)#\n// -&gt; &lt;input type=&quot;hidden&quot; name=&quot;returnTo&quot; value=&quot;/dashboard&quot; id=&quot;returnToField&quot;&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a hidden field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"hiddenFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.highlight","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Highlight a single phrase in text\n// Outputs: You searched for: &lt;span class=&quot;highlight&quot;&gt;CFWheels&lt;/span&gt; framework\nresult = highlight(text=&quot;You searched for: CFWheels framework&quot;, phrase=&quot;CFWheels&quot;);\n\n// 2. Highlight multiple phrases using a comma-delimited list\n// Outputs: &lt;span class=&quot;highlight&quot;&gt;Open&lt;/span&gt; source &lt;span class=&quot;highlight&quot;&gt;CFML&lt;/span&gt; framework\nresult = highlight(text=&quot;Open source CFML framework&quot;, phrase=&quot;Open,CFML&quot;);\n\n// 3. Highlight with a custom tag and CSS class\n// Outputs: Learn &lt;strong class=&quot;match&quot;&gt;ColdFusion&lt;/strong&gt; today\nresult = highlight(text=&quot;Learn ColdFusion today&quot;, phrase=&quot;ColdFusion&quot;, tag=&quot;strong&quot;, class=&quot;match&quot;);\n</code></pre>","hasExtended":true},"hint":"Highlights the phrase(s) everywhere in the text if found by wrapping them in <code>span</code> tags.\n\n","parameters":[{"type":"string","hint":"Text to search in.","required":true,"name":"text"},{"type":"string","hint":"Phrase (or list of phrases) to highlight. This argument is also aliased as `phrases`.","required":false,"name":"phrase"},{"type":"string","hint":"Delimiter to use when passing in multiple phrases.","required":false,"name":"delimiter","default":","},{"type":"string","hint":"HTML tag to use to wrap the highlighted phrase(s).","required":false,"name":"tag","default":"span"},{"type":"string","hint":"Class to use in the tags wrapping highlighted phrase(s).","required":false,"name":"class","default":"highlight"},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"highlight","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.hourSelectTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage — render a select control for hours of the day\n#hourSelectTag(name=&quot;hourOfMeeting&quot;, selected=params.hourOfMeeting)#\n\n// 2. Show hours in 12-hour (AM/PM) format instead of 24-hour format\n#hourSelectTag(name=&quot;hourOfMeeting&quot;, selected=params.hourOfMeeting, twelveHour=true)#\n\n// 3. Include a blank option as a placeholder prompt and add a label\n#hourSelectTag(name=&quot;startHour&quot;, selected=params.startHour, includeBlank=&quot;-- Select Hour --&quot;, label=&quot;Start Hour&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing one <code>select</code> form control for the hours of the day based on the supplied name.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"The hour that should be selected initially.","required":false,"name":"selected","default":""},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"boolean","hint":"whether to display the hours in 24 or 12 hour format. 12 hour format has AM/PM drop downs","required":false,"name":"twelveHour","default":false},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"date","required":false,"name":"$now","default":"[runtime expression]"}],"name":"hourSelectTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.humanize","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Humanize a camelCase string\nresult = humanize(&quot;wheelsIsAFramework&quot;);\n// result -&gt; &quot;Wheels Is A Framework&quot;\n\n// 2. Humanize a string and replace an abbreviation using the except argument\nresult = humanize(&quot;wheelsIsACfmlFramework&quot;, &quot;CFML&quot;);\n// result -&gt; &quot;Wheels Is A CFML Framework&quot;\n\n// 3. Humanize a multi-word property name from a model attribute\nresult = humanize(&quot;firstName&quot;);\n// result -&gt; &quot;First Name&quot;\n</code></pre>","hasExtended":true},"hint":"Returns readable text by capitalizing and converting camel casing to multiple words.\n\n","parameters":[{"type":"string","hint":"Text to humanize.","required":true,"name":"text"},{"type":"string","hint":"A list of strings (space separated) to replace within the output.","required":false,"name":"except","default":""}],"name":"humanize","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"string","slug":"controller.hyphenize","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic camelCase to hyphenated string\nresult = hyphenize(&quot;myBlogPost&quot;);\n// result -&gt; &quot;my-blog-post&quot;\n\n// 2. Single word (no change)\nresult = hyphenize(&quot;hello&quot;);\n// result -&gt; &quot;hello&quot;\n\n// 3. Used in URL slug generation\nslug = hyphenize(&quot;userProfileSettings&quot;);\n// slug -&gt; &quot;user-profile-settings&quot;\n</code></pre>","hasExtended":true},"hint":"Converts camelCase strings to lowercase strings with hyphens as word delimiters instead. Example: myVariable becomes my-variable.\n\n","parameters":[{"type":"string","hint":"The string to hyphenize.","required":true,"name":"string"}],"name":"hyphenize","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"void","slug":"model.ignoredColumns","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Ignore a single column in the model's config() method\n// In app/models/User.cfc\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tignoredColumns(columns=[&quot;legacyField&quot;]);\n\t}\n}\n\n// 2. Ignore multiple columns so they are excluded from Wheels ORM property mapping\n// In app/models/Product.cfc\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tignoredColumns(columns=[&quot;internalCode&quot;, &quot;deprecatedFlag&quot;, &quot;tempCache&quot;]);\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Use this method to specify which columns cannot be used by the wheels ORM.\n\n","parameters":[{"type":"array","hint":"Array of columns names that will be ignored.","required":false,"name":"columns","default":"[runtime expression]"}],"name":"ignoredColumns","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.imageTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Output an img tag for a local image (width, height, and alt are auto-detected)\nwriteOutput(imageTag(&quot;logo.png&quot;));\n\n// 2. Output an img tag for an image hosted on an external server\nwriteOutput(imageTag(source=&quot;https://example.com/images/logo.png&quot;, alt=&quot;Company Logo&quot;));\n\n// 3. Output an img tag with additional HTML attributes\nwriteOutput(imageTag(source=&quot;logo.png&quot;, class=&quot;logo&quot;, id=&quot;mainLogo&quot;));\n\n// 4. Output an img tag without requiring the file to exist locally (useful in development)\nwriteOutput(imageTag(source=&quot;placeholder.png&quot;, required=false));\n</code></pre>","hasExtended":true},"hint":"Returns an <code>img</code> tag.\nIf the image is stored in the local <code>images</code> folder, the tag will also set the <code>width</code>, <code>height</code>, and <code>alt</code> attributes for you.\nYou can pass any additional arguments (e.g. <code>class</code>, <code>rel</code>, <code>id</code>), and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"The file name of the image if it's available in the local file system (i.e. ColdFusion will be able to access it). Provide the full URL if the image is on a remote server.","required":true,"name":"source"},{"type":"boolean","required":false,"name":"onlyPath","default":true},{"type":"string","required":false,"name":"host","default":""},{"type":"string","required":false,"name":"protocol","default":""},{"type":"numeric","required":false,"name":"port","default":0},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"boolean","required":false,"name":"required","default":true}],"name":"imageTag","tags":{"category":"Asset Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"assetfunctions"}},{"returntype":"string","slug":"controller.imageUrl","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"URL publique d'un visuel a partir de sa cle logique.\nLa base est configurable pour que le stockage puisse changer sans toucher\naux vues : aujourd'hui un volume servi par Nginx, demain un stockage objet.\nC'est la raison pour laquelle la base ne stocke qu'une cle, jamais une URL.","parameters":[{"type":"string","required":false,"name":"key","default":""}],"name":"imageUrl","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"string","slug":"controller.includeContent","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Output the main page body inside a layout (default section is &quot;body&quot;)\n// In `app/views/layout.cfm`:\n&lt;html&gt;\n\t&lt;head&gt;\n\t\t&lt;title&gt;My Site&lt;/title&gt;\n\t&lt;/head&gt;\n\t&lt;body&gt;\n\t\t&lt;cfoutput&gt;\n\t\t\t#includeContent()#\n\t\t&lt;/cfoutput&gt;\n\t&lt;/body&gt;\n&lt;/html&gt;\n\n// 2. Define a named section in a view, then render it in the layout\n// In `app/views/blog/show.cfm`:\ncontentFor(head='&lt;meta name=&quot;description&quot; content=&quot;Read our latest post&quot;&gt;');\n\n// In `app/views/layout.cfm`:\n&lt;html&gt;\n\t&lt;head&gt;\n\t\t&lt;title&gt;My Site&lt;/title&gt;\n\t\t&lt;cfoutput&gt;#includeContent(&quot;head&quot;)#&lt;/cfoutput&gt;\n\t&lt;/head&gt;\n\t&lt;body&gt;\n\t\t&lt;cfoutput&gt;#includeContent()#&lt;/cfoutput&gt;\n\t&lt;/body&gt;\n&lt;/html&gt;\n\n// 3. Provide a default value when a section may not have been defined\n&lt;cfoutput&gt;\n\t#includeContent(name=&quot;sidebar&quot;, defaultValue=&quot;&lt;p&gt;No sidebar content.&lt;/p&gt;&quot;)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Used to output the content for a particular section in a layout.\n\n","parameters":[{"type":"string","hint":"Name of layout section to return content for.","required":false,"name":"name","default":"body"},{"type":"string","hint":"What to display as a default if the section is not defined.","required":false,"name":"defaultValue","default":""}],"name":"includeContent","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.includedInObject","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check whether a customer is already subscribed to a particular publication via a hasMany join\n// (Note: keys should be listed in the order they appear in the join table columns)\nif (includedInObject(objectName=&quot;customer&quot;, association=&quot;subscriptions&quot;, keys=&quot;#customer.key()#,#swimsuitEdition.id#&quot;)) {\n    writeOutput(&quot;Already subscribed.&quot;);\n} else {\n    writeOutput(&quot;Not yet subscribed.&quot;);\n}\n\n// 2. Use the return value to find the position of the associated object in the array\nposition = includedInObject(objectName=&quot;order&quot;, association=&quot;lineItems&quot;, keys=&quot;#lineItem.key()#&quot;);\n// Returns false when not found, or the 1-based index position when found\n// position -&gt; 3 (the associated lineItem is at index 3 in order.lineItems)\n\n// 3. Guard against adding duplicate associations before creating a new join record\nif (!includedInObject(objectName=&quot;student&quot;, association=&quot;courses&quot;, keys=&quot;#course.key()#&quot;)) {\n    student.courses = ArrayAppend(student.courses, course);\n}\n</code></pre>","hasExtended":true},"hint":"Used as a shortcut to check if the specified IDs are a part of the main form object.\nThis method should only be used for <code>hasMany</code> associations.\n\n","parameters":[{"type":"string","hint":"Name of the variable containing the parent object to represent with this form field.","required":true,"name":"objectName"},{"type":"string","hint":"Name of the association set in the parent object to represent with this form field.","required":true,"name":"association"},{"type":"string","hint":"Primary keys associated with this form field. Note that these keys should be listed in the order that they appear in the database table.","required":true,"name":"keys"}],"name":"includedInObject","tags":{"category":"Form Association Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formassociationfunctions"}},{"returntype":"string","slug":"controller.includeLayout","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Include the default parent layout from within a child layout\n// (looks for `app/views/layout.cfm` by default)\n#includeLayout()#\n\n// 2. Include a specific parent layout by path\n// (looks for `app/views/layouts/application.cfm`)\n#includeLayout(&quot;/layouts/application.cfm&quot;)#\n\n// 3. Pass section content to the parent layout before including it\n// Capture sidebar markup to make it available in the parent layout\n&lt;cfsavecontent variable=&quot;sidebar&quot;&gt;\n  &lt;nav&gt;\n    #includePartial(&quot;categories&quot;)#\n  &lt;/nav&gt;\n&lt;/cfsavecontent&gt;\n&lt;cfset contentFor(sidebar=sidebar)&gt;\n\n// Then pull in the parent layout that renders the sidebar via includeContent()\n#includeLayout(&quot;/layouts/application.cfm&quot;)#\n</code></pre>","hasExtended":true},"hint":"Includes the contents of another layout file.\nThis is usually used to include a parent layout from within a child layout.\n\n","parameters":[{"type":"string","hint":"Name of the layout file to include.","required":false,"name":"name","default":"layout"}],"name":"includeLayout","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.includePartial","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Include a partial from the current controller's view folder.\n//    When in the &quot;sessions&quot; controller, Wheels looks for &quot;app/views/sessions/_login.cfm&quot;.\n#includePartial(&quot;login&quot;)#\n\n// 2. Include a partial relative to the root views folder using a leading slash.\n//    Wheels looks for &quot;app/views/shared/_button.cfm&quot;.\n#includePartial(partial=&quot;/shared/button&quot;)#\n\n// 3. Pass a query to loop through records automatically.\n//    Wheels loops through the result set and renders &quot;app/views/posts/_post.cfm&quot; for each row.\nposts = model(&quot;Post&quot;).findAll();\n#includePartial(posts)#\n\n// 4. Override the template when rendering a query.\n//    Provide the template path via partial and pass the query separately.\nposts = model(&quot;Post&quot;).findAll();\n#includePartial(partial=&quot;/shared/post&quot;, query=posts)#\n\n// 5. Pass a single model object — Wheels renders the matching partial for its model type.\npost = model(&quot;Post&quot;).findByKey(params.key);\n#includePartial(post)#\n\n// 6. Override the template when rendering a single model object.\npost = model(&quot;Post&quot;).findByKey(params.key);\n#includePartial(partial=&quot;/shared/post&quot;, object=post)#\n\n// 7. Pass an array of model objects — Wheels iterates and renders the partial for each.\nposts = model(&quot;Post&quot;).findAll(returnAs=&quot;objects&quot;);\n#includePartial(posts)#\n\n// 8. Override the template when rendering an array of model objects.\nposts = model(&quot;Post&quot;).findAll(returnAs=&quot;objects&quot;);\n#includePartial(partial=&quot;/shared/post&quot;, objects=posts)#\n\n// 9. Cache the partial output for 30 minutes to reduce processing overhead.\n#includePartial(partial=&quot;sidebar&quot;, cache=30)#\n\n// 10. Group a query result set by a column before rendering.\n//     Wheels splits the query into sub-queries grouped by &quot;categoryId&quot;\n//     and passes each sub-query into &quot;app/views/products/_product.cfm&quot;.\nproducts = model(&quot;Product&quot;).findAll(order=&quot;categoryId&quot;);\n#includePartial(partial=&quot;product&quot;, query=products, group=&quot;categoryId&quot;)#\n\n// 11. Insert a separator string between each rendered partial in a loop.\nposts = model(&quot;Post&quot;).findAll();\n#includePartial(partial=&quot;post&quot;, query=posts, spacer=&quot;&lt;hr&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Includes the specified partial file in the view.\nSimilar to using <code>cfinclude</code> but with the ability to cache the result and use Wheels-specific file look-up.\nBy default, Wheels will look for the file in the current controller's view folder.\nTo include a file relative from the base <code>views</code> folder, you can start the path supplied to <code>partial</code> with a forward slash.\n\n","parameters":[{"type":"any","hint":"The name of the partial file to be used. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder. Do not include the partial filename's underscore and file extension. If you want to have Wheels display the partial for a single model object, array of model objects, or a query, pass a variable containing that data into this argument.","required":true,"name":"partial"},{"type":"string","hint":"If passing a query result set for the partial argument, use this to specify the field to group the query by. A new query will be passed into the partial template for you to iterate over.","required":false,"name":"group","default":""},{"type":"any","hint":"Number of minutes to cache the content for.","required":false,"name":"cache","default":""},{"type":"string","hint":"The layout to wrap the content in. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder. Pass `false` to not load a layout at all.","required":false,"name":"layout","default":""},{"type":"string","hint":"HTML or string to place between partials when called using a query.","required":false,"name":"spacer","default":""},{"type":"any","hint":"Name of controller function to load data from.","required":false,"name":"dataFunction","default":true},{"type":"boolean","required":false,"name":"$prependWithUnderscore","default":true}],"name":"includePartial","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"controller.initSSEStream","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Initialize a streaming SSE connection that bypasses the normal Wheels rendering pipeline.\nReturns a writer object that can be used with sendSSEEvent() and closeSSEStream().\nThis enables sending multiple events over a single connection.\nNote: This bypasses layouts and after-filters. Use for true streaming endpoints only.","parameters":[],"name":"initSSEStream","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"void","slug":"controller.inject","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Declare one or more services for injection into this controller.\nCall in config(). Services are resolved when the controller instance is created.","parameters":[{"type":"string","hint":"Comma-delimited list of registered service names to inject.","required":true,"name":"name"}],"name":"inject","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"array","slug":"controller.injectedServices","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Return the list of declared service names for this controller.","parameters":[],"name":"injectedServices","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"any","slug":"controller.injector","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a singleton service in `config/services.cfm` (one instance per app lifetime)\ndi = injector();\ndi.map(&quot;emailService&quot;).to(&quot;app.lib.EmailService&quot;).asSingleton();\n\n// 2. Bind an interface name to a concrete implementation\ndi = injector();\ndi.bind(&quot;INotifier&quot;).to(&quot;app.lib.SlackNotifier&quot;).asSingleton();\n\n// 3. Register a request-scoped service (one instance per HTTP request)\ndi = injector();\ndi.map(&quot;currentUser&quot;).to(&quot;app.lib.CurrentUserResolver&quot;).asRequestScoped();\n\n// 4. Inspect or resolve at runtime\ndi = injector();\nif (di.containsInstance(&quot;emailService&quot;)) {\n    mailer = di.getInstance(&quot;emailService&quot;);\n    mailer.send(to=&quot;user@example.com&quot;, subject=&quot;Welcome&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Return a reference to the DI container for direct configuration.\n\n","parameters":[],"name":"injector","tags":{"category":"Miscellaneous Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"struct","slug":"model.insertAll","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Insert multiple user records in a single batch\nnewUsers = [\n    {firstName: &quot;Alice&quot;, lastName: &quot;Smith&quot;, email: &quot;alice@example.com&quot;},\n    {firstName: &quot;Bob&quot;,   lastName: &quot;Jones&quot;, email: &quot;bob@example.com&quot;},\n    {firstName: &quot;Carol&quot;, lastName: &quot;White&quot;, email: &quot;carol@example.com&quot;}\n];\nresult = model(&quot;User&quot;).insertAll(records=newUsers);\n// result -&gt; {insertedCount: 3}\n\n// 2. Insert records without automatic createdAt/updatedAt timestamps\nrows = [\n    {username: &quot;imported_1&quot;, score: 9800},\n    {username: &quot;imported_2&quot;, score: 7450}\n];\nresult = model(&quot;HighScore&quot;).insertAll(records=rows, timestamps=false);\n// result -&gt; {insertedCount: 2}\n\n// 3. Insert a large dataset wrapped in a single transaction, using selective cfqueryparam\nproducts = [];\nfor (i = 1; i &lt;= 2500; i++) {\n    arrayAppend(products, {name: &quot;Product #i#&quot;, price: RandRange(1, 999), stock: RandRange(0, 500)});\n}\n// Batches automatically in groups of 1000; all batches share one transaction.\nresult = model(&quot;Product&quot;).insertAll(\n    records      = products,\n    transaction  = &quot;commit&quot;,\n    parameterize = &quot;price,stock&quot;\n);\n// result -&gt; {insertedCount: 2500}\n</code></pre>","hasExtended":true},"hint":"Inserts multiple records into the database in a single batch operation.\nAccepts an array of structs where each struct represents a record to insert.\nAll structs must have the same set of keys (property names).\nBatches in groups of 1000 to avoid database parameter limits.\n\n","parameters":[{"type":"array","hint":"Array of structs, each containing property name/value pairs to insert.","required":true,"name":"records"},{"type":"boolean","hint":"Set to `false` to skip automatic `createdAt`/`updatedAt` timestamping.","required":false,"name":"timestamps","default":true},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true}],"name":"insertAll","tags":{"category":"Create Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"createfunctions"}},{"returntype":"any","slug":"tabledefinition.integer","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single integer column to a new table\nt = createTable(name='products');\n\tt.string(columnNames='name', limit=255, allowNull=false);\n\tt.integer(columnNames='quantity');\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple integer columns at once with a default value\nt = createTable(name='scores');\n\tt.integer(columnNames='wins,losses,draws', default=0, allowNull=false);\n\tt.string(columnNames='playerName', limit=100, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add an integer column with a limit when altering an existing table\nt = changeTable(name='orders');\n\tt.integer(columnNames='itemCount', default=0, allowNull=false, limit=4);\nt.change();\n</code></pre>","hasExtended":true},"hint":"adds integer columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"numeric","required":false,"name":"limit"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"integer","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"any","slug":"model.invokeWithTransaction","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Run a custom model method inside a database transaction.\n// Define the method on the model (e.g. Person.cfc):\npublic boolean function transferFunds(required any personFrom, required any personTo, required numeric amount) {\n\tif (arguments.personFrom.withdraw(arguments.amount) &amp;&amp; arguments.personTo.deposit(arguments.amount)) {\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n// Then invoke it wrapped in a transaction from a controller action:\nlocal.david = model(&quot;Person&quot;).findOneByName(&quot;David&quot;);\nlocal.mary = model(&quot;Person&quot;).findOneByName(&quot;Mary&quot;);\nlocal.success = model(&quot;Person&quot;).invokeWithTransaction(method=&quot;transferFunds&quot;, personFrom=local.david, personTo=local.mary, amount=100);\n\n// 2. Run in rollback mode to test queries without committing changes.\nlocal.success = model(&quot;Person&quot;).invokeWithTransaction(method=&quot;transferFunds&quot;, personFrom=local.david, personTo=local.mary, amount=100, transaction=&quot;rollback&quot;);\n\n// 3. Run with a stricter isolation level (e.g. serializable) to prevent phantom reads.\nlocal.success = model(&quot;Person&quot;).invokeWithTransaction(method=&quot;transferFunds&quot;, personFrom=local.david, personTo=local.mary, amount=100, isolation=&quot;serializable&quot;);\n</code></pre>","hasExtended":true},"hint":"Runs the specified method within a single database transaction.\n\n","parameters":[{"type":"string","hint":"Model method to run.","required":true,"name":"method"},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"commit"},{"type":"string","hint":"Isolation level to be passed through to the cftransaction tag. See your CFML engine's documentation for more details about cftransaction's isolation attribute.","required":false,"name":"isolation","default":"read_committed"}],"name":"invokeWithTransaction","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isAjax","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Respond differently based on whether the request is an AJAX call\nif (isAjax()) {\n    renderNothing();\n} else {\n    redirectTo(action = &quot;index&quot;);\n}\n\n// 2. Return JSON for AJAX requests, render a full view otherwise\nif (isAjax()) {\n    renderWith(data = model(&quot;Article&quot;).findAll(returnAs = &quot;objects&quot;));\n} else {\n    articles = model(&quot;Article&quot;).findAll();\n}\n</code></pre>","hasExtended":true},"hint":"Returns whether the page was called from JavaScript or not.\n\n","parameters":[],"name":"isAjax","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"model.isClass","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Use isClass() to branch between class-level and instance-level behavior\n// In a model method, detect whether the method is being called on the class\n// (e.g. model(&quot;User&quot;).isAdmin(42)) or on an instance (e.g. user.isAdmin()).\nfunction isAdmin(numeric id) {\n\tif (isClass()) {\n\t\t// Called on the class — look up the record by the provided id\n\t\treturn this.findByKey(arguments.id).admin;\n\t} else {\n\t\t// Called on an instance — the property is already available\n\t\treturn this.admin;\n\t}\n}\n\n// 2. Guard a class-only operation\nfunction resetAllPasswords() {\n\tif (!isClass()) {\n\t\tThrow(type=&quot;App.Error&quot;, message=&quot;resetAllPasswords must be called on the class, not an instance.&quot;);\n\t}\n\tthis.updateAll(password=&quot;changeme&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Use this method to check whether you are currently in a class-level object.\n\n","parameters":[],"name":"isClass","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isDelete","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Only process delete logic when the request method is DELETE\nif (isDelete()) {\n    // perform delete operation\n}\n\n// 2. Assign the result to a variable for later use\nrequestIsDelete = isDelete();\n</code></pre>","hasExtended":true},"hint":"Returns whether the request was a <code>DELETE</code> request or not.\n\n","parameters":[],"name":"isDelete","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isGet","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Only allow GET requests in an action\nif (!isGet()) {\n    redirectTo(action = &quot;index&quot;);\n}\n\n// 2. Respond differently depending on the HTTP method\nif (isGet()) {\n    // Render the form for display\n    user = model(&quot;User&quot;).findByKey(params.key);\n} else {\n    // Handle a non-GET submission\n    renderNothing();\n}\n\n// 3. Store the result to use in a conditional\nrequestIsGet = isGet();\n// requestIsGet -&gt; true (for a normal page request), false otherwise\n</code></pre>","hasExtended":true},"hint":"Returns whether the request was a normal <code>GET</code> request or not.\n\n","parameters":[],"name":"isGet","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isHead","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Respond to a HEAD request by rendering nothing\nif (isHead()) {\n    renderNothing();\n}\n\n// 2. Restrict an action to HEAD requests only\nif (!isHead()) {\n    renderText(&quot;Method not allowed&quot;);\n}\n\n// 3. Store the result to use in a conditional\nrequestIsHead = isHead();\n// requestIsHead -&gt; true when the HTTP method is HEAD, false otherwise\n</code></pre>","hasExtended":true},"hint":"Returns whether the request was a <code>HEAD</code> request or not.\n\n","parameters":[],"name":"isHead","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"model.isInstance","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Branch logic inside a shared model method based on class vs. instance context\nfunction memberIsAdmin() {\n\tif (isInstance()) {\n\t\t// Called on an instance object — property is already loaded\n\t\treturn this.admin;\n\t} else {\n\t\t// Called on the class — look up the record first\n\t\treturn this.findByKey(arguments.id).admin;\n\t}\n}\n\n// 2. Use isInstance() in config() to guard instance-only setup\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tif (isInstance()) {\n\t\t\t// Instance-specific initialization (rarely needed; shown for contrast)\n\t\t} else {\n\t\t\t// Class-level configuration: validations, associations, callbacks\n\t\t\tvalidatesPresenceOf(properties=&quot;username,email&quot;);\n\t\t\thasMany(name=&quot;posts&quot;);\n\t\t}\n\t}\n}\n\n// 3. Pair with isClass() to make the intent explicit\nfunction label() {\n\tif (isClass()) {\n\t\treturn &quot;User (class)&quot;;\n\t}\n\treturn &quot;User #this.id#&quot;;\n}\n</code></pre>","hasExtended":true},"hint":"Use this method to check whether you are currently in an instance object.\n\n","parameters":[],"name":"isInstance","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"model.isNew","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if a newly instantiated object has been saved to the database\nemployee = model(&quot;Employee&quot;).new(firstName=&quot;Jane&quot;, lastName=&quot;Doe&quot;);\nif (employee.isNew()) {\n    // employee.save() has not been called yet, so no DB record exists\n    employee.save();\n}\n\n// 2. Check after loading from the database (isNew() returns false for persisted records)\nemployee = model(&quot;Employee&quot;).findOne(where=&quot;firstName='Jane'&quot;);\nif (!employee.isNew()) {\n    // record already exists in the database\n    employee.firstName = &quot;Janet&quot;;\n    employee.save();\n}\n\n// 3. Useful inside a before/after callback to branch logic for new vs. existing records\n// In Employee.cfc:\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        beforeSave(&quot;stampAuditFields&quot;);\n    }\n    private function stampAuditFields() {\n        if (isNew()) {\n            this.createdBy = request.currentUserId;\n        }\n        this.updatedBy = request.currentUserId;\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Returns <code>true</code> if this object hasn't been saved yet (in other words, no matching record exists in the database yet).\nReturns <code>false</code> if a record exists.\n\n","parameters":[],"name":"isNew","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isOptions","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Respond to a CORS preflight OPTIONS request\nif (isOptions()) {\n    header(name = &quot;Access-Control-Allow-Methods&quot;, value = &quot;GET, POST, PUT, DELETE&quot;);\n    renderNothing();\n    return;\n}\n\n// 2. Restrict an action to only handle OPTIONS requests\nif (!isOptions()) {\n    redirectTo(action = &quot;index&quot;);\n}\n\n// 3. Store the result to use in a conditional\nrequestIsOptions = isOptions();\n// requestIsOptions -&gt; true when the HTTP method is OPTIONS, false otherwise\n</code></pre>","hasExtended":true},"hint":"Returns whether the request was an <code>OPTIONS</code> request or not.\n\n","parameters":[],"name":"isOptions","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isPatch","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Only handle PATCH requests in an action\nif (!isPatch()) {\n    redirectTo(action = &quot;index&quot;);\n}\n\n// 2. Respond differently depending on whether the request is a PATCH\nif (isPatch()) {\n    // Apply a partial update to the resource\n    user = model(&quot;User&quot;).findByKey(params.key);\n    user.update(params.user);\n} else {\n    // Not a PATCH request; redirect away\n    redirectTo(action = &quot;index&quot;);\n}\n\n// 3. Store the result to use in a conditional\nrequestIsPatch = isPatch();\n// requestIsPatch -&gt; true for a PATCH request, false otherwise\n</code></pre>","hasExtended":true},"hint":"Returns whether the request was a <code>PATCH</code> request or not.\n\n","parameters":[],"name":"isPatch","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"model.isPersisted","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if a newly created (unsaved) object has been persisted\nuser = model(&quot;User&quot;).new(firstName=&quot;Jane&quot;, lastName=&quot;Doe&quot;);\nwriteOutput(user.isPersisted()); // -&gt; false\n\n// 2. Check if an object loaded from the database is persisted\nuser = model(&quot;User&quot;).findByKey(1);\nwriteOutput(user.isPersisted()); // -&gt; true\n\n// 3. Check persistence after saving a new object\npost = model(&quot;Post&quot;).new(title=&quot;Hello World&quot;, body=&quot;First post.&quot;);\npost.save();\nwriteOutput(post.isPersisted()); // -&gt; true\n</code></pre>","hasExtended":true},"hint":"Returns <code>true</code> if this object has been persisted to the database or was loaded from the database via a finder.\nReturns <code>false</code> if the record has not been persisted to the database.\n\n","parameters":[],"name":"isPersisted","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isPost","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Respond differently depending on whether the request is a POST\nif (isPost()) {\n    // Process the submitted form data\n    user = model(&quot;User&quot;).new(params.user);\n    if (user.save()) {\n        redirectTo(action=&quot;index&quot;);\n    } else {\n        renderView(action=&quot;new&quot;);\n    }\n} else {\n    renderView(action=&quot;new&quot;);\n}\n\n// 2. Guard an action so it only accepts POST requests\nfunction create() {\n    if (!isPost()) {\n        renderNothing(status=&quot;405 Method Not Allowed&quot;);\n        return;\n    }\n    // handle form submission\n}\n\n// 3. Store the result for later use in the action\nrequestIsPost = isPost();\n// requestIsPost -&gt; true (when submitted via a form POST)\n// requestIsPost -&gt; false (when the page is visited normally with GET)\n</code></pre>","hasExtended":true},"hint":"Returns whether the request came from a form <code>POST</code> submission or not.\n\n","parameters":[],"name":"isPost","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isPut","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Allow only PUT requests for a resource update action\nif (!isPut()) {\n    redirectTo(action = &quot;index&quot;);\n}\n// ... proceed with update logic\n\n// 2. Branch behavior based on HTTP method\nif (isPut()) {\n    // Full replacement of the resource\n    user = model(&quot;User&quot;).findByKey(params.key);\n    user.update(params.user);\n    redirectTo(action = &quot;show&quot;, key = user.key());\n} else {\n    renderNothing();\n}\n</code></pre>","hasExtended":true},"hint":"Returns whether the request was a <code>PUT</code> request or not.\n\n","parameters":[],"name":"isPut","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isSecure","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Redirect non-secure connections to the HTTPS version\nif (!isSecure()) {\n\tredirectTo(protocol=&quot;https&quot;);\n}\n\n// 2. Conditionally set a secure cookie flag based on the connection\ncookieOptions = {secure: isSecure(), httpOnly: true};\n\n// 3. Log a warning when a sensitive action is performed over a non-secure connection\nif (!isSecure()) {\n\tlogMessage(&quot;WARNING: sensitive action performed over non-secure connection&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Returns whether Wheels is communicating over a secure port.\n<code>X-Forwarded-Proto</code> is client-controlled and is only honored when the app has opted into\nproxy trust via <code>set(trustProxyHeaders=true)</code> behind a trusted reverse proxy.\n\n","parameters":[],"name":"isSecure","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.isSSERequest","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Check if the current request is from an EventSource client.\nUseful for conditionally rendering SSE vs HTML responses.","parameters":[],"name":"isSSERequest","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"string","slug":"controller.javaScriptIncludeTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>&lt;!--- view code ---&gt;\n&lt;head&gt;\n    &lt;!--- Includes `javascripts/main.js` ---&gt;\n    #javaScriptIncludeTag(&quot;main&quot;)#\n\n    &lt;!--- Includes `javascripts/blog.js` and `javascripts/accordion.js` ---&gt;\n    #javaScriptIncludeTag(&quot;blog,accordion&quot;)#\n\n    &lt;!--- Includes an external JavaScript file ---&gt;\n    #javaScriptIncludeTag(&quot;https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js&quot;)#\n\n    &lt;!--- Uses a pipe delimiter instead of the default comma ---&gt;\n    #javaScriptIncludeTag(sources=&quot;app|utils|vendor&quot;, delim=&quot;|&quot;)#\n&lt;/head&gt;\n\n&lt;body&gt;\n    &lt;!--- Will still appear in the `head` ---&gt;\n    #javaScriptIncludeTag(source=&quot;tabs&quot;, head=true)#\n&lt;/body&gt;\n</code></pre>","hasExtended":true},"hint":"Returns a <code>script</code> tag for a JavaScript file (or several) based on the supplied arguments.\n\n","parameters":[{"type":"string","hint":"The name of one or many JavaScript files in the `javascripts` folder, minus the `.js` extension. Pass a full URL to access an external JavaScript file. Can also be called with the `source` argument.","required":false,"name":"sources","default":""},{"type":"string","hint":"The `type` attribute for the `script` tag.","required":false,"name":"type","default":"text/javascript"},{"type":"boolean","hint":"Set to `true` to place the output in the `head` area of the HTML page instead of the default behavior (which is to place the output where the function is called from).","required":false,"name":"head","default":false},{"type":"string","hint":"The delimiter to use for the list of JavaScript files.","required":false,"name":"delim","default":","},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"javaScriptIncludeTag","tags":{"category":"Asset Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"assetfunctions"}},{"returntype":"string","slug":"model.key","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the primary key value of a found object\nemployee = model(&quot;Employee&quot;).findByKey(params.key);\nwriteOutput(employee.key());\n// -&gt; 42\n\n// 2. Use key() when you don't know the primary key column name (dynamic programming)\nobj = model(params.modelName).findByKey(params.id);\nif (IsObject(obj)) {\n\twriteOutput(&quot;Found record with key: &quot; &amp; obj.key());\n}\n\n// 3. Composite primary key — key() returns a comma-delimited list of both values\norderItem = model(&quot;OrderItem&quot;).findByKey(key=&quot;1,5&quot;);\nwriteOutput(orderItem.key());\n// -&gt; 1,5 (orderId and productId combined)\n</code></pre>","hasExtended":true},"hint":"Returns the value of the primary key for the object.\nIf you have a single primary key named id, then <code>someObject.key()</code> is functionally equivalent to <code>someObject.id</code>.\nThis method is more useful when you do dynamic programming and don't know the name of the primary key or when you use composite keys (in which case it's convenient to use this method to get a list of both key values returned).\n\n","parameters":[{"type":"boolean","required":false,"name":"$persisted","default":false},{"type":"boolean","required":false,"name":"$returnTickCountWhenNew","default":false}],"name":"key","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.lastPageLink","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>//--------------------------------------------------------------------\n// Example 1: Basic usage — show a &quot;Last&quot; link at the bottom of a\n// paginated list; renders a disabled span when already on the last page\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts = model(&quot;Post&quot;).findAll(page=params.page, perPage=10, order=&quot;createdAt DESC&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #firstPageLink()#\n    #previousPageLink()#\n    #pageNumberLinks()#\n    #nextPageLink()#\n    #lastPageLink()#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom link text and CSS classes\n\n// View code\n&lt;cfoutput&gt;\n    #lastPageLink(\n        text=&quot;Last &amp;raquo;&amp;raquo;&quot;,\n        class=&quot;page-link&quot;,\n        disabledClass=&quot;page-link disabled&quot;\n    )#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 3: Hide the disabled element entirely when on the last page\n\n// View code\n&lt;cfoutput&gt;\n    #lastPageLink(showDisabled=false)#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 4: Use a named route so page numbers appear in the URL path\n// instead of as a query-string param (e.g. /articles/page/3)\n\n// Route setup in app/config/routes.cfm\nmapper()\n    .get(name=&quot;paginatedArticles&quot;, pattern=&quot;articles/page/[page]&quot;, to=&quot;articles##index&quot;)\n    .get(name=&quot;articles&quot;, pattern=&quot;articles&quot;, to=&quot;articles##index&quot;)\n.end();\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\narticles = model(&quot;Article&quot;).findAll(page=params.page, perPage=20, order=&quot;title&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #lastPageLink(route=&quot;paginatedArticles&quot;, pageNumberAsParam=false)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Creates a link to the last page, or a disabled span when already on the last page.\n\n","parameters":[{"type":"string","hint":"The text for the link.","required":false,"name":"text","default":"Last"},{"type":"string","hint":"The handle given to the query that the pagination should be displayed for.","required":false,"name":"handle","default":"query"},{"type":"string","hint":"The name of the param that holds the current page number.","required":false,"name":"name","default":"page"},{"type":"string","hint":"CSS class for the link element.","required":false,"name":"class","default":""},{"type":"string","hint":"CSS class for the disabled span element.","required":false,"name":"disabledClass","default":"disabled"},{"type":"boolean","hint":"Whether to render a disabled span when already on the last page.","required":false,"name":"showDisabled","default":true},{"type":"boolean","hint":"Decides whether to link the page number as a param or as part of a route.","required":false,"name":"pageNumberAsParam","default":true},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"lastPageLink","tags":{"category":"Pagination Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"paginationfunctions"}},{"returntype":"string","slug":"controller.linkTo","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Link to a controller/action pair\nwriteOutput(linkTo(text=&quot;Log Out&quot;, controller=&quot;account&quot;, action=&quot;logout&quot;));\n// -&gt; &lt;a href=&quot;/account/logout&quot;&gt;Log Out&lt;/a&gt;\n\n// 2. Omit the controller when linking within the same controller\n// (CFWheels uses the current controller automatically)\nwriteOutput(linkTo(text=&quot;Log Out&quot;, action=&quot;logout&quot;));\n// -&gt; &lt;a href=&quot;/account/logout&quot;&gt;Log Out&lt;/a&gt;\n\n// 3. Link to a specific record using a key\nwriteOutput(linkTo(text=&quot;View Post&quot;, controller=&quot;blog&quot;, action=&quot;post&quot;, key=99));\n// -&gt; &lt;a href=&quot;/blog/post/99&quot;&gt;View Post&lt;/a&gt;\n\n// 4. Pass extra query string parameters\nwriteOutput(linkTo(text=&quot;View Settings&quot;, action=&quot;settings&quot;, params=&quot;show=all&amp;sort=asc&quot;));\n// -&gt; &lt;a href=&quot;/account/settings?show=all&amp;amp;sort=asc&quot;&gt;View Settings&lt;/a&gt;\n\n// 5. Use a named route (configured in app/config/routes.cfm)\nwriteOutput(linkTo(text=&quot;Joe's Profile&quot;, route=&quot;userProfile&quot;, userName=&quot;joe&quot;));\n// -&gt; &lt;a href=&quot;/user/joe&quot;&gt;Joe's Profile&lt;/a&gt;\n\n// 6. Link to an external URL, bypassing the routing system\nwriteOutput(linkTo(text=&quot;ColdFusion on Wheels&quot;, href=&quot;https://cfwheels.org/&quot;));\n// -&gt; &lt;a href=&quot;https://cfwheels.org/&quot;&gt;ColdFusion on Wheels&lt;/a&gt;\n\n// 7. Add HTML attributes (class, id, rel, etc.) via extra arguments\nwriteOutput(linkTo(text=&quot;Delete Post&quot;, action=&quot;delete&quot;, key=99, class=&quot;delete&quot;, id=&quot;delete-99&quot;));\n// -&gt; &lt;a class=&quot;delete&quot; href=&quot;/blog/delete/99&quot; id=&quot;delete-99&quot;&gt;Delete Post&lt;/a&gt;\n\n// 8. Include icon markup in link text; use encode=&quot;attributes&quot; to encode\n//    only attribute values and leave the tag content (the icon HTML) untouched\nwriteOutput(linkTo(text=&quot;&lt;i class='fa fa-trash'&gt;&lt;/i&gt; Delete Post&quot;, encode=&quot;attributes&quot;, action=&quot;delete&quot;, key=99));\n// -&gt; &lt;a href=&quot;/blog/delete/99&quot;&gt;&lt;i class='fa fa-trash'&gt;&lt;/i&gt; Delete Post&lt;/a&gt;\n\n// 9. Build an absolute URL by turning off onlyPath and setting a protocol/host\nwriteOutput(linkTo(text=&quot;Home&quot;, action=&quot;index&quot;, onlyPath=false, protocol=&quot;https&quot;, host=&quot;www.example.com&quot;));\n// -&gt; &lt;a href=&quot;https://www.example.com/home/index&quot;&gt;Home&lt;/a&gt;\n\n// 10. Link to an anchor on the target page\nwriteOutput(linkTo(text=&quot;Jump to Comments&quot;, controller=&quot;blog&quot;, action=&quot;post&quot;, key=99, anchor=&quot;comments&quot;));\n// -&gt; &lt;a href=&quot;/blog/post/99#comments&quot;&gt;Jump to Comments&lt;/a&gt;\n</code></pre>","hasExtended":true},"hint":"Creates a link to another page in your application.\nPass in the name of a route to use your configured routes or a controller/action/key combination.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"The text content of the link.","required":false,"name":"text"},{"type":"string","hint":"Name of a route that you have configured in config/routes.cfm.","required":false,"name":"route","default":""},{"type":"string","hint":"Name of the controller to include in the URL.","required":false,"name":"controller","default":""},{"type":"string","hint":"Name of the action to include in the URL.","required":false,"name":"action","default":""},{"type":"any","hint":"Key(s) to include in the URL.","required":false,"name":"key","default":""},{"type":"string","hint":"Any additional parameters to be set in the query string (example: wheels=cool&x=y). Please note that Wheels uses the & and = characters to split the parameters and encode them properly for you. However, if you need to pass in & or = as part of the value, then you need to encode them (and only them), example: a=cats%26dogs%3Dtrouble!&b=1.","required":false,"name":"params","default":""},{"type":"string","hint":"Sets an anchor name to be appended to the path.","required":false,"name":"anchor","default":""},{"type":"boolean","hint":"If true, returns only the relative URL (no protocol, host name or port).","required":false,"name":"onlyPath","default":true},{"type":"string","hint":"Set this to override the current host.","required":false,"name":"host","default":""},{"type":"string","hint":"Set this to override the current protocol.","required":false,"name":"protocol","default":""},{"type":"numeric","hint":"Set this to override the current port number.","required":false,"name":"port","default":0},{"type":"string","hint":"Pass a link to an external site here if you want to bypass the Wheels routing system altogether and link to an external URL.","required":false,"name":"href"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"linkTo","tags":{"category":"Link Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"linkfunctions"}},{"returntype":"string","slug":"controller.mailTo","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic mailto link using the email address as the link text\nmailTo(emailAddress=&quot;webmaster@example.com&quot;);\n// -&gt; &lt;a href=&quot;mailto:webmaster@example.com&quot;&gt;webmaster@example.com&lt;/a&gt;\n\n// 2. Mailto link with a custom display name\nmailTo(emailAddress=&quot;support@example.com&quot;, name=&quot;Contact Support&quot;);\n// -&gt; &lt;a href=&quot;mailto:support@example.com&quot;&gt;Contact Support&lt;/a&gt;\n\n// 3. Mailto link with additional HTML attributes (class, title)\nmailTo(emailAddress=&quot;info@example.com&quot;, name=&quot;Email Us&quot;, class=&quot;email-link&quot;, title=&quot;Send us a message&quot;);\n// -&gt; &lt;a href=&quot;mailto:info@example.com&quot; class=&quot;email-link&quot; title=&quot;Send us a message&quot;&gt;Email Us&lt;/a&gt;\n</code></pre>","hasExtended":true},"hint":"Creates a <code>mailto</code> link tag to the specified email address, which is also used as the name of the link unless name is specified.\n\n","parameters":[{"type":"string","hint":"The email address to link to.","required":true,"name":"emailAddress"},{"type":"string","hint":"A string to use as the link text (\"Joe\" or \"Support Department\", for example).","required":false,"name":"name","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"mailTo","tags":{"category":"Link Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"linkfunctions"}},{"returntype":"struct","slug":"controller.mapper","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"","hasExtended":false},"hint":"Returns the mapper object used to configure your application's routes. Usually you will use this method in <code>config/routes.cfm</code> to start chaining route mapping methods like <code>resources</code>, <code>namespace</code>, etc.\n\n","parameters":[{"type":"boolean","hint":"Whether to turn on RESTful routing or not. Not recommended to set. Will probably be removed in a future version of wheels, as RESTful routes are the default.","required":false,"name":"restful","default":true},{"type":"boolean","hint":"If not RESTful, then specify allowed routes. Not recommended to set. Will probably be removed in a future version of wheels, as RESTful routes are the default.","required":false,"name":"methods","default":"[runtime expression]"},{"type":"boolean","hint":"This is useful for providing formats via URL like `json`, `xml`, `pdf`, etc. Set to false to disable automatic .[format] generation for resource based routes","required":false,"name":"mapFormat","default":true}],"name":"mapper","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"any","slug":"model.maximum","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the highest salary across all employees\nhighestSalary = model(&quot;employee&quot;).maximum(&quot;salary&quot;);\n\n// 2. Get the highest salary for employees in a specific department\nhighestSalary = model(&quot;employee&quot;).maximum(property=&quot;salary&quot;, where=&quot;departmentId=#params.key#&quot;);\n\n// 3. Return 0 instead of a blank string when no matching records are found\nhighestSalary = model(&quot;employee&quot;).maximum(property=&quot;salary&quot;, where=&quot;salary &gt; #params.minSalary#&quot;, ifNull=0);\n\n// 4. Get the highest salary per department (returns a query with departmentId and the maximum value)\nsalaryByDept = model(&quot;employee&quot;).maximum(property=&quot;salary&quot;, group=&quot;departmentId&quot;);\n</code></pre>","hasExtended":true},"hint":"Calculates the maximum value for a given property.\nUses the SQL function <code>MAX</code>.\nIf no records can be found to perform the calculation on you can use the <code>ifNull</code> argument to decide what should be returned.\n\n","parameters":[{"type":"string","hint":"Name of the property to get the highest value for (must be a property of a numeric data type).","required":true,"name":"property"},{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"any","required":false,"name":"parameterize","default":true},{"type":"any","hint":"The value returned if no records are found. Common usage is to set this to `0` to make sure a numeric value is always returned instead of a blank string.","required":false,"name":"ifNull","default":""},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"},{"type":"string","hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"group"}],"name":"maximum","tags":{"category":"Statistics Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"statisticsfunctions"}},{"returntype":"struct","slug":"mapper.member","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\n// 1. Add a preview route acting on a single photo (GET /photos/1/preview)\nmapper()\n    .resources(name=&quot;photos&quot;, nested=true)\n        .member()\n            .get(&quot;preview&quot;)\n        .end()\n    .end()\n.end();\n\n// 2. Add multiple member routes (GET /articles/1/publish, DELETE /articles/1/archive)\nmapper()\n    .resources(name=&quot;articles&quot;, nested=true)\n        .member()\n            .get(&quot;publish&quot;)\n            .delete(&quot;archive&quot;)\n        .end()\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Scope routes within a nested resource which require use of the primary key as part of the URL pattern;\nA member route will require an ID, because it acts on a member.\nphotos/1/preview is an example of a member route, because it acts on (and displays) a single object.\n\n","parameters":[],"name":"member","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"migrator.migrateIndividual","availableIn":["migrator"],"extended":{"docs":"<pre><code class='javascript'>// 1. Run a specific migration by version number (out-of-sequence)\nresult = application.wheels.migrator.migrateIndividual(&quot;20240315120000&quot;);\n// result -&gt; &quot;Running individual migration 20240315120000.\n// -------- 20240315120000_add_status_to_orders --------------------\n// &quot;\n\n// 2. Check the result string for errors or success messages\nresult = application.wheels.migrator.migrateIndividual(&quot;20240101000000&quot;);\nif (FindNoCase(&quot;Error&quot;, result)) {\n    writeOutput(&quot;Migration failed: &quot; &amp; result);\n} else if (FindNoCase(&quot;already been applied&quot;, result)) {\n    writeOutput(&quot;Skipped: migration was already applied.&quot;);\n} else {\n    writeOutput(&quot;Migration applied successfully.&quot;);\n}\n\n// 3. Apply an individual colleague's migration without advancing the version pointer\n// This is useful when a team member's migration has a lower timestamp than\n// the current version but was not yet applied in your environment.\ncolVersion = &quot;20231205083000&quot;;\nresult = application.wheels.migrator.migrateIndividual(colVersion);\nwriteOutput(result);\n</code></pre>","hasExtended":true},"hint":"Runs a single specific migration's up() regardless of sequence order.\nUsed for out-of-sequence migrations that were created by other developers\nand need to be applied individually without affecting the current version pointer.\n\n","parameters":[{"type":"string","hint":"The version number of the specific migration to run","required":true,"name":"version"}],"name":"migrateIndividual","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"string","slug":"migrator.migrateTo","availableIn":["migrator"],"extended":{"docs":"<pre><code class='javascript'>// 1. Migrate up to a specific version\nresult = application.wheels.migrator.migrateTo(&quot;20240315120000&quot;);\n// result -&gt; &quot;Migrating from 20231201000000 up to 20240315120000.\n// -------- 20240315120000_add_status_to_orders --------------------\n// &quot;\n\n// 2. Migrate down to an earlier version (rolls back newer migrations)\nresult = application.wheels.migrator.migrateTo(&quot;20230601000000&quot;);\n// result -&gt; &quot;Migrating from 20240315120000 down to 20230601000000.\n// ------- 20240315120000_add_status_to_orders ---------------------\n// &quot;\n\n// 3. Migrate to version 0 (rolls back all migrations)\nresult = application.wheels.migrator.migrateTo(&quot;0&quot;);\n// result -&gt; &quot;Migrating from 20240315120000 down to 0.\n// ...&quot;\n\n// 4. Check the result string for errors before proceeding\nresult = application.wheels.migrator.migrateTo(&quot;20240315120000&quot;);\nif (FindNoCase(&quot;Error&quot;, result)) {\n    writeOutput(&quot;Migration failed: &quot; &amp; result);\n} else {\n    writeOutput(&quot;Migration result: &quot; &amp; result);\n}\n\n// 5. Apply a missing (out-of-order gap) migration using missingMigFlag\n// Use this when a migration with a timestamp earlier than the current version\n// was never applied in your environment.\nresult = application.wheels.migrator.migrateTo(\n    version = &quot;20231205083000&quot;,\n    missingMigFlag = true\n);\nwriteOutput(result);\n</code></pre>","hasExtended":true},"hint":"Migrates database to a specified version. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n","parameters":[{"type":"string","hint":"The Database schema version to migrate to","required":false,"name":"version","default":""},{"type":"boolean","hint":"Flag for any available missing migrations","required":false,"name":"missingMigFlag","default":false}],"name":"migrateTo","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"string","slug":"migrator.migrateToLatest","availableIn":["migrator"],"extended":{"docs":"<pre><code class='javascript'>// 1. Run all pending migrations to bring the database up to the latest version\nresult = application.wheels.migrator.migrateToLatest();\n// result -&gt; &quot;Migrating from 20240101000000 up to 20240315120000.\n// -------- 20240315120000_add_status_to_orders --------------------\n// &quot;\n\n// 2. Already at the latest version — no migration required\nresult = application.wheels.migrator.migrateToLatest();\n// result -&gt; &quot;Database is currently at version 20240315120000. No migration required.&quot;\n\n// 3. Check for errors after migrating to latest\nresult = application.wheels.migrator.migrateToLatest();\nif (FindNoCase(&quot;Error&quot;, result)) {\n    writeOutput(&quot;Migration failed: &quot; &amp; result);\n} else {\n    writeOutput(&quot;All migrations applied successfully.&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Shortcut function to migrate to the latest version\n\n","parameters":[],"name":"migrateToLatest","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"string","slug":"controller.mimeTypes","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the MIME type for a known file extension\nmimeType = mimeTypes(&quot;xls&quot;);\n// mimeType -&gt; &quot;application/vnd.ms-excel&quot;\n\n// 2. Get the MIME type for a dynamic extension from user input, with a custom fallback\nmimeType = mimeTypes(extension=params.fileType, fallback=&quot;text/plain&quot;);\n\n// 3. Use the default fallback (application/octet-stream) for an unknown extension\nmimeType = mimeTypes(&quot;xyz&quot;);\n// mimeType -&gt; &quot;application/octet-stream&quot;\n</code></pre>","hasExtended":true},"hint":"Returns an associated MIME type based on a file extension.\n\n","parameters":[{"type":"string","hint":"The extension to get the MIME type for.","required":true,"name":"extension"},{"type":"string","hint":"The fallback MIME type to return.","required":false,"name":"fallback","default":"application/octet-stream"}],"name":"mimeTypes","tags":{"category":"Miscellaneous Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"model.minimum","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the amount of the lowest salary for all employees\nlowestSalary = model(&quot;employee&quot;).minimum(&quot;salary&quot;);\n\n// 2. Get the amount of the lowest salary for employees in a given department\nlowestSalary = model(&quot;employee&quot;).minimum(property=&quot;salary&quot;, where=&quot;departmentId=#params.key#&quot;);\n\n// 3. Make sure a numeric amount is always returned, even when there were no records analyzed by the query\nlowestSalary = model(&quot;employee&quot;).minimum(property=&quot;salary&quot;, where=&quot;salary BETWEEN #params.min# AND #params.max#&quot;, ifNull=0);\n</code></pre>","hasExtended":true},"hint":"Calculates the minimum value for a given property.\nUses the SQL function <code>MIN</code>.\nIf no records can be found to perform the calculation on you can use the <code>ifNull</code> argument to decide what should be returned.\n\n","parameters":[{"type":"string","hint":"Name of the property to get the lowest value for (must be a property of a numeric data type).","required":true,"name":"property"},{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"any","hint":"The value returned if no records are found. Common usage is to set this to `0` to make sure a numeric value is always returned instead of a blank string.","required":false,"name":"ifNull","default":""},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"},{"type":"string","hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"group"}],"name":"minimum","tags":{"category":"Statistics Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"statisticsfunctions"}},{"returntype":"string","slug":"controller.minuteSelectTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage — the &quot;Tag&quot; version accepts a `name` and `selected` instead of binding to a model object\n&lt;cfoutput&gt;\n    #minuteSelectTag(name=&quot;minuteOfMeeting&quot;, selected=params.minuteOfMeeting)#\n&lt;/cfoutput&gt;\n\n// 2. Only show 15-minute intervals\n&lt;cfoutput&gt;\n    #minuteSelectTag(name=&quot;minuteOfMeeting&quot;, selected=params.minuteOfMeeting, minuteStep=15)#\n&lt;/cfoutput&gt;\n\n// 3. Include a blank option and add a label\n&lt;cfoutput&gt;\n    #minuteSelectTag(name=&quot;minuteOfMeeting&quot;, selected=params.minuteOfMeeting, includeBlank=true, label=&quot;Minute&quot;)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing one <code>select</code> form control for the minutes of an hour based on the supplied name.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"The minute that should be selected initially.","required":false,"name":"selected","default":""},{"type":"numeric","hint":"Pass in 10 to only show minute 10, 20, 30, etc.","required":false,"name":"minuteStep","default":1},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"date","required":false,"name":"$now","default":"[runtime expression]"}],"name":"minuteSelectTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"any","slug":"controller.model","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get a reference to the User model and call a class-level finder on it\nuser = model(&quot;User&quot;).findByKey(params.key);\n\n// 2. Find all active users by calling findAll() on the model reference\nactiveUsers = model(&quot;User&quot;).findAll(where=&quot;active = 1&quot;, order=&quot;lastName&quot;);\n\n// 3. Create a new record via the model reference\nnewPost = model(&quot;Post&quot;).new(title=params.title, body=params.body);\nnewPost.save();\n\n// 4. Count records using the model reference\ntotalOrders = model(&quot;Order&quot;).count(where=&quot;status = 'pending'&quot;);\n</code></pre>","hasExtended":true},"hint":"Returns a reference to the requested model so that class level methods can be called on it.\n\n","parameters":[{"type":"string","hint":"Name of the model to get a reference to.","required":true,"name":"name"}],"name":"model","tags":{"category":"Miscellaneous Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.monthSelectTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage: render a month select tag bound to a form param\n&lt;cfoutput&gt;\n    #monthSelectTag(name=&quot;monthOfBirthday&quot;, selected=params.monthOfBirthday)#\n&lt;/cfoutput&gt;\n\n// 2. Display month abbreviations instead of full names and include a blank prompt\n&lt;cfoutput&gt;\n    #monthSelectTag(\n        name=&quot;month&quot;,\n        selected=params.month,\n        monthDisplay=&quot;abbreviations&quot;,\n        includeBlank=&quot;- Select Month -&quot;\n    )#\n&lt;/cfoutput&gt;\n\n// 3. Display month numbers with a label wrapped around the control\n&lt;cfoutput&gt;\n    #monthSelectTag(\n        name=&quot;expirationMonth&quot;,\n        selected=params.expirationMonth,\n        monthDisplay=&quot;numbers&quot;,\n        label=&quot;Expiration Month&quot;\n    )#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a <code>select</code> form control for the months of the year based on the supplied name.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"The month that should be selected initially.","required":false,"name":"selected","default":""},{"type":"string","hint":"Pass in names, numbers, or abbreviations to control display.","required":false,"name":"monthDisplay","default":"names"},{"type":"string","hint":"[see:dateSelect].","required":false,"name":"monthNames","default":"January,February,March,April,May,June,July,August,September,October,November,December"},{"type":"string","hint":"[see:dateSelect].","required":false,"name":"monthAbbreviations","default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"date","required":false,"name":"$now","default":"[runtime expression]"}],"name":"monthSelectTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"struct","slug":"mapper.namespace","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    .namespace(&quot;api&quot;)\n        .namespace(&quot;v2&quot;)\n            // Route name:  apiV2Products\n            // Example URL: /api/v2/products/1234\n            // Controller:  api.v2.Products\n            .resources(&quot;products&quot;)\n        .end()\n\n        .namespace(&quot;v1&quot;)\n            // Route name:  apiV1Users\n            // Example URL: /api/v1/users\n            // Controller:  api.v1.Users\n            .get(name=&quot;users&quot;, to=&quot;users##index&quot;)\n        .end()\n    .end()\n\n    // Custom package and path: name=&quot;foo&quot;, package=&quot;foos&quot;, path=&quot;foose&quot;\n    // The `path` argument overrides the default URL prefix (which would be &quot;foo&quot;).\n    // The `package` argument overrides the default controller subfolder (which would be &quot;foo&quot;).\n    .namespace(name=&quot;foo&quot;, package=&quot;foos&quot;, path=&quot;foose&quot;)\n        // Route name:  fooBars\n        // Example URL: /foose/bars\n        // Controller:  foos.Bars\n        .post(name=&quot;bars&quot;, to=&quot;bars##create&quot;)\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Scopes any the controllers for any routes configured within this block to a subfolder (package) and also adds the package name to the URL.\n\n","parameters":[{"type":"string","hint":"Name to prepend to child route names.","required":true,"name":"name"},{"type":"string","hint":"Subfolder (package) to reference for controllers. This defaults to the value provided for `name`.","required":false,"name":"package","default":"[runtime expression]"},{"type":"string","hint":"Subfolder path to add to the URL.","required":false,"name":"path","default":"[runtime expression]"}],"name":"namespace","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"void","slug":"model.nestedProperties","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. In `models/User.cfc`, allow `groupEntitlements` to be saved and deleted through the `user` object.\nfunction config() {\n\thasMany(&quot;groupEntitlements&quot;);\n\tnestedProperties(association=&quot;groupEntitlements&quot;, allowDelete=true);\n}\n\n// 2. Allow nested `addresses` to be saved but not auto-saved with the parent; also reject blank `street` values.\nfunction config() {\n\thasMany(&quot;addresses&quot;);\n\tnestedProperties(association=&quot;addresses&quot;, autoSave=false, rejectIfBlank=&quot;street&quot;);\n}\n\n// 3. Allow nested `lineItems` with a sort order driven by the `position` property, and enable deletion.\nfunction config() {\n\thasMany(&quot;lineItems&quot;);\n\tnestedProperties(association=&quot;lineItems&quot;, allowDelete=true, sortProperty=&quot;position&quot;);\n}\n\n// 4. Enable nested properties for multiple associations at once.\nfunction config() {\n\thasOne(&quot;profile&quot;);\n\thasMany(&quot;phoneNumbers&quot;);\n\tnestedProperties(associations=&quot;profile,phoneNumbers&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Allows for nested objects, structs, and arrays to be set from params and other generated data.\n\n","parameters":[{"type":"string","hint":"The association (or list of associations) you want to allow to be set through the params. This argument is also aliased as `associations`.","required":false,"name":"association","default":""},{"type":"boolean","hint":"Whether to save the association(s) when the parent object is saved.","required":false,"name":"autoSave","default":true},{"type":"boolean","hint":"Set this to `true` to tell Wheels to look for the property `_delete` in your model. If present and set to a value that evaluates to true, the model will be deleted when saving the parent.","required":false,"name":"allowDelete","default":false},{"type":"string","hint":"Set this to a property on the object that you would like to sort by. The property should be numeric, should start with 1, and should be consecutive. Only valid with `hasMany` associations.","required":false,"name":"sortProperty","default":""},{"type":"string","hint":"A list of properties that should not be blank. If any of the properties are blank, any CRUD operations will be rejected.","required":false,"name":"rejectIfBlank","default":""}],"name":"nestedProperties","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"model.new","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Create a new author in memory (not saved to the database)\nnewAuthor = model(&quot;author&quot;).new();\n\n// 2. Create a new author by passing in a struct of properties\nnewAuthor = model(&quot;author&quot;).new(params.authorStruct);\n\n// 3. Create a new author by passing in named arguments\nnewAuthor = model(&quot;author&quot;).new(firstName=&quot;John&quot;, lastName=&quot;Doe&quot;);\n\n// 4. Create a new object without running callbacks\nnewAuthor = model(&quot;author&quot;).new(firstName=&quot;Jane&quot;, callbacks=false);\n\n// 5. Create a new object and allow explicit assignment of timestamp properties\nnewAuthor = model(&quot;author&quot;).new(firstName=&quot;Bob&quot;, createdAt=&quot;2024-01-01&quot;, allowExplicitTimestamps=true);\n\n// 6. Scoped call via a `hasMany` association (calls `model(&quot;order&quot;).new(customerId=aCustomer.id)` internally)\naCustomer = model(&quot;customer&quot;).findByKey(params.customerId);\nanOrder = aCustomer.newOrder(shipping=params.shipping);\n</code></pre>","hasExtended":true},"hint":"Creates a new object based on supplied <code>properties</code> and returns it.\nThe object is not saved to the database, it only exists in memory.\nProperty names and values can be passed in either using named arguments or as a struct to the <code>properties</code> argument.\n\n","parameters":[{"type":"struct","hint":"The properties you want to set on the object (can also be passed in as named arguments).","required":false,"name":"properties","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":true},{"type":"boolean","hint":"Set this to `true` to allow explicit assignment of `createdAt` or `updatedAt` properties","required":false,"name":"allowExplicitTimestamps","default":false}],"name":"new","tags":{"category":"Create Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"createfunctions"}},{"returntype":"string","slug":"controller.nextPageLink","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>//--------------------------------------------------------------------\n// Example 1: Basic usage — show a &quot;Next&quot; link below a paginated list;\n// renders a disabled span when already on the last page\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts = model(&quot;Post&quot;).findAll(page=params.page, perPage=10, order=&quot;createdAt DESC&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #firstPageLink()#\n    #previousPageLink()#\n    #pageNumberLinks()#\n    #nextPageLink()#\n    #lastPageLink()#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom link text and CSS classes\n\n// View code\n&lt;cfoutput&gt;\n    #nextPageLink(\n        text=&quot;Next &amp;raquo;&quot;,\n        class=&quot;page-link&quot;,\n        disabledClass=&quot;page-link disabled&quot;\n    )#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 3: Hide the disabled element entirely when on the last page\n\n// View code\n&lt;cfoutput&gt;\n    #nextPageLink(showDisabled=false)#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 4: Use a named route so page numbers appear in the URL path\n// instead of as a query-string param (e.g. /articles/page/3)\n\n// Route setup in app/config/routes.cfm\nmapper()\n    .get(name=&quot;paginatedArticles&quot;, pattern=&quot;articles/page/[page]&quot;, to=&quot;articles##index&quot;)\n    .get(name=&quot;articles&quot;, pattern=&quot;articles&quot;, to=&quot;articles##index&quot;)\n.end();\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\narticles = model(&quot;Article&quot;).findAll(page=params.page, perPage=20, order=&quot;title&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #nextPageLink(route=&quot;paginatedArticles&quot;, pageNumberAsParam=false)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Creates a link to the next page, or a disabled span when on the last page.\n\n","parameters":[{"type":"string","hint":"The text for the link.","required":false,"name":"text","default":"Next"},{"type":"string","hint":"The handle given to the query that the pagination should be displayed for.","required":false,"name":"handle","default":"query"},{"type":"string","hint":"The name of the param that holds the current page number.","required":false,"name":"name","default":"page"},{"type":"string","hint":"CSS class for the link element.","required":false,"name":"class","default":""},{"type":"string","hint":"CSS class for the disabled span element.","required":false,"name":"disabledClass","default":"disabled"},{"type":"boolean","hint":"Whether to render a disabled span when on the last page.","required":false,"name":"showDisabled","default":true},{"type":"boolean","hint":"Decides whether to link the page number as a param or as part of a route.","required":false,"name":"pageNumberAsParam","default":true},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"nextPageLink","tags":{"category":"Pagination Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"paginationfunctions"}},{"returntype":"string","slug":"controller.numberField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic number field bound to a model object\n#numberField(objectName=&quot;product&quot;, property=&quot;price&quot;)#\n\n// 2. Number field with a label and min/max/step constraints\n#numberField(label=&quot;Quantity&quot;, objectName=&quot;orderItem&quot;, property=&quot;quantity&quot;, min=&quot;1&quot;, max=&quot;100&quot;, step=&quot;1&quot;)#\n\n// 3. Number field for a nested association (line items in an order)\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(order.lineItems)#&quot; index=&quot;i&quot;&gt;\n\t#numberField(label=&quot;Amount ##i#&quot;, objectName=&quot;order&quot;, association=&quot;lineItems&quot;, position=i, property=&quot;amount&quot;, min=&quot;0&quot;)#\n&lt;/cfloop&gt;</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a number field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"Minimum allowed value.","required":false,"name":"min"},{"type":"string","hint":"Maximum allowed value.","required":false,"name":"max"},{"type":"string","hint":"Stepping interval.","required":false,"name":"step"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"numberField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.numberFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic number field with a name and current value\n#numberFieldTag(name=&quot;quantity&quot;, value=params.quantity)#\n\n// 2. Number field with min, max, and step constraints plus a label\n#numberFieldTag(name=&quot;rating&quot;, value=params.rating, label=&quot;Rating&quot;, min=&quot;1&quot;, max=&quot;5&quot;, step=&quot;1&quot;)#\n\n// 3. Number field with a CSS class and prepended label text\n#numberFieldTag(name=&quot;price&quot;, value=params.price, label=&quot;Price ($)&quot;, min=&quot;0&quot;, step=&quot;0.01&quot;, class=&quot;price-input&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a number field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"Minimum allowed value.","required":false,"name":"min"},{"type":"string","hint":"Maximum allowed value.","required":false,"name":"max"},{"type":"string","hint":"Stepping interval.","required":false,"name":"step"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"numberFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.obfuscateParam","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Obfuscate a primary key value before including it in a URL\nobfuscatedId = obfuscateParam(99);\n// obfuscatedId -&gt; &quot;a3f6c1&quot; (an obfuscated hex string)\n\n// 2. Use an obfuscated key in a generated URL to hide the real record ID\nparams.userKey = obfuscateParam(model(&quot;User&quot;).findOne().key());\nredirectTo(route=&quot;userProfile&quot;, key=params.userKey);\n\n// 3. Reverse the obfuscation with deobfuscateParam to get the original value back\nobfuscated = obfuscateParam(42);\noriginal = deobfuscateParam(obfuscated);\n// original -&gt; &quot;42&quot;\n</code></pre>","hasExtended":true},"hint":"Obfuscates a value. Typically used for hiding primary key values when passed along in the URL.\n\n","parameters":[{"type":"any","hint":"The value to obfuscate.","required":true,"name":"param"}],"name":"obfuscateParam","tags":{"category":"Miscellaneous Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.offerPrice","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Prix d'une offre, recompose depuis ses trois colonnes.","parameters":[{"type":"any","required":false,"name":"price","default":"[runtime expression]"}],"name":"offerPrice","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"void","slug":"controller.onlyProvides","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Override a global `provides()` setting for a single action — only respond with HTML\nonlyProvides(&quot;html&quot;);\n\n// 2. Allow a specific action to respond with JSON and XML only\nonlyProvides(&quot;json,xml&quot;);\n\n// 3. Override the provides formats for a named action from within another context (e.g. config())\nonlyProvides(formats=&quot;json&quot;, action=&quot;create&quot;);\n</code></pre>","hasExtended":true},"hint":"Use this in an individual controller action to define which formats the action will respond with.\nThis can be used to define provides behavior in individual actions or to override a global setting set with <code>provides</code> in the controller's <code>config()</code>.\nRestrictions are enforced (since 4.0.4): <code>renderWith()</code> falls back to the <code>html</code> view for a\nformat outside the list, and the automatic render in <code>$callAction()</code> skips view rendering for\nnon-acceptable, non-html formats.\n\n","parameters":[{"type":"string","hint":"Formats to instruct the controller to provide. Valid values are `html` (the default), `xml`, `json`, `csv`, `pdf`, and `xls`.","required":false,"name":"formats","default":""},{"type":"string","hint":"Name of action, defaults to current.","required":false,"name":"action","default":"[runtime expression]"}],"name":"onlyProvides","tags":{"category":"Provides Functions","sectionClass":"controller","section":"Controller","categoryClass":"providesfunctions"}},{"returntype":"any","slug":"model.onMissingMethod","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// Note: onMissingMethod() is not called directly. It is the CFML hook that\n// powers Wheels' dynamic model methods. The examples below show what you\n// call in your code — Wheels intercepts each one automatically.\n\n// 1. Dynamic finder: findOneBy&lt;Property&gt;\n// Finds the first user whose email matches the given value.\nuser = model(&quot;User&quot;).findOneByEmail(&quot;jane@example.com&quot;);\n\n// 2. Dynamic finder: findAllBy&lt;Property&gt;\n// Finds all posts with the given status.\nposts = model(&quot;Post&quot;).findAllByStatus(&quot;published&quot;);\n\n// 3. Dynamic finder across multiple properties joined by &quot;And&quot;\n// Finds a single order matching both customerId and status.\norder = model(&quot;Order&quot;).findOneByCustomerIdAndStatus(42, &quot;pending&quot;);\n\n// 4. Find or create by property\n// Returns an existing tag with the name &quot;cfml&quot;, or creates one if none exists.\ntag = model(&quot;Tag&quot;).findOrCreateByName(&quot;cfml&quot;);\n\n// 5. Association helpers generated for hasMany (comments on a post)\npost = model(&quot;Post&quot;).findByKey(1);\n// Retrieve all associated comments\ncomments = post.comments();\n// Count associated comments\ntotal = post.commentCount();\n// Create a new associated comment (foreign key set automatically)\npost.createComment(body=&quot;Great post!&quot;);\n\n// 6. Property change helpers\nuser = model(&quot;User&quot;).findByKey(1);\nuser.email = &quot;new@example.com&quot;;\n// Check whether a specific property has changed since the record was loaded\nchanged = user.emailHasChanged();\n// Get the original value before the change\noriginal = user.emailChangedFrom();\n\n// 7. Enum boolean helpers (requires enum() declaration in model config)\n// component Post extends=&quot;Model&quot; { function config() { enum(property=&quot;status&quot;, values=&quot;draft,published,archived&quot;); } }\npost = model(&quot;Post&quot;).findByKey(1);\nwriteOutput(post.isPublished()); // true or false\nwriteOutput(post.isDraft());     // true or false\n</code></pre>","hasExtended":true},"hint":"This method is not designed to be called directly from your code, but provides functionality for dynamic finders such as <code>findOneByEmail()</code>\n\n","parameters":[{"type":"string","required":true,"name":"missingMethodName"},{"type":"struct","required":true,"name":"missingMethodArguments"}],"name":"onMissingMethod","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"struct","slug":"mapper.package","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\n// 1. Scope controllers into a subfolder without adding the package name to the URL\nmapper()\n    .package(&quot;admin&quot;)\n        // Route name:  adminProducts\n        // Example URL: /products (no &quot;admin&quot; in the URL)\n        // Controller:  admin.Products\n        .resources(&quot;products&quot;)\n\n        // Example URL: /users (no &quot;admin&quot; in the URL)\n        // Controller:  admin.Users\n        .resources(&quot;users&quot;)\n    .end()\n.end();\n\n// 2. Use the `package` argument to override the subfolder name\nmapper()\n    .package(name=&quot;v2&quot;, package=&quot;api/v2&quot;)\n        // Route name:  v2Articles\n        // Example URL: /articles\n        // Controller:  api/v2.Articles\n        .resources(&quot;articles&quot;)\n    .end()\n.end();\n\n// 3. Nest a `package` inside a resource to scope sub-resource controllers\nmapper()\n    .resources(name=&quot;users&quot;, nested=true)\n        // Calling `package` here scopes nested routes to a subfolder without\n        // changing the URL structure.\n        .package(&quot;users&quot;)\n            // Route name:  usersProfile\n            // Example URL: /users/4321/profile\n            // Controller:  users.Profiles\n            .resource(&quot;profile&quot;)\n        .end()\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Scopes any the controllers for any routes configured within this block to a subfolder (package) without adding the package name to the URL.\n\n","parameters":[{"type":"string","hint":"Name to prepend to child route names.","required":true,"name":"name"},{"type":"string","hint":"Subfolder (package) to reference for controllers. This defaults to the value provided for `name`.","required":false,"name":"package","default":"[runtime expression]"}],"name":"package","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.pageDescription","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"","parameters":[],"name":"pageDescription","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"string","slug":"controller.pageNumberLinks","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>//--------------------------------------------------------------------\n// Example 1: Basic page number links for a paginated query\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts = model(&quot;Post&quot;).findAll(page=params.page, perPage=10, order=&quot;createdAt DESC&quot;);\n\n// View code — renders links like: 1 2 [3] 4 5  (current page as a span)\n&lt;cfoutput&gt;#pageNumberLinks()#&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 2: Widen the window around the current page and add CSS classes\n\n// View code — shows 5 pages on each side of the current page,\n// styling each link and the current-page span differently\n&lt;cfoutput&gt;\n    #pageNumberLinks(windowSize=5, class=&quot;page-link&quot;, classForCurrent=&quot;active&quot;)#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 3: Wrap each page number in a list item\n\n// View code\n&lt;ul&gt;\n    &lt;cfoutput&gt;\n        #pageNumberLinks(prependToPage=&quot;&lt;li&gt;&quot;, appendToPage=&quot;&lt;/li&gt;&quot;)#\n    &lt;/cfoutput&gt;\n&lt;/ul&gt;\n\n\n//--------------------------------------------------------------------\n// Example 4: Make the current page a link (useful for reloading)\n\n// View code\n&lt;cfoutput&gt;#pageNumberLinks(linkToCurrentPage=true)#&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 5: Multiple paginated queries — reference each by its handle\n\n// Controller code\nauthors = model(&quot;Author&quot;).findAll(handle=&quot;authorQuery&quot;, page=params.page, perPage=20, order=&quot;lastName&quot;);\nposts   = model(&quot;Post&quot;).findAll(handle=&quot;postQuery&quot;,   page=params.page, perPage=5,  order=&quot;createdAt&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    Authors: #pageNumberLinks(handle=&quot;authorQuery&quot;)#\n    Posts:   #pageNumberLinks(handle=&quot;postQuery&quot;)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Creates a windowed set of page number links around the current page.\nThe current page is rendered as a span (not a link) unless <code>linkToCurrentPage</code> is true.\n\n\nWhen non-plain, emits the canonical wrapper markup for that framework (e.g. <code><li class=\"page-item active\"></code>)\nand ignores <code>prependToPage</code> / <code>appendToPage</code> / <code>classForCurrent</code> / <code>class</code> in favor of the preset.","parameters":[{"type":"numeric","hint":"The number of page links to show around the current page.","required":false,"name":"windowSize","default":2},{"type":"string","hint":"The handle given to the query that the pagination should be displayed for.","required":false,"name":"handle","default":"query"},{"type":"string","hint":"The name of the param that holds the current page number.","required":false,"name":"name","default":"page"},{"type":"string","hint":"CSS class for each page number link.","required":false,"name":"class","default":""},{"type":"string","hint":"CSS class for the current page span or link.","required":false,"name":"classForCurrent","default":"current"},{"type":"boolean","hint":"Whether to render the current page as a link.","required":false,"name":"linkToCurrentPage","default":false},{"type":"string","hint":"String to prepend before each page number.","required":false,"name":"prependToPage","default":""},{"type":"string","hint":"String to append after each page number.","required":false,"name":"appendToPage","default":""},{"type":"boolean","hint":"Whether to inject `active ` into the prependToPage `class` attribute on the current page (Bootstrap idiom). Has no effect if `prependToPage` contains no `class` attribute.","required":false,"name":"addActiveClassToPrependedParent","default":false},{"type":"boolean","hint":"Decides whether to link the page number as a param or as part of a route.","required":false,"name":"pageNumberAsParam","default":true},{"type":"string","hint":"CSS-framework preset for markup: \"plain\" (default), \"bootstrap5\", \"bootstrap4\", or \"tailwind\".","required":false,"name":"viewStyle","default":"plain"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"pageNumberLinks","tags":{"category":"Pagination Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"paginationfunctions"}},{"returntype":"string","slug":"controller.pageTitle","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Titre de la page, defini par le controleur via request.pageTitle.\nLe suffixe est ajoute ici et non dans chaque vue : un titre est un element\nde referencement, et l'oublier sur une page passe inapercu en relecture.","parameters":[],"name":"pageTitle","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"struct","slug":"controller.pagination","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get pagination info for the default query handle\nauthors = model(&quot;Author&quot;).findAll(page=1, perPage=25, order=&quot;lastName&quot;);\ninfo = pagination();\n// info.currentPage  -&gt; 1\n// info.totalPages   -&gt; 4\n// info.totalRecords -&gt; 98\n\n// 2. Get pagination info using a named handle (when running multiple paginated queries)\narticles = model(&quot;Article&quot;).findAll(page=2, perPage=10, order=&quot;publishedAt DESC&quot;, handle=&quot;articles&quot;);\narticleInfo = pagination(&quot;articles&quot;);\nwriteOutput(&quot;Page &quot; &amp; articleInfo.currentPage &amp; &quot; of &quot; &amp; articleInfo.totalPages);\n\n// 3. Use pagination info to build a simple summary string\nproducts = model(&quot;Product&quot;).findAll(page=params.page, perPage=20, order=&quot;name&quot;, handle=&quot;products&quot;);\ninfo = pagination(&quot;products&quot;);\nwriteOutput(&quot;Showing page &quot; &amp; info.currentPage &amp; &quot; of &quot; &amp; info.totalPages &amp; &quot; (&quot; &amp; info.totalRecords &amp; &quot; total products)&quot;);\n</code></pre>","hasExtended":true},"hint":"Returns a struct with information about the specified paginated query.\nThe keys that will be included in the struct are <code>currentPage</code>, <code>totalPages</code> and <code>totalRecords</code>.\n\n","parameters":[{"type":"string","hint":"The handle given to the query to return pagination information for.","required":false,"name":"handle","default":"query"}],"name":"pagination","tags":{"category":"Pagination Functions","sectionClass":"controller","section":"Controller","categoryClass":"paginationfunctions"}},{"returntype":"string","slug":"controller.paginationInfo","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>//--------------------------------------------------------------------\n// Example 1: Basic usage — display the default summary text for a\n// paginated query (e.g. &quot;Showing 26-50 of 1,000 records&quot;)\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts = model(&quot;Post&quot;).findAll(page=params.page, perPage=25, order=&quot;createdAt DESC&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #paginationInfo()#\n&lt;/cfoutput&gt;\n// -&gt; &quot;Showing 26-50 of 1,000 records&quot;\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom format string using available tokens\n// Tokens: [startRow], [endRow], [totalRecords], [currentPage], [totalPages]\n\n// View code\n&lt;cfoutput&gt;\n    #paginationInfo(format=&quot;Page [currentPage] of [totalPages] ([totalRecords] total)&quot;)#\n&lt;/cfoutput&gt;\n// -&gt; &quot;Page 2 of 40 (1,000 total)&quot;\n\n\n//--------------------------------------------------------------------\n// Example 3: Multiple paginated queries on the same page using handles\n\n// Controller code\nparam name=&quot;params.postPage&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nparam name=&quot;params.commentPage&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts    = model(&quot;Post&quot;).findAll(handle=&quot;posts&quot;, page=params.postPage, perPage=10, order=&quot;createdAt DESC&quot;);\ncomments = model(&quot;Comment&quot;).findAll(handle=&quot;comments&quot;, page=params.commentPage, perPage=5, order=&quot;createdAt DESC&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    Posts: #paginationInfo(handle=&quot;posts&quot;)#\n    Comments: #paginationInfo(handle=&quot;comments&quot;)#\n&lt;/cfoutput&gt;\n// -&gt; &quot;Posts: Showing 1-10 of 87 records&quot;\n// -&gt; &quot;Comments: Showing 1-5 of 342 records&quot;\n</code></pre>","hasExtended":true},"hint":"Displays a text summary of the current pagination state, e.g. \"Showing 26-50 of 1,000 records\".\nUses token replacement in the format string: \n","parameters":[{"type":"string","hint":"The handle given to the query that the pagination info should be displayed for.","required":false,"name":"handle","default":"query"},{"type":"string","hint":"Format string with tokens: [startRow], [endRow], [totalRecords], [currentPage], [totalPages].","required":false,"name":"format","default":"Showing [startRow]-[endRow] of [totalRecords] records"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"paginationInfo","tags":{"category":"Pagination Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"paginationfunctions"}},{"returntype":"string","slug":"controller.paginationLinks","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>//--------------------------------------------------------------------\n// Example 1: List authors page by page, 25 at a time\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nauthors = model(&quot;author&quot;).findAll(page=params.page, perPage=25, order=&quot;lastName&quot;);\n\n// View code\n&lt;ul&gt;\n    &lt;cfoutput query=&quot;authors&quot;&gt;\n        &lt;li&gt;#EncodeForHtml(firstName)# #EncodeForHtml(lastName)#&lt;/li&gt;\n    &lt;/cfoutput&gt;\n&lt;/ul&gt;\n\n&lt;cfoutput&gt;#paginationLinks(route=&quot;authors&quot;)#&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 2: Using the same model call above, show all authors with a\n// window size of 5\n\n// View code\n&lt;cfoutput&gt;#paginationLinks(route=&quot;authors&quot;, windowSize=5)#&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 3: If more than one paginated query is being run, then you\n// need to reference the correct `handle` in the view\n\n// Controller code\nauthors = model(&quot;author&quot;).findAll(handle=&quot;authQuery&quot;, page=5, order=&quot;id&quot;);\n\n// View code\n&lt;ul&gt;\n    &lt;cfoutput&gt;\n        #paginationLinks(\n            route=&quot;authors&quot;,\n            handle=&quot;authQuery&quot;,\n            prependToPage=&quot;&lt;li&gt;&quot;,\n            appendToPage=&quot;&lt;/li&gt;&quot;\n        )#\n    &lt;/cfoutput&gt;\n&lt;/ul&gt;\n\n\n//--------------------------------------------------------------------\n// Example 4: Call to `paginationLinks` using routes\n\n// Route setup in app/config/routes.cfm\nmapper()\n    .get(name=&quot;paginatedCommentListing&quot;, pattern=&quot;blog/[year]/[month]/[day]/[page]&quot;, to=&quot;blogs##stats&quot;)\n    .get(name=&quot;commentListing&quot;, pattern=&quot;blog/[year]/[month]/[day]&quot;, to=&quot;blogs##stats&quot;)\n.end();\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\ncomments = model(&quot;comment&quot;).findAll(page=params.page, order=&quot;createdAt&quot;);\n\n// View code\n&lt;ul&gt;\n    &lt;cfoutput&gt;\n        #paginationLinks(\n            route=&quot;paginatedCommentListing&quot;,\n            year=2009,\n            month=&quot;feb&quot;,\n            day=10\n        )#\n    &lt;/cfoutput&gt;\n&lt;/ul&gt;\n\n\n//--------------------------------------------------------------------\n// Example 5: Highlight the current page with a CSS class and wrap\n// each page number in a Bootstrap-style list item, marking the active\n// item's parent with an &quot;active&quot; class\n\n// View code\n&lt;ul class=&quot;pagination&quot;&gt;\n    &lt;cfoutput&gt;\n        #paginationLinks(\n            route=&quot;articles&quot;,\n            prependToPage='&lt;li class=&quot;page-item&quot;&gt;',\n            appendToPage=&quot;&lt;/li&gt;&quot;,\n            classForCurrent=&quot;page-link active&quot;,\n            addActiveClassToPrependedParent=true,\n            linkToCurrentPage=true\n        )#\n    &lt;/cfoutput&gt;\n&lt;/ul&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing links to pages based on a paginated query.\nUses <code>linkTo()</code> internally to build the link, so you need to pass in a route name or a controller/action/key combination.\nAll other <code>linkTo()</code> arguments can be supplied as well, in which case they are passed through directly to <code>linkTo()</code>.\nIf you have paginated more than one query in the controller, you can use the handle argument to reference them. (Don't forget to pass in a handle to the <code>findAll()</code> function in your controller first.)\n\n","parameters":[{"type":"numeric","hint":"The number of page links to show around the current page.","required":false,"name":"windowSize","default":2},{"type":"boolean","hint":"Whether or not links to the first and last page should always be displayed.","required":false,"name":"alwaysShowAnchors","default":true},{"type":"string","hint":"String to place next to the anchors on either side of the list.","required":false,"name":"anchorDivider","default":" ... "},{"type":"boolean","hint":"Whether or not the current page should be linked to.","required":false,"name":"linkToCurrentPage","default":false},{"type":"string","hint":"String or HTML to be prepended before result.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String or HTML to be appended after result.","required":false,"name":"append","default":""},{"type":"string","hint":"String or HTML to be prepended before each page number.","required":false,"name":"prependToPage","default":""},{"type":"boolean","hint":"Whether or not to add an active class to the parent element of the current page link (requires prependToPage to contain a class attribute).","required":false,"name":"addActiveClassToPrependedParent","default":false},{"type":"boolean","hint":"Whether or not to prepend the prependToPage string on the first page in the list.","required":false,"name":"prependOnFirst","default":true},{"type":"boolean","hint":"Whether or not to prepend the prependToPage string on the anchors.","required":false,"name":"prependOnAnchor","default":true},{"type":"string","hint":"String or HTML to be appended after each page number.","required":false,"name":"appendToPage","default":""},{"type":"boolean","hint":"Whether or not to append the appendToPage string on the last page in the list.","required":false,"name":"appendOnLast","default":true},{"type":"boolean","hint":"Whether or not to append the appendToPage string on the anchors.","required":false,"name":"appendOnAnchor","default":true},{"type":"string","hint":"Class name for the current page number (if linkToCurrentPage is true, the class name will go on the a element. If not, a span element will be used).","required":false,"name":"classForCurrent","default":""},{"type":"string","hint":"The handle given to the query that the pagination links should be displayed for.","required":false,"name":"handle","default":"query"},{"type":"string","hint":"The name of the param that holds the current page number.","required":false,"name":"name","default":"page"},{"type":"boolean","hint":"Will show a single page when set to true. (The default behavior is to return an empty string when there is only one page in the pagination).","required":false,"name":"showSinglePage","default":false},{"type":"boolean","hint":"Decides whether to link the page number as a param or as part of a route. (The default behavior is true).","required":false,"name":"pageNumberAsParam","default":true},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"paginationLinks","tags":{"category":"Link Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"linkfunctions"}},{"returntype":"string","slug":"controller.paginationNav","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>//--------------------------------------------------------------------\n// Example 1: Basic usage — render a full pagination nav for a\n// paginated query (first, previous, page numbers, next, last links)\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts = model(&quot;Post&quot;).findAll(page=params.page, perPage=25, order=&quot;createdAt DESC&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #paginationNav()#\n&lt;/cfoutput&gt;\n// -&gt; &lt;nav class=&quot;pagination&quot;&gt;&lt;a href=&quot;/posts?page=1&quot;&gt;1&lt;/a&gt; &lt;a href=&quot;/posts?page=2&quot;&gt;2&lt;/a&gt; ...&lt;/nav&gt;\n\n\n//--------------------------------------------------------------------\n// Example 2: Show pagination info text alongside the nav links,\n// and use a custom CSS class on the wrapping nav element\n\n// View code\n&lt;cfoutput&gt;\n    #paginationNav(showInfo=true, navClass=&quot;pagination-bar&quot;)#\n&lt;/cfoutput&gt;\n// -&gt; &lt;nav class=&quot;pagination-bar&quot;&gt;Showing 1-25 of 87 records &lt;a href=&quot;...&quot;&gt;1&lt;/a&gt; ...&lt;/nav&gt;\n\n\n//--------------------------------------------------------------------\n// Example 3: Minimal nav — page numbers only (no first/last links)\n\n// View code\n&lt;cfoutput&gt;\n    #paginationNav(showFirst=false, showLast=false)#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 4: Multiple paginated queries on the same page using handles\n\n// Controller code\nparam name=&quot;params.postPage&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nparam name=&quot;params.commentPage&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts    = model(&quot;Post&quot;).findAll(handle=&quot;posts&quot;, page=params.postPage, perPage=10, order=&quot;createdAt DESC&quot;);\ncomments = model(&quot;Comment&quot;).findAll(handle=&quot;comments&quot;, page=params.commentPage, perPage=5, order=&quot;createdAt DESC&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #paginationNav(handle=&quot;posts&quot;)#\n    #paginationNav(handle=&quot;comments&quot;)#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 5: Show pagination even when there is only one page of results\n\n// View code\n&lt;cfoutput&gt;\n    #paginationNav(showSinglePage=true)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Creates a complete pagination navigation element wrapping individual pagination helpers.\nOutputs a <code><nav></code> element containing first/previous/page-numbers/next/last links and optional info text.\nThe <code>showFirst</code> / <code>showLast</code> / <code>showPrevious</code> / <code>showNext</code> args accept the\nstrings <code>\"auto\"</code>, <code>\"always\"</code>, or <code>\"never\"</code>. Booleans are normalized for\nbackwards compatibility: <code>true</code> maps to <code>\"always\"</code>, <code>false</code> maps to <code>\"never\"</code>.\nUnder <code>\"auto\"</code> the first/last anchors only render when the visible page-number\nwindow does not already reach the boundary (matching legacy 3.x semantics).\nUnder <code>\"auto\"</code> the previous/next anchors always delegate to their sub-helper,\nwhich renders a disabled <code><span class=\"disabled\"></code> at the boundary by default —\nuse <code>\"never\"</code> to suppress the boundary indicator entirely.\n\n\nWhen non-plain, the entire nav is rendered with the framework's canonical structure\n(e.g. <code><nav><ul class=\"pagination\"><li class=\"page-item active\">...</code>), removing the need\nfor <code>Replace()</code> post-processing in app code. Passed through to <code>pageNumberLinks()</code>.","parameters":[{"type":"string","hint":"The handle given to the query that the pagination should be displayed for.","required":false,"name":"handle","default":"query"},{"type":"string","hint":"CSS class for the wrapping nav element.","required":false,"name":"navClass","default":"pagination"},{"type":"any","hint":"Anchor display mode for the first page link: \"auto\" (default), \"always\", \"never\", or boolean.","required":false,"name":"showFirst","default":"auto"},{"type":"any","hint":"Anchor display mode for the last page link: \"auto\" (default), \"always\", \"never\", or boolean.","required":false,"name":"showLast","default":"auto"},{"type":"any","hint":"Anchor display mode for the previous page link: \"auto\" (default), \"always\", \"never\", or boolean.","required":false,"name":"showPrevious","default":"auto"},{"type":"any","hint":"Anchor display mode for the next page link: \"auto\" (default), \"always\", \"never\", or boolean.","required":false,"name":"showNext","default":"auto"},{"type":"boolean","hint":"Whether to show the pagination info text.","required":false,"name":"showInfo","default":false},{"type":"boolean","hint":"Whether to show pagination when there is only one page.","required":false,"name":"showSinglePage","default":false},{"type":"numeric","hint":"Number of page links shown around the current page in `pageNumberLinks` and used by the auto-mode predicates.","required":false,"name":"windowSize","default":2},{"type":"string","hint":"CSS-framework preset for markup: \"plain\" (default), \"bootstrap5\", \"bootstrap4\", or \"tailwind\".","required":false,"name":"viewStyle","default":"plain"},{"type":"string","hint":"String or HTML to be prepended inside the `<nav>` before the link list (e.g. `<ul class=\"pagination\">`).","required":false,"name":"prepend","default":""},{"type":"string","hint":"String or HTML to be appended inside the `<nav>` after the link list (e.g. `</ul>`).","required":false,"name":"append","default":""},{"type":"string","hint":"String or HTML to wrap before each anchor (first/previous/page numbers/next/last). Forwards to `pageNumberLinks` for the numbered links.","required":false,"name":"prependToPage","default":""},{"type":"string","hint":"String or HTML to wrap after each anchor (first/previous/page numbers/next/last). Forwards to `pageNumberLinks` for the numbered links.","required":false,"name":"appendToPage","default":""},{"type":"boolean","hint":"Whether to inject `active ` into the prependToPage `class` attribute on the current page (Bootstrap idiom — forwards to `pageNumberLinks`). Applies only to numbered-page anchors, not to first / previous / next / last (which are never \"current\" in the Bootstrap sense). Has no effect if `prependToPage` contains no `class` attribute.","required":false,"name":"addActiveClassToPrependedParent","default":false},{"type":"string","hint":"Separator inserted between the first/previous/page-numbers/next/last sections.","required":false,"name":"anchorDivider","default":" "},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"paginationNav","tags":{"category":"Pagination Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"paginationfunctions"}},{"returntype":"string","slug":"controller.passwordField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic password field bound to a `user` object\n&lt;cfoutput&gt;\n    #passwordField(objectName=&quot;user&quot;, property=&quot;password&quot;, label=&quot;Password&quot;)#\n&lt;/cfoutput&gt;\n// -&gt; &lt;label for=&quot;user-password&quot;&gt;Password&lt;input id=&quot;user-password&quot; type=&quot;password&quot; name=&quot;user[password]&quot; value=&quot;&quot;&gt;&lt;/label&gt;\n\n// 2. Password field with a confirmation property on the same object\n&lt;cfoutput&gt;\n    #passwordField(objectName=&quot;user&quot;, property=&quot;password&quot;, label=&quot;Password&quot;)#\n    #passwordField(objectName=&quot;user&quot;, property=&quot;passwordConfirmation&quot;, label=&quot;Confirm Password&quot;)#\n&lt;/cfoutput&gt;\n\n// 3. Password fields for nested `passwords` association (hasMany)\n&lt;fieldset&gt;\n    &lt;legend&gt;Passwords&lt;/legend&gt;\n    &lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(user.passwords)#&quot; index=&quot;i&quot;&gt;\n        #passwordField(objectName=&quot;user&quot;, association=&quot;passwords&quot;, position=i, property=&quot;password&quot;, label=&quot;Password ##i#&quot;)#\n    &lt;/cfloop&gt;\n&lt;/fieldset&gt;\n\n// 4. Wrap the field with custom HTML using `prepend` and `append`\n&lt;cfoutput&gt;\n    #passwordField(objectName=&quot;user&quot;, property=&quot;password&quot;, label=&quot;Password&quot;, prepend=&quot;&lt;div class=&quot;&quot;field&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a password field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"passwordField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.passwordFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic password field with just a name\n&lt;cfoutput&gt;\n    #passwordFieldTag(name=&quot;password&quot;)#\n&lt;/cfoutput&gt;\n// -&gt; &lt;input type=&quot;password&quot; name=&quot;password&quot; id=&quot;password&quot; value=&quot;&quot;&gt;\n\n// 2. With a label and a pre-filled value (e.g. re-displaying on validation error)\n&lt;cfoutput&gt;\n    #passwordFieldTag(name=&quot;password&quot;, label=&quot;Password&quot;, value=params.password)#\n&lt;/cfoutput&gt;\n// -&gt; &lt;label for=&quot;password&quot;&gt;Password&lt;input type=&quot;password&quot; name=&quot;password&quot; id=&quot;password&quot; value=&quot;&quot;&gt;&lt;/label&gt;\n\n// 3. Label placed before the field, with HTML wrappers using prepend/append\n&lt;cfoutput&gt;\n    #passwordFieldTag(name=&quot;password&quot;, label=&quot;Password&quot;, labelPlacement=&quot;before&quot;, prepend=&quot;&lt;div class=&quot;&quot;field&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n&lt;/cfoutput&gt;\n// -&gt; &lt;div class=&quot;field&quot;&gt;&lt;label for=&quot;password&quot;&gt;Password&lt;/label&gt;&lt;input type=&quot;password&quot; name=&quot;password&quot; id=&quot;password&quot; value=&quot;&quot;&gt;&lt;/div&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a password field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"passwordFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"struct","slug":"mapper.patch","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // Route name:  ghostStory\n    // Example URL: /ghosts/666/stories/616\n    // Controller:  Stories\n    // Action:      update\n    .patch(name=&quot;ghostStory&quot;, pattern=&quot;ghosts/[ghostKey]/stories/[key]&quot;, to=&quot;stories##update&quot;)\n\n    // Route name:  goblins\n    // Example URL: /goblins\n    // Controller:  Goblins\n    // Action:      update\n    .patch(name=&quot;goblins&quot;, controller=&quot;goblins&quot;, action=&quot;update&quot;)\n\n    // Route name:  heartbeat\n    // Example URL: /heartbeat\n    // Controller:  Sessions\n    // Action:      update\n    .patch(name=&quot;heartbeat&quot;, to=&quot;sessions##update&quot;)\n\n    // Route name:  usersPreferences\n    // Example URL: /preferences\n    // Controller:  users.Preferences\n    // Action:      update\n    .patch(name=&quot;preferences&quot;, to=&quot;preferences##update&quot;, package=&quot;users&quot;)\n\n    // Route name:  orderShipment\n    // Example URL: /shipments/5432\n    // Controller:  orders.Shipments\n    // Action:      update\n    .patch(\n        name=&quot;shipment&quot;,\n        pattern=&quot;shipments/[key]&quot;,\n        to=&quot;shipments##update&quot;,\n        package=&quot;orders&quot;\n    )\n\n    // Redirect a legacy PATCH endpoint to the canonical URL\n    // Example URL: /accounts/[key]/edit -&gt; redirects to /users/[key]/edit\n    .patch(name=&quot;legacyAccount&quot;, pattern=&quot;accounts/[key]/edit&quot;, redirect=&quot;/users/[key]/edit&quot;)\n\n    // Example scoping within a nested resource\n    .resources(name=&quot;subscribers&quot;, nested=true)\n        // Route name:  launchSubscribers\n        // Example URL: /subscribers/3209/launch\n        // Controller:  Subscribers\n        // Action:      update\n        .patch(name=&quot;launch&quot;, to=&quot;subscribers##update&quot;, on=&quot;collection&quot;)\n\n        // Route name:  discontinueSubscriber\n        // Example URL: /subscribers/2251/discontinue\n        // Controller:  Subscribers\n        // Action:      discontinue\n        .patch(name=&quot;discontinue&quot;, to=&quot;subscribers##discontinue&quot;, on=&quot;member&quot;)\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Create a route that matches a URL requiring an HTTP <code>PATCH</code> method. We recommend using this matcher to expose actions that update database records.\n\n","parameters":[{"type":"string","hint":"Camel-case name of route to reference when build links and form actions (e.g., `blogPost`).","required":false,"name":"name"},{"type":"string","hint":"Overrides the URL pattern that will match the route. The default value is a dasherized version of `name` (e.g., a `name` of `blogPost` generates a pattern of `blog-post`).","required":false,"name":"pattern"},{"type":"string","hint":"Set `controller##action` combination to map the route to. You may use either this argument or a combination of `controller` and `action`.","required":false,"name":"to"},{"type":"string","hint":"Map the route to a given controller. This must be passed along with the `action` argument.","required":false,"name":"controller"},{"type":"string","hint":"Map the route to a given action within the `controller`. This must be passed along with the `controller` argument.","required":false,"name":"action"},{"type":"string","hint":"Indicates a subfolder that the controller will be referenced from (but not added to the URL pattern). For example, if you set this to `admin`, the controller will be located at `admin/YourController.cfc`, but the URL path will not contain `admin/`.","required":false,"name":"package"},{"type":"string","hint":"If this route is within a nested resource, you can set this argument to `member` or `collection`. A `member` route contains a reference to the resource's `key`, while a `collection` route does not.","required":false,"name":"on"},{"type":"string","hint":"Redirect via 302 to this URL when this route is matched. Has precedence over controller/action. Use either an absolute link like `/about/`, or a full canonical link.","required":false,"name":"redirect"}],"name":"patch","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.pluginNames","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if the Scaffold plugin is installed\n&lt;cfif listFindNoCase(pluginNames(), &quot;scaffold&quot;)&gt;\n    // do something cool\n&lt;/cfif&gt;\n\n// 2. Output all installed plugin names\nnames = pluginNames();\n// names -&gt; &quot;scaffold,formobject,myplugin&quot; (comma-separated list of installed plugin names)\n\n// 3. Loop over installed plugins\n&lt;cfloop list=&quot;#pluginNames()#&quot; index=&quot;pluginName&quot;&gt;\n    writeOutput(pluginName);\n&lt;/cfloop&gt;\n</code></pre>","hasExtended":true},"hint":"Returns a list of the names of all installed plugins.\n\n","parameters":[],"name":"pluginNames","tags":{"category":"Miscellaneous Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.pluralize","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Pluralize a word using standard rules\nwriteOutput(pluralize(&quot;person&quot;));\n// -&gt; &quot;people&quot;\n\n// 2. Pluralize based on a count; returns count prepended to the word\nwriteOutput(pluralize(word=&quot;comment&quot;, count=1));\n// -&gt; &quot;1 comment&quot;\n\nwriteOutput(pluralize(word=&quot;comment&quot;, count=5));\n// -&gt; &quot;5 comments&quot;\n\n// 3. Pluralize based on a count but omit the count from the output\nwriteOutput(pluralize(word=&quot;person&quot;, count=users.RecordCount, returnCount=false));\n// -&gt; &quot;people&quot; (when RecordCount != 1) or &quot;person&quot; (when RecordCount == 1)\n</code></pre>","hasExtended":true},"hint":"Returns the plural form of the passed in word. Can also pluralize a word based on a value passed to the <code>count</code> argument. Wheels stores a list of words that are the same in both singular and plural form (e.g. \"equipment\", \"information\") and words that don't follow the regular pluralization rules (e.g. \"child\" / \"children\", \"foot\" / \"feet\"). Use <code>get(\"uncountables\")</code> / <code>set(\"uncountables\", newList)</code> and <code>get(\"irregulars\")</code> / <code>set(\"irregulars\", newList)</code> to modify them to suit your needs.\n\n","parameters":[{"type":"string","hint":"The word to pluralize.","required":true,"name":"word"},{"type":"numeric","hint":"Pluralization will occur when this value is not 1.","required":false,"name":"count","default":"-1"},{"type":"boolean","hint":"Will return count prepended to the pluralization when true and count is not -1.","required":false,"name":"returnCount","default":"true"}],"name":"pluralize","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"any","slug":"controller.policyScope","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Narrows a collection to the records the current user may see by delegating\nto the policy's <code>scope()</code> method. Returns whatever the policy returns —\nconventionally a chainable finder you keep composing:\n<code></code><code>\nfunction index() {\nposts = policyScope(model(\"Post\")).findAll(page = params.page, perPage = 25);\n}\n</code><code></code>\nPass the model class first and chain scopes after the call\n(<code>policyScope(model(\"Post\")).active()</code>) — a query-builder or scope chain\nthat is already in flight cannot be introspected for its model. When the\npolicy class is missing, this throws <code>Wheels.Policy.NotDefined</code> in\ndevelopment/testing and returns a default-deny (no rows) chain in\nproduction.\n\n","parameters":[{"type":"any","hint":"The model class to narrow.","required":true,"name":"collection"}],"name":"policyScope","tags":{"category":"Authorization Functions","sectionClass":"controller","section":"Controller","categoryClass":"authorizationfunctions"}},{"returntype":"struct","slug":"mapper.post","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Basic POST route using `to` shorthand (controller##action)\n    // Route name:  widgets\n    // Example URL: /sites/918/widgets\n    // Controller:  Widgets\n    // Action:      create\n    .post(name=&quot;widgets&quot;, pattern=&quot;sites/[siteKey]/widgets&quot;, to=&quot;widgets##create&quot;)\n\n    // 2. POST route using explicit `controller` and `action` arguments\n    // Route name:  wadgets\n    // Example URL: /wadgets\n    // Controller:  Wadgets\n    // Action:      create\n    .post(name=&quot;wadgets&quot;, controller=&quot;wadgets&quot;, action=&quot;create&quot;)\n\n    // 3. POST route with a custom URL pattern (e.g., format-bearing endpoint)\n    // Route name:  authenticate\n    // Example URL: /oauth/token.json\n    // Controller:  Tokens\n    // Action:      create\n    .post(name=&quot;authenticate&quot;, pattern=&quot;oauth/token.json&quot;, to=&quot;tokens##create&quot;)\n\n    // 4. POST route scoped to a package (subfolder) — package not in URL\n    // Route name:  usersPreferences\n    // Example URL: /preferences\n    // Controller:  users.Preferences\n    // Action:      create\n    .post(name=&quot;preferences&quot;, to=&quot;preferences##create&quot;, package=&quot;users&quot;)\n\n    // 5. POST route with both a custom pattern and a package\n    // Route name:  extranetOrders\n    // Example URL: /buy-now/orders\n    // Controller:  extranet.Orders\n    // Action:      create\n    .post(\n        name=&quot;orders&quot;,\n        pattern=&quot;buy-now/orders&quot;,\n        to=&quot;orders##create&quot;,\n        package=&quot;extranet&quot;\n    )\n\n    // 6. POST route that issues a 302 redirect instead of dispatching to a controller\n    // Route name:  legacySignup\n    // Example URL: /signup  →  redirects to /register\n    .post(name=&quot;legacySignup&quot;, pattern=&quot;signup&quot;, redirect=&quot;/register&quot;)\n\n    // 7. POST routes nested inside a `resources` block using `on`\n    .resources(name=&quot;customers&quot;, nested=true)\n        // Route name:  leadsCustomers\n        // Example URL: /customers/leads\n        // Controller:  Leads\n        // Action:      create\n        .post(name=&quot;leads&quot;, to=&quot;leads##create&quot;, on=&quot;collection&quot;)\n\n        // Route name:  cancelCustomer\n        // Example URL: /customers/3209/cancel\n        // Controller:  Cancellations\n        // Action:      create\n        .post(name=&quot;cancel&quot;, to=&quot;cancellations##create&quot;, on=&quot;member&quot;)\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Create a route that matches a URL requiring an HTTP <code>POST</code> method. We recommend using this matcher to expose actions that create database records.\n\n","parameters":[{"type":"string","hint":"Camel-case name of route to reference when build links and form actions (e.g., `blogPosts`).","required":false,"name":"name"},{"type":"string","hint":"Overrides the URL pattern that will match the route. The default value is a dasherized version of `name` (e.g., a `name` of `blogPosts` generates a pattern of `blog-posts`).","required":false,"name":"pattern"},{"type":"string","hint":"Set `controller##action` combination to map the route to. You may use either this argument or a combination of `controller` and `action`.","required":false,"name":"to"},{"type":"string","hint":"Map the route to a given controller. This must be passed along with the `action` argument.","required":false,"name":"controller"},{"type":"string","hint":"Map the route to a given action within the `controller`. This must be passed along with the `controller` argument.","required":false,"name":"action"},{"type":"string","hint":"Indicates a subfolder that the controller will be referenced from (but not added to the URL pattern). For example, if you set this to `admin`, the controller will be located at `admin/YourController.cfc`, but the URL path will not contain `admin/`.","required":false,"name":"package"},{"type":"string","hint":"If this route is within a nested resource, you can set this argument to `member` or `collection`. A `member` route contains a reference to the resource's `key`, while a `collection` route does not.","required":false,"name":"on"},{"type":"string","hint":"Redirect via 302 to this URL when this route is matched. Has precedence over controller/action. Use either an absolute link like `/about/`, or a full canonical link.","required":false,"name":"redirect"}],"name":"post","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"migrator.pretendVersion","availableIn":["migrator"],"extended":{"docs":"","hasExtended":false},"hint":"Records a version as applied in <code>wheels_migrator_versions</code> without\nrunning its up() method. Useful when a peer applied the migration\nvia direct SQL or a different tool and you need the tracking\ntable to reflect that. Refuses if the version is already applied,\nor if no local file matches (only known versions can be pretended).\nReturns: {success, recorded, message}\n\n","parameters":[{"type":"string","hint":"The version string to record (digits only after sanitisation).","required":true,"name":"version"}],"name":"pretendVersion","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"string","slug":"controller.previousPageLink","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>//--------------------------------------------------------------------\n// Example 1: Basic usage — show a &quot;Previous&quot; link above a paginated list;\n// renders a disabled span when already on the first page\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\nposts = model(&quot;Post&quot;).findAll(page=params.page, perPage=10, order=&quot;createdAt DESC&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #firstPageLink()#\n    #previousPageLink()#\n    #pageNumberLinks()#\n    #nextPageLink()#\n    #lastPageLink()#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom link text and CSS classes\n\n// View code\n&lt;cfoutput&gt;\n    #previousPageLink(\n        text=&quot;&amp;laquo; Previous&quot;,\n        class=&quot;page-link&quot;,\n        disabledClass=&quot;page-link disabled&quot;\n    )#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 3: Hide the disabled element entirely when on the first page\n\n// View code\n&lt;cfoutput&gt;\n    #previousPageLink(showDisabled=false)#\n&lt;/cfoutput&gt;\n\n\n//--------------------------------------------------------------------\n// Example 4: Use a named route so page numbers appear in the URL path\n// instead of as a query-string param (e.g. /articles/page/2)\n\n// Route setup in app/config/routes.cfm\nmapper()\n    .get(name=&quot;paginatedArticles&quot;, pattern=&quot;articles/page/[page]&quot;, to=&quot;articles##index&quot;)\n    .get(name=&quot;articles&quot;, pattern=&quot;articles&quot;, to=&quot;articles##index&quot;)\n.end();\n\n// Controller code\nparam name=&quot;params.page&quot; type=&quot;integer&quot; default=&quot;1&quot;;\narticles = model(&quot;Article&quot;).findAll(page=params.page, perPage=20, order=&quot;title&quot;);\n\n// View code\n&lt;cfoutput&gt;\n    #previousPageLink(route=&quot;paginatedArticles&quot;, pageNumberAsParam=false)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Creates a link to the previous page, or a disabled span when on the first page.\n\n","parameters":[{"type":"string","hint":"The text for the link.","required":false,"name":"text","default":"Previous"},{"type":"string","hint":"The handle given to the query that the pagination should be displayed for.","required":false,"name":"handle","default":"query"},{"type":"string","hint":"The name of the param that holds the current page number.","required":false,"name":"name","default":"page"},{"type":"string","hint":"CSS class for the link element.","required":false,"name":"class","default":""},{"type":"string","hint":"CSS class for the disabled span element.","required":false,"name":"disabledClass","default":"disabled"},{"type":"boolean","hint":"Whether to render a disabled span when on the first page.","required":false,"name":"showDisabled","default":true},{"type":"boolean","hint":"Decides whether to link the page number as a param or as part of a route.","required":false,"name":"pageNumberAsParam","default":true},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"previousPageLink","tags":{"category":"Pagination Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"paginationfunctions"}},{"returntype":"string","slug":"model.primaryKey","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the name of the primary key for the `employee` model (maps to the `employees` table by default)\nkeyName = model(&quot;employee&quot;).primaryKey();\n// keyName -&gt; &quot;id&quot;\n\n// 2. Get all primary key column names for a model with a composite primary key\nkeys = model(&quot;orderItem&quot;).primaryKey();\n// keys -&gt; &quot;orderId,productId&quot;\n\n// 3. Get only the first key of a composite primary key using the `position` argument\nfirstKey = model(&quot;orderItem&quot;).primaryKey(1);\n// firstKey -&gt; &quot;orderId&quot;\n\n// 4. Use the `primaryKeys()` alias (preferred for readability with composite keys)\nkeys = model(&quot;orderItem&quot;).primaryKeys();\n// keys -&gt; &quot;orderId,productId&quot;\n</code></pre>","hasExtended":true},"hint":"Returns the name of the primary key for this model's table.\nThis is determined through database introspection.\nIf composite primary keys have been used, they will both be returned in a list.\nThis function is also aliased as <code>primaryKeys()</code>.\n\n","parameters":[{"type":"numeric","hint":"If you are accessing a composite primary key, pass the position of a single key to fetch.","required":false,"name":"position","default":0}],"name":"primaryKey","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"tabledefinition.primaryKey","availableIn":["tabledefinition"],"extended":{"docs":"","hasExtended":false},"hint":"Adds a primary key definition to the table. this method also allows for multiple primary keys.\nAccepts <code>columnName</code> / <code>columnNames</code> as aliases for <code>name</code> (per #2803) so the\nPK helper matches the argument-naming convention every other column helper\nin this file uses. The legacy <code>name</code> parameter keeps working — it is still\nwhat the body reads and what <code>init()</code> passes when adding the conventional\n<code>id</code> primary key.\n\n","parameters":[{"type":"string","hint":"Legacy parameter for the primary-key column name. New code should prefer `columnName`.","required":false,"name":"name"},{"type":"string","hint":"Modern singular alias for `name` (matches sibling column helpers).","required":false,"name":"columnName"},{"type":"string","hint":"Modern plural alias for `name`. Accepted for muscle-memory parity with `t.integer(columnNames=...)` etc. NOTE: unlike sibling helpers, this does NOT accept a comma-separated list — `primaryKey()` always creates one PK column, so `columnNames=\"a,b\"` produces a single column literally named `a,b` (not two PKs). For composite PKs call `t.primaryKey()` multiple times.","required":false,"name":"columnNames"},{"type":"string","required":false,"name":"type","default":"integer"},{"type":"boolean","required":false,"name":"autoIncrement","default":"false"},{"type":"numeric","required":false,"name":"limit"},{"type":"numeric","required":false,"name":"precision"},{"type":"numeric","required":false,"name":"scale"},{"type":"string","required":false,"name":"references"},{"type":"string","required":false,"name":"onUpdate","default":""},{"type":"string","required":false,"name":"onDelete","default":""}],"name":"primaryKey","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"model.primaryKeys","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the name(s) of the primary key(s) for the User model (returns a comma-separated list for composite keys)\nkeyNames = model(&quot;User&quot;).primaryKeys();\n// keyNames -&gt; &quot;id&quot;\n\n// 2. Get the name of the first primary key in a model that uses a composite primary key (e.g., an OrderItem table keyed on orderId,productId)\nfirstKey = model(&quot;OrderItem&quot;).primaryKeys(1);\n// firstKey -&gt; &quot;orderId&quot;\n\n// 3. Get the second primary key in a composite key model\nsecondKey = model(&quot;OrderItem&quot;).primaryKeys(2);\n// secondKey -&gt; &quot;productId&quot;\n</code></pre>","hasExtended":true},"hint":"Alias for <code>primaryKey()</code>.\nUse this for better readability when you're accessing multiple primary keys.\n\n","parameters":[{"type":"numeric","hint":"If you are accessing a composite primary key, pass the position of a single key to fetch.","required":false,"name":"position","default":0}],"name":"primaryKeys","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"controller.processAction","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Process the current action (runs before and after filters plus the action itself).\n// Typically called automatically by the framework; used directly in unit tests.\nresult = controller.processAction();\n// result -&gt; true\n\n// 2. Process the action running only &quot;before&quot; filters (skip &quot;after&quot; filters).\nresult = controller.processAction(includeFilters=&quot;before&quot;);\n// result -&gt; true\n\n// 3. Process the action without running any filters.\nresult = controller.processAction(includeFilters=false);\n// result -&gt; true\n</code></pre>","hasExtended":true},"hint":"Process the specified action of the controller.\nThis is exposed in the API primarily for testing purposes; you would not usually call it directly unless in the test suite.\n\n","parameters":[{"type":"string","hint":"Set to `before` to only execute \"before\" filters, `after` to only execute \"after\" filters or `false` to skip all filters. This argument is generally inherited from the `processRequest` function during unit test execution.","required":false,"name":"includeFilters","default":true}],"name":"processAction","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"controller.processRequest","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage: simulate a GET request to the Users#index action and return the rendered body.\nresult = processRequest(params={controller=&quot;users&quot;, action=&quot;index&quot;});\n// result -&gt; &quot;&lt;html&gt;...&lt;/html&gt;&quot;\n\n// 2. Simulate a POST request to create a new user and return the full response struct.\nresult = processRequest(\n    params={controller=&quot;users&quot;, action=&quot;create&quot;, firstName=&quot;Jane&quot;, lastName=&quot;Doe&quot;},\n    method=&quot;post&quot;,\n    returnAs=&quot;struct&quot;\n);\n// result.status   -&gt; 302\n// result.redirect -&gt; &quot;/users&quot;\n// result.body     -&gt; &quot;&quot;\n// result.flash    -&gt; {success=&quot;User created.&quot;}\n\n// 3. Roll back all database changes made during the request (useful in tests to keep data clean).\nresult = processRequest(\n    params={controller=&quot;users&quot;, action=&quot;create&quot;, firstName=&quot;Jane&quot;},\n    method=&quot;post&quot;,\n    rollback=true,\n    returnAs=&quot;struct&quot;\n);\n// result.status -&gt; 302\n\n// 4. Run the action without any filters (bypass before/after filter logic).\nresult = processRequest(\n    params={controller=&quot;users&quot;, action=&quot;index&quot;},\n    includeFilters=false\n);\n// result -&gt; &quot;&lt;html&gt;...&lt;/html&gt;&quot;\n</code></pre>","hasExtended":true},"hint":"Creates a controller and calls an action on it.\nWhich controller and action that's called is determined by the params passed in.\nReturns the result of the request either as a string or in a struct with <code>body</code>, <code>emails</code>, <code>files</code>, <code>flash</code>, <code>redirect</code>, <code>status</code>, and <code>type</code>.\nPrimarily used for testing purposes.\n\n","parameters":[{"type":"struct","hint":"The params struct to use in the request (make sure that at least `controller` and `action` are set).","required":true,"name":"params"},{"type":"string","hint":"The HTTP method to use in the request (`get`, `post` etc).","required":false,"name":"method","default":"get"},{"type":"string","hint":"Pass in `struct` to return all information about the request instead of just the final output (`body`).","required":false,"name":"returnAs","default":""},{"type":"string","hint":"Pass in `true` to roll back all database transactions made during the request.","required":false,"name":"rollback","default":false},{"type":"string","hint":"Set to `before` to only execute \"before\" filters, `after` to only execute \"after\" filters or `false` to skip all filters.","required":false,"name":"includeFilters","default":true}],"name":"processRequest","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.projectContext","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Contexte d'un projet sous forme lisible.\nLa base separe le libelle et l'annee — c'est ce qui rend l'annee triable.\nLa recomposition pour l'affichage se fait donc ici, en un seul endroit.","parameters":[{"type":"any","required":false,"name":"context","default":"[runtime expression]"}],"name":"projectContext","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"struct","slug":"model.properties","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get all properties of a model object as a struct\nuser = model(&quot;User&quot;).findByKey(1);\nprops = user.properties();\n// props -&gt; {id: 1, firstName: &quot;Jane&quot;, lastName: &quot;Doe&quot;, email: &quot;jane@example.com&quot;, createdAt: ...}\n\n// 2. Exclude nested (included) association properties from the result\n// Useful when you only want the object's own scalar properties\npost = model(&quot;Post&quot;).findOne(include=&quot;comments&quot;);\nownProps = post.properties(returnIncluded=false);\n// ownProps -&gt; {id: 42, title: &quot;Hello World&quot;, body: &quot;...&quot;, createdAt: ...}\n// (nested `comments` array is omitted)\n\n// 3. Use properties() to pass a model's data as a plain struct (e.g. to a service layer)\nuser = model(&quot;User&quot;).findByKey(session.userId);\nuserService.syncUser(user.properties());\n</code></pre>","hasExtended":true},"hint":"Returns a structure of all the properties with their names as keys and the values of the property as values.\n\n","parameters":[{"type":"boolean","hint":"Whether to return nested properties or not.","required":false,"name":"returnIncluded","default":true}],"name":"properties","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"model.property","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Map a CFML property name to a differently-named database column\n// Tell Wheels that `firstName` in CFML maps to `STR_USERS_FNAME` in the database\n// instead of the default `firstname` column\nproperty(name=&quot;firstName&quot;, column=&quot;STR_USERS_FNAME&quot;);\n\n// 2. Create a calculated property using a SQL expression\n// `fullName` is derived by concatenating two columns at the database level\nproperty(name=&quot;fullName&quot;, sql=&quot;STR_USERS_FNAME + ' ' + STR_USERS_LNAME&quot;);\n\n// 3. Set a custom label used in form helpers and validation error messages\nproperty(name=&quot;firstName&quot;, label=&quot;First name(s)&quot;);\n\n// 4. Specify a default value applied when creating new objects\nproperty(name=&quot;firstName&quot;, defaultValue=&quot;Dave&quot;);\n\n// 5. Define a calculated property with a specific data type and exclude it from default SELECTs\n// Useful when the SQL expression returns a numeric result or when you only need\n// the value in specific queries\nproperty(name=&quot;orderTotal&quot;, sql=&quot;SUM(line_items.price)&quot;, dataType=&quot;decimal&quot;, select=false);\n\n// 6. Disable automatic validations for a specific property\n// Wheels normally infers validations (e.g. string-length, numeric) from the column type;\n// set automaticValidations=false to skip that for this property\nproperty(name=&quot;legacyCode&quot;, automaticValidations=false);\n</code></pre>","hasExtended":true},"hint":"Use this method to map an object property to either a table column with a different name than the property or to a SQL expression.\nYou only need to use this method when you want to override the default object relational mapping that Wheels performs.\n\n","parameters":[{"type":"string","hint":"The name that you want to use for the column or SQL function result in the CFML code.","required":true,"name":"name"},{"type":"string","hint":"The name of the column in the database table to map the property to.","required":false,"name":"column","default":""},{"type":"string","hint":"An SQL expression to use to calculate the property value.","required":false,"name":"sql","default":""},{"type":"string","hint":"A custom label for this property to be referenced in the interface and error messages.","required":false,"name":"label","default":""},{"type":"string","hint":"A default value for this property.","required":false,"name":"defaultValue"},{"type":"boolean","hint":"Whether to include this property by default in SELECT statements","required":false,"name":"select","default":"true"},{"type":"string","hint":"Specify the column dataType for this property","required":false,"name":"dataType","default":"char"},{"type":"boolean","hint":"Enable / disable automatic validations for this property.","required":false,"name":"automaticValidations"}],"name":"property","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"model.propertyIsBlank","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if a property is blank before sending a notification\nuser = model(&quot;User&quot;).findByKey(params.userId);\nif (user.propertyIsBlank(&quot;email&quot;)) {\n    flashInsert(error=&quot;Please provide an email address before continuing.&quot;);\n}\n\n// 2. Conditionally set a default value when a property is blank\nproduct = model(&quot;Product&quot;).findByKey(params.id);\nif (product.propertyIsBlank(&quot;description&quot;)) {\n    product.description = &quot;No description available.&quot;;\n    product.save();\n}\n\n// 3. Use propertyIsBlank alongside its inverse propertyIsPresent for branching logic\npost = model(&quot;Post&quot;).findByKey(params.postId);\nif (post.propertyIsBlank(&quot;publishedAt&quot;)) {\n    // post has never been published\n    writeOutput(&quot;Draft&quot;);\n} else {\n    // propertyIsPresent(&quot;publishedAt&quot;) would return true here\n    writeOutput(&quot;Published on #post.publishedAt#&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Returns <code>true</code> if the specified property doesn't exist on the model or is an empty string.\nThis method is the inverse of <code>propertyIsPresent()</code>.\n\n","parameters":[{"type":"string","hint":"Name of property to inspect.","required":true,"name":"property"}],"name":"propertyIsBlank","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"boolean","slug":"model.propertyIsPresent","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if a non-blank property is present\nemployee = model(&quot;Employee&quot;).new();\nemployee.firstName = &quot;Jane&quot;;\nwriteOutput(employee.propertyIsPresent(&quot;firstName&quot;)); // true\n\n// 2. Returns false when the property is an empty string\nemployee = model(&quot;Employee&quot;).new();\nemployee.firstName = &quot;&quot;;\nwriteOutput(employee.propertyIsPresent(&quot;firstName&quot;)); // false\n\n// 3. Returns false when the property does not exist on the object\nemployee = model(&quot;Employee&quot;).new();\nwriteOutput(employee.propertyIsPresent(&quot;nonExistentField&quot;)); // false\n</code></pre>","hasExtended":true},"hint":"Returns <code>true</code> if the specified property exists on the model and is not a blank string.\n\n","parameters":[{"type":"string","hint":"Name of property to inspect.","required":true,"name":"property"}],"name":"propertyIsPresent","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"model.propertyNames","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get a comma-delimited list of all property names for the User model\npropNames = model(&quot;User&quot;).propertyNames();\n// propNames -&gt; &quot;id,firstName,lastName,email,createdAt,updatedAt&quot;\n\n// 2. Check whether a specific property exists on the model before accessing it\npropNames = model(&quot;User&quot;).propertyNames();\nif (listFindNoCase(propNames, &quot;email&quot;)) {\n    writeOutput(&quot;email is a valid property&quot;);\n}\n\n// 3. Property names include calculated properties defined with property(sql=&quot;...&quot;)\n// In User.cfc config():\n//   property(name=&quot;fullName&quot;, sql=&quot;firstName || ' ' || lastName&quot;);\npropNames = model(&quot;User&quot;).propertyNames();\n// propNames -&gt; &quot;id,firstName,lastName,email,createdAt,updatedAt,fullName&quot;\n</code></pre>","hasExtended":true},"hint":"Returns a list of property names ordered by their respective column's ordinal position in the database table.\nAlso includes calculated property names that will be generated by the Wheels ORM.\n\n","parameters":[],"name":"propertyNames","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"model.protectedProperties","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Protect a comma-delimited list of properties from mass assignment in `models/User.cfc`.\n// `firstName` and `lastName` cannot be changed via `updateAll()`, `new()`, `update()`, etc.\nfunction config() {\n\tprotectedProperties(&quot;firstName,lastName&quot;);\n}\n\n// 2. Using the named argument form to protect sensitive fields like `role` and `isAdmin`\nfunction config() {\n\tprotectedProperties(properties=&quot;role,isAdmin&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Use this method to specify which properties cannot be set through mass assignment.\n\n","parameters":[{"type":"string","hint":"Property name (or list of property names) that are not allowed to be altered through mass assignment.","required":false,"name":"properties","default":""}],"name":"protectedProperties","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"controller.protectsFromForgery","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Protect all POST actions across the entire application (add to the base Controller.cfc).\ncomponent extends=&quot;Controller&quot; {\n    function config() {\n        protectsFromForgery();\n    }\n}\n\n// 2. Abort silently on an invalid token instead of throwing an exception.\ncomponent extends=&quot;Controller&quot; {\n    function config() {\n        protectsFromForgery(with=&quot;abort&quot;);\n    }\n}\n\n// 3. Enable CSRF protection only on state-changing actions.\ncomponent extends=&quot;Controller&quot; {\n    function config() {\n        protectsFromForgery(only=&quot;create, update, delete&quot;);\n    }\n}\n\n// 4. Enable CSRF protection globally but skip it for a public API endpoint.\ncomponent extends=&quot;Controller&quot; {\n    function config() {\n        protectsFromForgery(except=&quot;apiReceive&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Tells Wheels to protect <code>POST</code>ed requests from CSRF vulnerabilities.\nInstructs the controller to verify that <code>params.authenticityToken</code> or <code>X-CSRF-Token</code> HTTP header is provided along with the request containing a valid authenticity token.\nCall this method within a controller's <code>config</code> method, preferably the base <code>Controller.cfc</code> file, to protect the entire application.\n\n","parameters":[{"type":"string","hint":"How to handle invalid authenticity token checks. Valid values are `exception` (the default — throws a `Wheels.InvalidAuthenticityToken` error), `abort` (aborts the request silently and sends a blank response to the client), and `ignore` (ignores the check and lets the request proceed).","required":false,"name":"with","default":"exception"},{"type":"string","hint":"List of actions that this check should only run on. Leave blank for all.","required":false,"name":"only","default":""},{"type":"string","hint":"List of actions that this check should be omitted from running on. Leave blank for no exceptions.","required":false,"name":"except","default":""}],"name":"protectsFromForgery","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"void","slug":"controller.provides","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Allow the controller to respond to HTML and JSON requests\n// Place this call inside the controller's config() function\nprovides(&quot;html,json&quot;);\n\n// 2. Allow all supported formats for an API controller\nprovides(&quot;html,xml,json,csv,pdf,xls&quot;);\n\n// 3. JSON-only controller (e.g. a pure REST API controller)\n// Any request for a format other than json will be rejected\nprovides(&quot;json&quot;);\n</code></pre>","hasExtended":true},"hint":"Defines formats that the controller will respond with upon request.\nThe format can be requested through a URL variable called <code>format</code>, by appending the <code>format</code> name to the end of a URL as an extension (when URL rewriting is enabled), or in the request header.\n\n","parameters":[{"type":"string","hint":"Formats to instruct the controller to provide. Valid values are `html` (the default), `xml`, `json`, `csv`, `pdf`, and `xls`.","required":false,"name":"formats","default":""}],"name":"provides","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"struct","slug":"controller.publish","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Publish a notification event to a user-specific channel (in-memory adapter)\ndata = serializeJSON({message = &quot;Your order has shipped!&quot;, orderId = 42});\nresult = publish(channel=&quot;user.42&quot;, event=&quot;notification&quot;, data=data);\n// result -&gt; {success: true, ...}\n\n// 2. Publish an update event using the database adapter for persistence\ndata = serializeJSON({status = &quot;active&quot;, updatedAt = Now()});\nresult = publish(channel=&quot;products&quot;, event=&quot;update&quot;, data=data, adapter=&quot;database&quot;);\n\n// 3. Broadcast a chat message to a room channel\nresult = publish(\n    channel = &quot;chat.room.5&quot;,\n    event   = &quot;message&quot;,\n    data    = serializeJSON({user = &quot;alice&quot;, text = &quot;Hello everyone!&quot;})\n);\n</code></pre>","hasExtended":true},"hint":"Publish an event to a channel.\nDelegates to the in-memory Channel engine or the DatabaseAdapter\ndepending on the adapter argument (or the global channelAdapter setting).\nCan be called from controllers, models, jobs, or anywhere with access\nto global helpers.\n\n","parameters":[{"type":"string","hint":"The channel name to publish to (e.g. \"user.42\").","required":true,"name":"channel"},{"type":"string","hint":"The event type (e.g. \"notification\", \"update\").","required":true,"name":"event"},{"type":"string","hint":"The event data as a string (typically JSON).","required":true,"name":"data"},{"type":"string","hint":"Adapter to use: \"memory\" (default) or \"database\".","required":false,"name":"adapter","default":""}],"name":"publish","tags":{"category":"Channel Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"channelfunctions"}},{"returntype":"struct","slug":"mapper.put","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Basic PUT route using &quot;to&quot; shorthand (controller##action)\n    // Route name:  ghostStory\n    // Example URL: /ghosts/666/stories/616\n    // Controller:  Stories\n    // Action:      update\n    .put(name=&quot;ghostStory&quot;, pattern=&quot;ghosts/[ghostKey]/stories/[key]&quot;, to=&quot;stories##update&quot;)\n\n    // 2. Explicit controller and action arguments\n    // Route name:  goblins\n    // Example URL: /goblins\n    // Controller:  Goblins\n    // Action:      update\n    .put(name=&quot;goblins&quot;, controller=&quot;goblins&quot;, action=&quot;update&quot;)\n\n    // 3. Minimal &quot;to&quot; — pattern derived from name\n    // Route name:  heartbeat\n    // Example URL: /heartbeat\n    // Controller:  Sessions\n    // Action:      update\n    .put(name=&quot;heartbeat&quot;, to=&quot;sessions##update&quot;)\n\n    // 4. Scoped to a package (subfolder) — package not added to URL\n    // Route name:  usersPreferences\n    // Example URL: /preferences\n    // Controller:  users.Preferences\n    // Action:      update\n    .put(name=&quot;preferences&quot;, to=&quot;preferences##update&quot;, package=&quot;users&quot;)\n\n    // 5. Package combined with an explicit pattern\n    // Route name:  orderShipment\n    // Example URL: /shipments/5432\n    // Controller:  orders.Shipments\n    // Action:      update\n    .put(\n        name=&quot;shipment&quot;,\n        pattern=&quot;shipments/[key]&quot;,\n        to=&quot;shipments##update&quot;,\n        package=&quot;orders&quot;\n    )\n\n    // 6. Permanent redirect — useful when an endpoint has moved\n    // Example URL: /legacy-profile -&gt; redirects to /profile\n    .put(name=&quot;legacyProfile&quot;, pattern=&quot;legacy-profile&quot;, redirect=&quot;/profile&quot;)\n\n    // 7. &quot;on&quot; argument within a nested resource\n    .resources(name=&quot;subscribers&quot;, nested=true)\n        // Route name:  launchSubscribers\n        // Example URL: /subscribers/launch\n        // Controller:  Subscribers\n        // Action:      launch\n        .put(name=&quot;launch&quot;, to=&quot;subscribers##launch&quot;, on=&quot;collection&quot;)\n\n        // Route name:  discontinueSubscriber\n        // Example URL: /subscribers/2251/discontinue\n        // Controller:  Subscribers\n        // Action:      discontinue\n        .put(name=&quot;discontinue&quot;, to=&quot;subscribers##discontinue&quot;, on=&quot;member&quot;)\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Create a route that matches a URL requiring an HTTP <code>PUT</code> method. We recommend using this matcher to expose actions that update database records. This method is provided as a convenience for when you really need to support the <code>PUT</code> verb; consider using the <code>patch</code> matcher instead of this one.\n\n","parameters":[{"type":"string","hint":"Camel-case name of route to reference when build links and form actions (e.g., `blogPost`).","required":false,"name":"name"},{"type":"string","hint":"Overrides the URL pattern that will match the route. The default value is a dasherized version of `name` (e.g., a `name` of `blogPost` generates a pattern of `blog-post`).","required":false,"name":"pattern"},{"type":"string","hint":"Set `controller##action` combination to map the route to. You may use either this argument or a combination of `controller` and `action`.","required":false,"name":"to"},{"type":"string","hint":"Map the route to a given controller. This must be passed along with the `action` argument.","required":false,"name":"controller"},{"type":"string","hint":"Map the route to a given action within the `controller`. This must be passed along with the `controller` argument.","required":false,"name":"action"},{"type":"string","hint":"Indicates a subfolder that the controller will be referenced from (but not added to the URL pattern). For example, if you set this to `admin`, the controller will be located at `admin/YourController.cfc`, but the URL path will not contain `admin/`.","required":false,"name":"package"},{"type":"string","hint":"If this route is within a nested resource, you can set this argument to `member` or `collection`. A `member` route contains a reference to the resource's `key`, while a `collection` route does not.","required":false,"name":"on"},{"type":"string","hint":"Redirect via 302 to this URL when this route is matched. Has precedence over controller/action. Use either an absolute link like `/about/`, or a full canonical link.","required":false,"name":"redirect"}],"name":"put","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.radioButton","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic radio buttons for a gender property on a user object\n&lt;cfoutput&gt;\n\t&lt;fieldset&gt;\n\t\t&lt;legend&gt;Gender&lt;/legend&gt;\n\t\t#radioButton(objectName=&quot;user&quot;, property=&quot;gender&quot;, tagValue=&quot;m&quot;, label=&quot;Male&quot;)#\n\t\t#radioButton(objectName=&quot;user&quot;, property=&quot;gender&quot;, tagValue=&quot;f&quot;, label=&quot;Female&quot;)#\n\t&lt;/fieldset&gt;\n&lt;/cfoutput&gt;\n\n// 2. Radio buttons with label placed after the control and a CSS class applied\n&lt;cfoutput&gt;\n\t#radioButton(objectName=&quot;user&quot;, property=&quot;status&quot;, tagValue=&quot;active&quot;, label=&quot;Active&quot;, labelPlacement=&quot;after&quot;, class=&quot;status-radio&quot;)#\n\t#radioButton(objectName=&quot;user&quot;, property=&quot;status&quot;, tagValue=&quot;inactive&quot;, label=&quot;Inactive&quot;, labelPlacement=&quot;after&quot;, class=&quot;status-radio&quot;)#\n&lt;/cfoutput&gt;\n\n// 3. Radio buttons for a nested hasMany association (e.g. setting each committee member's gender)\n&lt;cfoutput&gt;\n\t&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(committee.members)#&quot; index=&quot;i&quot;&gt;\n\t\t&lt;div&gt;\n\t\t\t&lt;h3&gt;#committee.members[i].fullName#:&lt;/h3&gt;\n\t\t\t#radioButton(objectName=&quot;committee&quot;, association=&quot;members&quot;, position=i, property=&quot;gender&quot;, tagValue=&quot;m&quot;, label=&quot;Male&quot;)#\n\t\t\t#radioButton(objectName=&quot;committee&quot;, association=&quot;members&quot;, position=i, property=&quot;gender&quot;, tagValue=&quot;f&quot;, label=&quot;Female&quot;)#\n\t\t&lt;/div&gt;\n\t&lt;/cfloop&gt;\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a radio button form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The value of the radio button when selected.","required":false,"name":"tagValue"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"radioButton","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.radioButtonTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage with a group of radio buttons sharing the same name\n&lt;cfoutput&gt;\n\t&lt;fieldset&gt;\n\t\t&lt;legend&gt;Gender&lt;/legend&gt;\n\t\t#radioButtonTag(name=&quot;gender&quot;, value=&quot;m&quot;, label=&quot;Male&quot;, checked=true)#\n\t\t#radioButtonTag(name=&quot;gender&quot;, value=&quot;f&quot;, label=&quot;Female&quot;)#\n\t&lt;/fieldset&gt;\n&lt;/cfoutput&gt;\n\n// 2. Place the label after the radio button instead of wrapping it\n&lt;cfoutput&gt;\n\t#radioButtonTag(name=&quot;size&quot;, value=&quot;s&quot;, label=&quot;Small&quot;, labelPlacement=&quot;after&quot;)#\n\t#radioButtonTag(name=&quot;size&quot;, value=&quot;m&quot;, label=&quot;Medium&quot;, labelPlacement=&quot;after&quot;)#\n\t#radioButtonTag(name=&quot;size&quot;, value=&quot;l&quot;, label=&quot;Large&quot;, labelPlacement=&quot;after&quot;)#\n&lt;/cfoutput&gt;\n\n// 3. Loop over a query to render one radio button per option\n// Controller\nsizes = model(&quot;Size&quot;).findAll(order=&quot;position&quot;);\n\n// View\n&lt;cfoutput query=&quot;sizes&quot;&gt;\n\t#radioButtonTag(\n\t\tname   = &quot;sizeId&quot;,\n\t\tvalue  = sizes.id,\n\t\tlabel  = sizes.name,\n\t\tchecked = sizes.id EQ params.sizeId\n\t)#\n&lt;/cfoutput&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a radio button form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":true,"name":"value"},{"type":"boolean","hint":"Whether or not to check the radio button by default.","required":false,"name":"checked","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"radioButtonTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.rangeField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic range slider bound to a model object\n#rangeField(objectName=&quot;settings&quot;, property=&quot;volume&quot;)#\n\n// 2. Range slider with min, max, and step constraints\n#rangeField(label=&quot;Volume&quot;, objectName=&quot;settings&quot;, property=&quot;volume&quot;, min=&quot;0&quot;, max=&quot;100&quot;, step=&quot;5&quot;)#\n\n// 3. Range slider for a nested association (preferences within a user profile)\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(user.preferences)#&quot; index=&quot;i&quot;&gt;\n\t#rangeField(label=&quot;Threshold ##i#&quot;, objectName=&quot;user&quot;, association=&quot;preferences&quot;, position=i, property=&quot;threshold&quot;, min=&quot;0&quot;, max=&quot;10&quot;, step=&quot;1&quot;)#\n&lt;/cfloop&gt;</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a range slider form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"Minimum allowed value.","required":false,"name":"min"},{"type":"string","hint":"Maximum allowed value.","required":false,"name":"max"},{"type":"string","hint":"Stepping interval.","required":false,"name":"step"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"rangeField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.rangeFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic range slider with a name and current value\n#rangeFieldTag(name=&quot;volume&quot;, value=params.volume)#\n\n// 2. Range slider with min, max, and step constraints plus a label\n#rangeFieldTag(name=&quot;brightness&quot;, value=params.brightness, label=&quot;Brightness&quot;, min=&quot;0&quot;, max=&quot;100&quot;, step=&quot;5&quot;)#\n\n// 3. Range slider with a CSS class and appended display hint\n#rangeFieldTag(name=&quot;opacity&quot;, value=params.opacity, label=&quot;Opacity&quot;, min=&quot;0&quot;, max=&quot;1&quot;, step=&quot;0.1&quot;, class=&quot;opacity-slider&quot;, append=&quot;(0–1)&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a range slider form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"Minimum allowed value.","required":false,"name":"min"},{"type":"string","hint":"Maximum allowed value.","required":false,"name":"max"},{"type":"string","hint":"Stepping interval.","required":false,"name":"step"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"rangeFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"void","slug":"controller.redirectTo","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Redirect to an action after successfully saving a user.\nif (user.save()) {\n\tredirectTo(action=&quot;saveSuccessful&quot;);\n}\n\n// 2. Redirect to a different controller and action on a secure server with extra query params.\nredirectTo(controller=&quot;checkout&quot;, action=&quot;start&quot;, params=&quot;type=express&quot;, protocol=&quot;https&quot;);\n\n// 3. Redirect to a named route and pass in a dynamic route variable.\nredirectTo(route=&quot;profile&quot;, screenName=&quot;Joe&quot;);\n\n// 4. Redirect back to the referring page (e.g. after a cancelled edit).\nredirectTo(back=true);\n\n// 5. Redirect to an external URL (requires allowExternalRedirects=true in config).\nredirectTo(url=&quot;https://example.com/landing&quot;);\n\n// 6. Delay the redirect until after the rest of the action has run, and set a flash message.\nredirectTo(action=&quot;index&quot;, delay=true, flashMessage=&quot;Record deleted successfully.&quot;);\n\n// 7. Use a 301 permanent redirect when moving a page.\nredirectTo(controller=&quot;posts&quot;, action=&quot;index&quot;, statusCode=301);\n</code></pre>","hasExtended":true},"hint":"Redirects the browser to the supplied controller/action/key, route or back to the referring page.\nInternally, this function uses the <code>URLFor</code> function to build the link and the <code>cflocation</code> tag to perform the redirect.\n\n","parameters":[{"type":"boolean","hint":"Set to `true` to redirect back to the referring page.","required":false,"name":"back","default":false},{"type":"boolean","hint":"See documentation for your CFML engine's implementation of `cflocation`.","required":false,"name":"addToken","default":false},{"type":"numeric","hint":"See documentation for your CFML engine's implementation of `cflocation`.","required":false,"name":"statusCode","default":302},{"type":"string","hint":"Name of a route that you have configured in `config/routes.cfm`.","required":false,"name":"route","default":""},{"type":"string","hint":"HTTP method constraint used when matching routes.","required":false,"name":"method","default":""},{"type":"string","hint":"Name of the controller to include in the URL.","required":false,"name":"controller","default":""},{"type":"string","hint":"Name of the action to include in the URL.","required":false,"name":"action","default":""},{"type":"any","hint":"Key(s) to include in the URL.","required":false,"name":"key","default":""},{"type":"string","hint":"Any additional parameters to be set in the query string (example: `wheels=cool&x=y`). Please note that Wheels uses the `&` and `=` characters to split the parameters and encode them properly for you. However, if you need to pass in `&` or `=` as part of the value, then you need to encode them (and only them), example: `a=cats%26dogs%3Dtrouble!&b=1`.","required":false,"name":"params","default":""},{"type":"string","hint":"Sets an anchor name to be appended to the path.","required":false,"name":"anchor","default":""},{"type":"boolean","hint":"If `true`, returns only the relative URL (no protocol, host name or port).","required":false,"name":"onlyPath","default":true},{"type":"string","hint":"Set this to override the current host.","required":false,"name":"host","default":""},{"type":"string","hint":"Set this to override the current protocol.","required":false,"name":"protocol","default":""},{"type":"numeric","hint":"Set this to override the current port number.","required":false,"name":"port","default":0},{"type":"string","hint":"Redirect to an external URL.","required":false,"name":"url","default":""},{"type":"boolean","hint":"Set to `true` to delay the redirection until after the rest of your action code has executed.","required":false,"name":"delay","default":false},{"type":"boolean","hint":"Encode URL parameters using `EncodeForURL()`. Please note that this does not make the string safe for placement in HTML attributes, for that you need to wrap the result in `EncodeForHtmlAttribute()` or use `linkTo()`, `startFormTag()` etc instead.","required":false,"name":"encode","default":true}],"name":"redirectTo","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"migrator.redoMigration","availableIn":["migrator"],"extended":{"docs":"<pre><code class='javascript'>// 1. Redo the current (most recent) migration — rolls it back then re-applies it\nresult = application.wheels.migrator.redoMigration();\n// result -&gt; &quot;\n// ------- 20240315120000_add_status_to_orders ----------------------\n// &quot;\n\n// 2. Redo a specific migration version\nresult = application.wheels.migrator.redoMigration(version=&quot;20240101000000&quot;);\n// result -&gt; &quot;\n// ------- 20240101000000_create_users ------------------------------\n// &quot;\n\n// 3. Check for errors after redoing a migration\nresult = application.wheels.migrator.redoMigration(version=&quot;20240315120000&quot;);\nif (FindNoCase(&quot;Error&quot;, result)) {\n    writeOutput(&quot;Redo failed: &quot; &amp; result);\n} else {\n    writeOutput(&quot;Migration redone successfully.&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Reruns the specified migration version. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n","parameters":[{"type":"string","hint":"The Database schema version to rerun","required":false,"name":"version","default":""}],"name":"redoMigration","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"any","slug":"tabledefinition.references","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// The generated column suffix depends on the `useUnderscoreReferenceColumns` setting:\n// `true` (the default for apps generated by `wheels new`) produces `&lt;name&gt;_id` / `&lt;name&gt;_type`,\n// matching Wheels model `belongsTo` defaults; `false` (the framework default for existing apps)\n// produces `&lt;name&gt;id` / `&lt;name&gt;type`. The examples below show both outcomes.\n\n// 1. Add a single reference column with a foreign key constraint\n// Creates a `user_id` (or `userid`) integer column and a foreign key pointing to the `users` table.\nt = createTable(name='posts');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.references(columnNames='user');\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple reference columns at once\n// Creates `author_id` and `category_id` (or `authorid` and `categoryid`) integer columns,\n// each with a foreign key.\nt = createTable(name='articles');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.references(columnNames='author,category');\n\tt.timestamps();\nt.create();\n\n// 3. Add a polymorphic reference (no foreign key, adds a `&lt;name&gt;_type` / `&lt;name&gt;type` string column)\n// Creates `commentable_id` (integer) and `commentable_type` (string) columns\n// (or `commentableid` / `commentabletype` when `useUnderscoreReferenceColumns` is `false`).\nt = createTable(name='comments');\n\tt.text(columnNames='body', allowNull=false);\n\tt.references(columnNames='commentable', polymorphic=true);\n\tt.timestamps();\nt.create();\n\n// 4. Add a reference with cascade delete and allow null\n// The legacy `referenceNames=` argument is still accepted as an alias for `columnNames=`.\nt = createTable(name='attachments');\n\tt.references(columnNames='post', allowNull=true, onDelete='cascade');\n\tt.string(columnNames='fileName', limit=255);\n\tt.timestamps();\nt.create();\n</code></pre>","hasExtended":true},"hint":"Adds integer reference columns to the table definition and (unless\n<code>foreignKey=false</code> or <code>polymorphic=true</code>) registers a matching foreign-key\nconstraint. The column suffix depends on the <code>useUnderscoreReferenceColumns</code>\nsetting: <code>false</code> (framework default) → <code><name>id</code>; <code>true</code> (default for\napps generated by <code>wheels new</code>) → <code><name>_id</code>, matching Wheels model\n<code>belongsTo</code> defaults. With <code>polymorphic=true</code>, a <code><name>type</code> / <code><name>_type</code>\ncompanion column is added and no FK is registered.\nAccepts <code>columnNames</code> as an alias for <code>referenceNames</code> (per #2781) — both\nare list-shaped (single name or comma-delimited). New code should use\n<code>columnNames</code> for consistency with every other column helper here.\n\n","parameters":[{"type":"string","hint":"Comma-delimited list of reference base names (e.g. `\"user,role\"`). Each produces a `<name>_id` (or `<name>id`) column. Legacy parameter — `columnNames` is the modern alias.","required":false,"name":"referenceNames"},{"type":"string","hint":"Modern alias for `referenceNames`. Pass one or the other — not both.","required":false,"name":"columnNames"},{"type":"any","hint":"Default value for the generated integer column(s).","required":false,"name":"default"},{"type":"boolean","hint":"If true, the generated column(s) allow NULL.","required":false,"name":"allowNull","default":"false"},{"type":"boolean","hint":"If true, also creates a `<name>type` / `<name>_type` companion column and skips the foreign-key constraint.","required":false,"name":"polymorphic","default":"false"},{"type":"boolean","hint":"If true (default), registers a foreign key on the generated column. Ignored when `polymorphic=true`.","required":false,"name":"foreignKey","default":"true"},{"type":"string","hint":"Foreign-key ON UPDATE clause. Engine-specific values; common: `\"cascade\"`, `\"null\"`, `\"none\"`.","required":false,"name":"onUpdate","default":""},{"type":"string","hint":"Foreign-key ON DELETE clause. Same value set as `onUpdate`.","required":false,"name":"onDelete","default":""}],"name":"references","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"controller.refLabel","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Libelle d'une valeur de reference, ou une chaine vide.","parameters":[{"type":"any","required":false,"name":"valeur","default":"[runtime expression]"}],"name":"refLabel","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"void","slug":"controller.registerOnError","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a simple error-notification callback in config/settings.cfm\nregisterOnError(function(exception) {\n    writeLog(\n        file = &quot;app-errors&quot;,\n        type = &quot;error&quot;,\n        text = &quot;Unhandled error: #exception.message# | Type: #exception.type#&quot;\n    );\n});\n\n// 2. Register multiple callbacks — they fire in registration order\nregisterOnError(function(exception) {\n    // Notify an external monitoring service\n    local.payload = serializeJSON({\n        message = exception.message,\n        type    = exception.type,\n        detail  = exception.detail\n    });\n    // cfhttp call to monitoring endpoint would go here\n});\n\nregisterOnError(function(exception) {\n    // Store the last error in the application scope for the admin dashboard\n    application.lastError = {\n        message   = exception.message,\n        type      = exception.type,\n        timestamp = now()\n    };\n});\n\n// 3. Guard against slow operations — callbacks must complete quickly\nregisterOnError(function(exception) {\n    // Do NOT perform long-running tasks here (database queries, large file I/O).\n    // A failing callback is caught, logged, and skipped so other callbacks still run.\n    if (structKeyExists(exception, &quot;message&quot;) &amp;&amp; len(exception.message)) {\n        writeLog(file = &quot;wheels&quot;, type = &quot;error&quot;, text = &quot;App error: #exception.message#&quot;);\n    }\n});\n</code></pre>","hasExtended":true},"hint":"Registers a callback function to be invoked when an unhandled error occurs.\nCallbacks receive a single argument: the exception struct.\nMultiple callbacks are invoked in registration order. A failing callback\nis logged and skipped — it will not prevent other callbacks from running.\nShould be called during app initialization, not per-request.\n\n","parameters":[{"type":"function","hint":"A function that accepts an exception struct argument. Must complete quickly — long-running callbacks delay error responses.","required":true,"name":"callback"}],"name":"registerOnError","tags":{"category":"Error Handling","sectionClass":"configuration","section":"Configuration","categoryClass":"errorhandling"}},{"returntype":"string","slug":"controller.reglage","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Valeur d'un reglage du site, avec repli.\nLe repli n'est pas decoratif : un reglage vide ou une API muette ne\ndoivent pas produire une page trouee.","parameters":[{"type":"string","required":true,"name":"code"},{"type":"string","required":false,"name":"defaut","default":""}],"name":"reglage","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"void","slug":"model.reload","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Reload after a call that may have changed values in the database\nemployee = model(&quot;Employee&quot;).findByKey(params.key);\nemployee.someCallThatChangesValuesInTheDatabase();\nemployee.reload();\n\n// 2. Discard in-memory changes and restore the current database values\npost = model(&quot;Post&quot;).findByKey(params.id);\npost.title = &quot;Draft title that we want to discard&quot;;\npost.reload();\n// post.title now reflects the value stored in the database\n</code></pre>","hasExtended":true},"hint":"Reloads the property values of this object from the database.\n\n","parameters":[],"name":"reload","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"migration.removeColumn","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Remove a column by specifying its name directly\nremoveColumn(table=&quot;members&quot;, columnName=&quot;status&quot;);\n\n// 2. Remove a reference column using its reference name (removes the &lt;referenceName&gt;id column)\nremoveColumn(table=&quot;posts&quot;, referenceName=&quot;author&quot;);\n// Removes the column named &quot;authorid&quot; from the posts table\n\n// 3. Typical use inside a migration's down() method to reverse an addColumn()\nfunction down() {\n    removeColumn(table=&quot;products&quot;, columnName=&quot;discountPrice&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Removes a column from a database table\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table containing the column to remove","required":true,"name":"table"},{"type":"string","hint":"The column name to remove","required":false,"name":"columnName"},{"type":"string","hint":"Modern alias for `columnName` (matches the plural form every TableDefinition column helper accepts). Pass one or the other — not both.","required":false,"name":"columnNames"},{"type":"string","hint":"optional reference name","required":false,"name":"referenceName","default":""}],"name":"removeColumn","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.removeIndex","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Remove an index by its name\nremoveIndex(table=&quot;members&quot;, indexName=&quot;members_username&quot;);\n\n// 2. Remove a compound index created on multiple columns\n// (index was previously added as &quot;orders_customerid_createdat&quot;)\nremoveIndex(table=&quot;orders&quot;, indexName=&quot;orders_customerid_createdat&quot;);\n\n// 3. Typical down() migration reversing an addIndex call\ncomponent extends=&quot;wheels.Migrator&quot; {\n    function up() {\n        addIndex(table=&quot;articles&quot;, columnNames=&quot;slug&quot;, unique=true, indexName=&quot;articles_slug&quot;);\n    }\n    function down() {\n        removeIndex(table=&quot;articles&quot;, indexName=&quot;articles_slug&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Remove a database index\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name to perform the index operation on","required":true,"name":"table"},{"type":"string","hint":"the name of the index to remove","required":true,"name":"indexName"}],"name":"removeIndex","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.removeRecord","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Remove all records from a table (use with caution)\nremoveRecord(table = &quot;sessions&quot;);\n\n// 2. Remove a specific record by primary key\nremoveRecord(table = &quot;roles&quot;, where = &quot;id = 1&quot;);\n\n// 3. Remove multiple records matching a condition\nremoveRecord(table = &quot;users&quot;, where = &quot;active = 0&quot;);\n\n// 4. Use removeRecord in a migration's down() function to reverse an addRecord call\ncomponent extends=&quot;wheels.migrator.Migration&quot; {\n    function up() {\n        addRecord(\n            table = &quot;settings&quot;,\n            name = &quot;maintenanceMode&quot;,\n            value = &quot;false&quot;\n        );\n    }\n    function down() {\n        removeRecord(table = &quot;settings&quot;, where = &quot;name = 'maintenanceMode'&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Removes existing records from a table\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name to remove the record from","required":true,"name":"table"},{"type":"string","hint":"The where clause, i.e id = 123","required":false,"name":"where","default":""}],"name":"removeRecord","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"migration.renameColumn","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Rename a column in the users table\nrenameColumn(table=&quot;users&quot;, columnName=&quot;userName&quot;, newColumnName=&quot;username&quot;);\n\n// 2. Rename a column as part of a migration's up() and down() methods\ncomponent extends=&quot;wheels.migrator.Migration&quot; hint=&quot;Rename fullName to displayName in profiles&quot; {\n    function up() {\n        renameColumn(table=&quot;profiles&quot;, columnName=&quot;fullName&quot;, newColumnName=&quot;displayName&quot;);\n    }\n\n    function down() {\n        renameColumn(table=&quot;profiles&quot;, columnName=&quot;displayName&quot;, newColumnName=&quot;fullName&quot;);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Renames a table column\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table containing the column to rename","required":true,"name":"table"},{"type":"string","hint":"The column name to rename","required":true,"name":"columnName"},{"type":"string","hint":"The new column name","required":true,"name":"newColumnName"}],"name":"renameColumn","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"struct","slug":"migrator.renameSystemTables","availableIn":["migrator"],"extended":{"docs":"<pre><code class='javascript'>// 1. Rename legacy c_o_r_e_* tables to wheels_* in one step\nresult = application.wheels.migrator.renameSystemTables();\n// result.success  -&gt; true\n// result.renamed  -&gt; [&quot;c_o_r_e_levels -&gt; wheels_levels&quot;, &quot;c_o_r_e_migrator_versions -&gt; wheels_migrator_versions&quot;]\n// result.sql      -&gt; [&quot;ALTER TABLE c_o_r_e_migrator_versions RENAME TO wheels_migrator_versions&quot;, &quot;ALTER TABLE c_o_r_e_levels RENAME TO wheels_levels&quot;]\n// result.skipped  -&gt; &quot;&quot;\n// result.errors   -&gt; []\n\n// 2. Dry-run: preview the SQL without executing any changes\nresult = application.wheels.migrator.renameSystemTables(dryRun=true);\n// result.success  -&gt; true\n// result.renamed  -&gt; []   (nothing executed)\n// result.sql      -&gt; [&quot;ALTER TABLE c_o_r_e_migrator_versions RENAME TO wheels_migrator_versions&quot;, &quot;ALTER TABLE c_o_r_e_levels RENAME TO wheels_levels&quot;]\n\n// 3. Handle all possible outcomes after running the rename\nresult = application.wheels.migrator.renameSystemTables();\nif (!result.success) {\n    // Partial-rename conflict or execution error\n    writeOutput(&quot;Rename failed: &quot; &amp; arrayToList(result.errors, &quot;; &quot;));\n} else if (len(result.skipped)) {\n    // Tables were already on wheels_* names (or no legacy tables found)\n    writeOutput(result.skipped);\n} else {\n    writeOutput(&quot;Renamed: &quot; &amp; arrayToList(result.renamed, &quot;, &quot;));\n}\n</code></pre>","hasExtended":true},"hint":"F15 Phase 2: rename legacy <code>c_o_r_e_*</code> system tables to <code>wheels_*</code>.\nPublic API for the <code>wheels migrate rename-system-tables</code> CLI command.\nReads the current schema, generates per-adapter rename SQL, and\n(unless <code>dryRun</code> is true) executes it inside a transaction. After\na successful rename, updates <code>application.wheels.{levelsTableName,\nmigratorTableName}</code> to the new names so the running app picks them\nup without a restart.\nResult struct:\n- success: boolean\n- renamed: array of \"old -> new\" strings (empty if no-op)\n- skipped: human message when there's nothing to do\n- errors: array of error messages (when success=false)\n- sql: array of SQL statements that would run / did run\nRefuses to run (returns success=false) when both <code>c_o_r_e_*</code> AND\n<code>wheels_*</code> versions of either table coexist — that's a partial-\nrename state which warrants manual cleanup, not silent destruction.\n\n","parameters":[{"type":"boolean","hint":"When true, returns the SQL that would run without executing.","required":false,"name":"dryRun","default":false}],"name":"renameSystemTables","tags":{"category":"General Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"generalfunctions"}},{"returntype":"void","slug":"migration.renameTable","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Rename a table from its old name to a new name\nrenameTable(oldName=&quot;blogPosts&quot;, newName=&quot;posts&quot;);\n\n// 2. Rename a table as part of a migration up/down pair\ncomponent extends=&quot;wheels.Migrator&quot; {\n\n    function up() {\n        renameTable(oldName=&quot;members&quot;, newName=&quot;users&quot;);\n    }\n\n    function down() {\n        renameTable(oldName=&quot;users&quot;, newName=&quot;members&quot;);\n    }\n\n}\n</code></pre>","hasExtended":true},"hint":"Renames a table\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"Name the old table","required":true,"name":"oldName"},{"type":"string","hint":"New name for the table","required":true,"name":"newName"}],"name":"renameTable","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"void","slug":"controller.renderNothing","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Render a blank response (useful for AJAX fire-and-forget actions)\nrenderNothing();\n\n// 2. Render a blank response with a specific HTTP status code (e.g., 204 No Content)\nrenderNothing(status=204);\n\n// 3. Use renderNothing() instead of cfabort so that after-filters still run\n// In a controller action:\nfunction markAsRead() {\n    post = model(&quot;Post&quot;).findByKey(params.key);\n    post.update(read=true);\n    // After-filters (e.g. logging) will still execute, unlike cfabort\n    renderNothing();\n}\n</code></pre>","hasExtended":true},"hint":"Instructs the controller to render an empty string when it's finished processing the action.\nThis is very similar to calling <code>cfabort</code> with the advantage that any after filters you have set on the action will still be run.\n\n","parameters":[{"type":"string","hint":"Force request to return with specific HTTP status code.","required":false,"name":"status","default":"[runtime expression]"}],"name":"renderNothing","tags":{"category":"Rendering Functions","sectionClass":"controller","section":"Controller","categoryClass":"renderingfunctions"}},{"returntype":"any","slug":"controller.renderPartial","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Render the partial `_comment.cfm` located in the current controller's view folder\nrenderPartial(&quot;comment&quot;);\n\n// 2. Render the partial at `app/views/shared/_comment.cfm` using an absolute path\nrenderPartial(&quot;/shared/comment&quot;);\n\n// 3. Return the rendered partial as a string instead of sending it to the client\ncommentHtml = renderPartial(partial=&quot;comment&quot;, returnAs=&quot;string&quot;);\n\n// 4. Render a shared partial wrapped in a layout and cache it for 5 minutes\nrenderPartial(partial=&quot;/shared/sidebar&quot;, layout=&quot;/layouts/sidebar&quot;, cache=5);\n\n// 5. Render a partial using a named data-loading function to supply variables\n//    (the controller must have a private function named `comment` returning a struct)\nrenderPartial(partial=&quot;comment&quot;, dataFunction=&quot;comment&quot;);\n\n// 6. Render a partial and force a specific HTTP status code (e.g. for AJAX responses)\nrenderPartial(partial=&quot;/shared/error&quot;, status=422);\n</code></pre>","hasExtended":true},"hint":"Instructs the controller to render a partial when it's finished processing the action.\n\n","parameters":[{"type":"string","hint":"The name of the partial file to be used. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder. Do not include the partial filename's underscore and file extension.","required":true,"name":"partial"},{"type":"any","hint":"Number of minutes to cache the content for.","required":false,"name":"cache","default":""},{"type":"string","hint":"The layout to wrap the content in. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder. Pass `false` to not load a layout at all.","required":false,"name":"layout","default":""},{"type":"string","hint":"Set to `string` to return the result instead of automatically sending it to the client.","required":false,"name":"returnAs","default":""},{"type":"any","hint":"Name of a controller function to load data from.","required":false,"name":"dataFunction","default":true},{"type":"string","hint":"Force request to return with specific HTTP status code.","required":false,"name":"status","default":"[runtime expression]"}],"name":"renderPartial","tags":{"category":"Rendering Functions","sectionClass":"controller","section":"Controller","categoryClass":"renderingfunctions"}},{"returntype":"void","slug":"controller.renderSSE","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Render a single SSE event as the controller response.\nThis sets appropriate headers and formats the response as an SSE event.\nThe client should use EventSource to connect and will receive this single event.","parameters":[{"type":"string","hint":"The event data to send (string). Will be sent as-is.","required":true,"name":"data"},{"type":"string","hint":"Optional event type name. Client can listen for specific event types.","required":false,"name":"event","default":""},{"type":"string","hint":"Optional event ID. Client sends Last-Event-ID header on reconnect.","required":false,"name":"id","default":""},{"type":"numeric","hint":"Optional reconnection time in milliseconds. Tells client how long to wait before reconnecting.","required":false,"name":"retry","default":0}],"name":"renderSSE","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"void","slug":"controller.renderText","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Render a simple text response to the client\nrenderText(&quot;Done!&quot;);\n\n// 2. Render serialized JSON data to the client\nproducts = model(&quot;Product&quot;).findAll();\nrenderText(serializeJSON(products));\n\n// 3. Render a plain-text response with a custom HTTP status code\nrenderText(text=&quot;Not authorized&quot;, status=401);\n</code></pre>","hasExtended":true},"hint":"Instructs the controller to render specified text when it's finished processing the action.\n\n","parameters":[{"type":"string","hint":"The text to render.","required":false,"name":"text","default":""},{"type":"any","hint":"Force request to return with specific HTTP status code.","required":false,"name":"status","default":"[runtime expression]"}],"name":"renderText","tags":{"category":"Rendering Functions","sectionClass":"controller","section":"Controller","categoryClass":"renderingfunctions"}},{"returntype":"any","slug":"controller.renderView","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Render the view template for a different action within the same controller.\nrenderView(action=&quot;edit&quot;);\n\n// 2. Render the view template for a different action within a different controller.\nrenderView(controller=&quot;blog&quot;, action=&quot;new&quot;);\n\n// 3. Render a specific template using an absolute path from the `views` folder.\nrenderView(template=&quot;/blog/new&quot;);\n\n// 4. Render without a layout and cache the output for 60 minutes.\nrenderView(layout=false, cache=60);\n\n// 5. Load a layout from a non-default folder within `views`.\nrenderView(layout=&quot;/layouts/blog&quot;);\n\n// 6. Return the rendered output as a string instead of sending it to the client.\nmyView = renderView(returnAs=&quot;string&quot;);\n\n// 7. Render with a specific HTTP status code (useful for error pages).\nrenderView(action=&quot;notFound&quot;, status=404);\n\n// 8. Render XML output and suppress debug information even when `showDebugInformation` is globally enabled.\nrenderView(template=&quot;/reports/summary&quot;, layout=false, hideDebugInformation=true);\n</code></pre>","hasExtended":true},"hint":"Instructs the controller which view template and layout to render when it's finished processing the action.\nNote that when passing values for controller and / or action, this function does not execute the actual action but rather just loads the corresponding view template.\n\n","parameters":[{"type":"string","hint":"Controller to include the view page for.","required":false,"name":"controller","default":"[runtime expression]"},{"type":"string","hint":"Action to include the view page for.","required":false,"name":"action","default":"[runtime expression]"},{"type":"string","hint":"A specific template to render. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder.","required":false,"name":"template","default":""},{"type":"any","hint":"The layout to wrap the content in. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder. Pass `false` to not load a layout at all.","required":false,"name":"layout","default":""},{"type":"any","hint":"Number of minutes to cache the content for.","required":false,"name":"cache","default":""},{"type":"string","hint":"Set to `string` to return the result instead of automatically sending it to the client.","required":false,"name":"returnAs","default":""},{"type":"boolean","hint":"Set to `true` to hide the debug information at the end of the output. This is useful, for example, when you're testing XML output in an environment where the global setting for `showDebugInformation` is `true`.","required":false,"name":"hideDebugInformation","default":false},{"type":"string","hint":"Force request to return with specific HTTP status code.","required":false,"name":"status","default":"[runtime expression]"}],"name":"renderView","tags":{"category":"Rendering Functions","sectionClass":"controller","section":"Controller","categoryClass":"renderingfunctions"}},{"returntype":"any","slug":"controller.renderWith","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Render a query using the format defined in the controller's `config()` function.\n// Wheels automatically serializes to JSON or XML when those formats are requested.\nproducts = model(&quot;Product&quot;).findAll();\nrenderWith(products);\n\n// 2. Return a JSON error payload with a specific HTTP status code.\nmsg = {\n\t&quot;status&quot;: &quot;Error&quot;,\n\t&quot;message&quot;: &quot;Not Authenticated&quot;\n};\nrenderWith(data=msg, status=403);\n\n// 3. Render a struct as JSON and return the result as a string instead of sending it to the client.\npayload = {&quot;id&quot;: 1, &quot;name&quot;: &quot;Alice&quot;};\njsonString = renderWith(data=payload, returnAs=&quot;string&quot;);\n\n// 4. Render with a custom XML template for the current action\n// (looks for a view file named `show.xml.cfm` in the current controller's views folder).\nuser = model(&quot;User&quot;).findByKey(params.key);\nrenderWith(data=user, layout=false, hideDebugInformation=true);\n\n// 5. Render data using a specific template from outside the current controller's views folder.\nreport = model(&quot;Order&quot;).findAll(select=&quot;id,total,createdAt&quot;);\nrenderWith(data=report, template=&quot;/reports/summary&quot;, layout=false);\n</code></pre>","hasExtended":true},"hint":"Instructs the controller to render the data passed in to the format that is requested.\nIf the format requested is <code>json</code> or <code>xml</code>, Wheels will transform the data into that format automatically.\nFor other formats (or to override the automatic formatting), you can also create a view template in this format: <code>nameofaction.xml.cfm</code>, <code>nameofaction.json.cfm</code>, <code>nameofaction.pdf.cfm</code>, etc.\nPer-action format restrictions set with <code>onlyProvides()</code> are enforced here (since 4.0.4):\nwhen the requested format is not acceptable for the action, <code>renderWith()</code> falls back to\nrendering the <code>html</code> view — even when <code>html</code> itself is not in the <code>onlyProvides()</code> list.\n\n","parameters":[{"type":"any","hint":"Data to format and render.","required":true,"name":"data"},{"type":"string","hint":"Controller to include the view page for.","required":false,"name":"controller","default":"[runtime expression]"},{"type":"string","hint":"Action to include the view page for.","required":false,"name":"action","default":"[runtime expression]"},{"type":"string","hint":"A specific template to render. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder.","required":false,"name":"template","default":""},{"type":"any","hint":"The layout to wrap the content in. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder. Pass `false` to not load a layout at all.","required":false,"name":"layout","default":""},{"type":"any","hint":"Number of minutes to cache the content for.","required":false,"name":"cache","default":""},{"type":"string","hint":"Set to `string` to return the result instead of automatically sending it to the client.","required":false,"name":"returnAs","default":""},{"type":"boolean","hint":"Set to `true` to hide the debug information at the end of the output. This is useful, for example, when you're testing XML output in an environment where the global setting for `showDebugInformation` is `true`.","required":false,"name":"hideDebugInformation","default":false},{"type":"string","hint":"Force request to return with specific HTTP status code.","required":false,"name":"status","default":"[runtime expression]"}],"name":"renderWith","tags":{"category":"Rendering Functions","sectionClass":"controller","section":"Controller","categoryClass":"renderingfunctions"}},{"returntype":"void","slug":"controller.resetCycle","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Reset the default cycle between grouped query sections\n&lt;cfoutput query=&quot;posts&quot; group=&quot;categoryId&quot;&gt;\n\tresetCycle();\n\t&lt;cfoutput&gt;\n\t\trowClass = cycle(values=&quot;even,odd&quot;);\n\t\twriteOutput(rowClass &amp; &quot;: &quot; &amp; posts.title);\n\t&lt;/cfoutput&gt;\n&lt;/cfoutput&gt;\n\n// 2. Reset a named cycle so it starts over for each department group\n&lt;cfoutput query=&quot;employees&quot; group=&quot;departmentId&quot;&gt;\n\tresetCycle(&quot;position&quot;);\n\t&lt;cfoutput&gt;\n\t\trank = cycle(values=&quot;manager,specialist,intern&quot;, name=&quot;position&quot;);\n\t\twriteOutput(employees.lastName &amp; &quot; - &quot; &amp; rank);\n\t&lt;/cfoutput&gt;\n&lt;/cfoutput&gt;\n\n// 3. Reset all cycles by name after rendering a section\nresetCycle(&quot;row&quot;);\nresetCycle(&quot;highlight&quot;);\n</code></pre>","hasExtended":true},"hint":"Resets a cycle so that it starts from the first list value the next time it is called.\n\n","parameters":[{"type":"string","hint":"The name of the cycle to reset.","required":false,"name":"name","default":"default"}],"name":"resetCycle","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"struct","slug":"mapper.resource","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Minimal singular resource — generates show, new, create, edit, update, delete routes\n    .resource(&quot;checkout&quot;)\n\n    // 2. Point to a controller at a custom path (app/controllers/sessions/Auth.cfc)\n    .resource(name=&quot;auth&quot;, controller=&quot;sessions/auth&quot;)\n\n    // 3. Limit generated routes with the `only` argument\n    .resource(name=&quot;profile&quot;, only=&quot;show,edit,update&quot;)\n\n    // 4. Exclude specific routes with the `except` argument\n    .resource(name=&quot;cart&quot;, except=&quot;new,create&quot;)\n\n    // 5. Nested singular resource — nest additional routes inside, then close with end()\n    .resource(name=&quot;preferences&quot;, nested=true)\n      .get(name=&quot;editPassword&quot;, to=&quot;passwords##edit&quot;)\n      .patch(name=&quot;password&quot;, to=&quot;passwords##update&quot;)\n      .resources(&quot;notifications&quot;)\n    .end()\n\n    // 6. Override the URL path (blogPostOptions -&gt; blog-post/options instead of blog-post-options)\n    .resource(name=&quot;blogPostOptions&quot;, path=&quot;blog-post/options&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Create a group of routes that exposes actions for manipulating a singular resource. A singular resource exposes URL patterns for the entire CRUD lifecycle of a single entity (<code>show</code>, <code>new</code>, <code>create</code>, <code>edit</code>, <code>update</code>, and <code>delete</code>) without exposing a primary key in the URL. Usually this type of resource represents a singleton entity tied to the session, application, or another resource (perhaps nested within another resource). If you need to generate routes for manipulating a collection of resources with a primary key in the URL, see the <code>resources</code> mapper method.\n\n","parameters":[{"type":"string","hint":"Camel-case name of resource to reference when build links and form actions. This is typically a singular word (e.g., `profile`).","required":true,"name":"name"},{"type":"boolean","hint":"Whether or not additional calls will be nested within this resource.","required":false,"name":"nested","default":false},{"type":"string","hint":"Override URL path representing this resource. Default is a dasherized version of `name` (e.g., `blogPost` generates a path of `blog-post`).","required":false,"name":"path","default":"[runtime expression]"},{"type":"string","hint":"Override name of the controller used by resource. This defaults to a pluralized version of `name`.","required":false,"name":"controller"},{"type":"string","hint":"Override singularize() result in plural resources.","required":false,"name":"singular"},{"type":"string","hint":"Override pluralize() result in singular resource.","required":false,"name":"plural"},{"type":"string","hint":"Limits the list of RESTful routes to generate. Can include `show`, `new`, `create`, `edit`, `update`, and `delete`.","required":false,"name":"only"},{"type":"string","hint":"Excludes RESTful routes to generate, taking priority over the `only` argument. Can include `show`, `new`, `create`, `edit,` `update`, and `delete`.","required":false,"name":"except"},{"type":"boolean","hint":"Turn on shallow resources.","required":false,"name":"shallow"},{"type":"string","hint":"Shallow path prefix.","required":false,"name":"shallowPath"},{"type":"string","hint":"Shallow name prefix.","required":false,"name":"shallowName"},{"type":"struct","hint":"Variable patterns to use for matching.","required":false,"name":"constraints"},{"type":"any","required":false,"name":"callback"},{"type":"any","required":false,"name":"binding"},{"type":"string","required":false,"name":"$call","default":"resource"},{"type":"boolean","required":false,"name":"$plural","default":false},{"type":"boolean","hint":"Whether or not to add an optional `.[format]` pattern to the end of the generated routes. This is useful for providing formats via URL like `json`, `xml`, `pdf`, etc.","required":false,"name":"mapFormat","default":"[runtime expression]"}],"name":"resource","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"mapper.resources","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Basic CRUD resource — generates index, show, new, create, edit, update, delete routes\n    .resources(&quot;admins&quot;)\n\n    // 2. Point authors URL to controller at `app/controllers/Users.cfc`\n    .resources(name=&quot;authors&quot;, controller=&quot;users&quot;)\n\n    // 3. Limit routes to a specific set with the `only` argument\n    .resources(name=&quot;products&quot;, only=&quot;index,show,edit,update&quot;)\n\n    // 4. Exclude specific routes using the `except` argument\n    .resources(name=&quot;orders&quot;, except=&quot;delete&quot;)\n\n    // 5. Nested resources — child routes receive parent key in URL (e.g. /stories/1/heroes)\n    .resources(name=&quot;stories&quot;, nested=true)\n        .resources(&quot;heroes&quot;)\n        .resources(&quot;villains&quot;)\n    .end()\n\n    // 6. Override the URL path (e.g. /blog-posts/options instead of /blog-posts-options)\n    .resources(name=&quot;blogPostsOptions&quot;, path=&quot;blog-posts/options&quot;)\n\n    // 7. Shallow nesting — member routes (show, edit, update, delete) drop the parent prefix\n    .resources(name=&quot;posts&quot;, nested=true, shallow=true)\n        .resources(&quot;comments&quot;)\n    .end()\n\n    // 8. Constrain URL parameters to a specific pattern (e.g. numeric IDs only)\n    .resources(name=&quot;photos&quot;, constraints={key=&quot;[0-9]+&quot;})\n\n    // 9. Override the singularized form when auto-detection is wrong\n    .resources(name=&quot;people&quot;, singular=&quot;person&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Create a group of routes that exposes actions for manipulating a collection of resources. A plural resource exposes URL patterns for the entire CRUD lifecycle (<code>index</code>, <code>show</code>, <code>new</code>, <code>create</code>, <code>edit</code>, <code>update</code>, <code>delete</code>), exposing a primary key in the URL for showing, editing, updating, and deleting records. If you need to generate routes for manipulating a singular resource without a primary key, see the <code>resource</code> mapper method.\n\n","parameters":[{"type":"string","hint":"Camel-case name of resource to reference when build links and form actions. This is typically a plural word (e.g., `posts`).","required":true,"name":"name"},{"type":"boolean","hint":"Whether or not additional calls will be nested within this resource.","required":false,"name":"nested","default":false},{"type":"string","hint":"Override URL path representing this resource. Default is a dasherized version of `name` (e.g., `blogPosts` generates a path of `blog-posts`).","required":false,"name":"path","default":"[runtime expression]"},{"type":"string","hint":"Override name of the controller used by resource. This defaults to the value provided for `name`.","required":false,"name":"controller"},{"type":"string","hint":"Override singularize() result in plural resources.","required":false,"name":"singular"},{"type":"string","hint":"Override pluralize() result in singular resource.","required":false,"name":"plural"},{"type":"string","hint":"Limits the list of RESTful routes to generate. Can include `index`, `show`, `new`, `create`, `edit`, `update`, and `delete`.","required":false,"name":"only"},{"type":"string","hint":"Excludes RESTful routes to generate, taking priority over the `only` argument. Can include `index`, `show`, `new`, `create`, `edit`, `update`, and `delete`.","required":false,"name":"except"},{"type":"boolean","hint":"Turn on shallow resources.","required":false,"name":"shallow"},{"type":"string","hint":"Shallow path prefix.","required":false,"name":"shallowPath"},{"type":"string","hint":"Shallow name prefix.","required":false,"name":"shallowName"},{"type":"struct","hint":"Variable patterns to use for matching.","required":false,"name":"constraints"},{"type":"any","required":false,"name":"callback"},{"type":"any","required":false,"name":"binding"},{"type":"boolean","hint":"Whether or not to add an optional `.[format]` pattern to the end of the generated routes. This is useful for providing formats via URL like `json`, `xml`, `pdf`, etc.","required":false,"name":"mapFormat","default":"[runtime expression]"}],"name":"resources","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.response","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the current response content (empty string if nothing has been rendered yet)\ncontent = response();\n\n// 2. Use in a controller test to verify rendered output\n// (Wheels populates the response after renderView, renderText, or renderPartial runs)\nrenderText(&quot;Hello, world!&quot;);\nassert(&quot;response() eq 'Hello, world!'&quot;);\n\n// 3. Inspect and modify the response before it is sent to the client\ncurrentContent = response();\nif (FindNoCase(&quot;&lt;!-- debug --&gt;&quot;, currentContent)) {\n    setResponse(Replace(currentContent, &quot;&lt;!-- debug --&gt;&quot;, &quot;&quot;, &quot;all&quot;));\n}\n</code></pre>","hasExtended":true},"hint":"Returns content that Wheels will send to the client in response to the request.\n\n","parameters":[],"name":"response","tags":{"category":"Rendering Functions","sectionClass":"controller","section":"Controller","categoryClass":"renderingfunctions"}},{"returntype":"struct","slug":"mapper.root","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\n// 1. Map the application's web root (home page) to a specific controller action\nmapper()\n    // Map &quot;/&quot; to the `index` action of the `home` controller\n    .root(to=&quot;home##index&quot;)\n.end();\n\n// 2. Map the root of a namespace scope using separate controller and action arguments\nmapper()\n    .namespace(&quot;admin&quot;)\n        // Map &quot;/admin/&quot; to the `dashboard` action of the `admin` controller\n        .root(controller=&quot;admin&quot;, action=&quot;dashboard&quot;)\n    .end()\n.end();\n\n// 3. Map the root with format matching enabled so &quot;.json&quot; etc. are captured\nmapper()\n    .namespace(&quot;api&quot;)\n        // Map &quot;/api/&quot; and &quot;/api/.json&quot; (etc.) to the `apis` controller's `index` action\n        .root(to=&quot;apis##index&quot;, mapFormat=true)\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Create a route that matches the root of its current context. This mapper can be used for the application's web root (or home page), or it can generate a route for the root of a namespace or other path scoping mapper. The route only responds to the <code>GET</code> verb unless you explicitly pass a <code>method</code> (or <code>methods</code>) argument.\n\n","parameters":[{"type":"string","hint":"Set `controller##action` combination to map the route to. You may use either this argument or a combination of `controller` and `action`.","required":false,"name":"to"},{"type":"boolean","hint":"Set to `true` to include the format (e.g. `.json`) in the route.","required":false,"name":"mapFormat"}],"name":"root","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"boolean","slug":"model.save","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Save a user object to the database (automatically does INSERT or UPDATE depending on whether the record is new)\nuser.save();\n\n// 2. Use save() in a conditional to handle success and failure\nif (user.save()) {\n\tflashInsert(notice=&quot;The user was saved successfully!&quot;);\n\tredirectTo(action=&quot;edit&quot;);\n} else {\n\tflashInsert(alert=&quot;Please correct the errors below.&quot;);\n\trenderView(action=&quot;edit&quot;);\n}\n\n// 3. Save without running validations (useful for administrative operations or data migrations)\nuser.save(validate=false);\n\n// 4. Save using cfqueryparam only on specific properties (pass a list of property names)\nuser.save(parameterize=&quot;firstName,lastName,email&quot;);\n\n// 5. Save and force a database reload of the object afterward (instead of using the request-level cache)\nuser.save(reload=true);\n</code></pre>","hasExtended":true},"hint":"Saves the object if it passes validation and callbacks.\nReturns <code>true</code> if the object was saved successfully to the database, <code>false</code> if not.\n\n","parameters":[{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"boolean","hint":"Set to `false` to skip validations for this operation.","required":false,"name":"validate","default":true},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":true}],"name":"save","tags":{"category":"CRUD Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"crudfunctions"}},{"returntype":"void","slug":"model.scope","availableIn":["model"],"extended":{"docs":"","hasExtended":false},"hint":"Defines a named query scope that can be chained onto finders.\nScopes allow you to define reusable query fragments in the model config and compose them together.\n\n","parameters":[{"type":"string","hint":"The name of the scope. This becomes a callable method on the model (e.g. `model(\"User\").active()`).","required":true,"name":"name"},{"type":"string","hint":"A `WHERE` clause fragment to apply when this scope is used.","required":false,"name":"where","default":""},{"type":"string","hint":"An `ORDER BY` clause fragment to apply when this scope is used.","required":false,"name":"order","default":""},{"type":"string","hint":"A `SELECT` clause override to apply when this scope is used.","required":false,"name":"select","default":""},{"type":"string","hint":"Associations to include when this scope is used.","required":false,"name":"include","default":""},{"type":"numeric","hint":"Maximum number of records to return when this scope is used.","required":false,"name":"maxRows","default":0},{"type":"string","hint":"The name of a method on this model that returns a struct of query arguments. Use for dynamic scopes that accept parameters. The method receives any arguments passed to the scope call.","required":false,"name":"handler","default":""}],"name":"scope","tags":{"category":"Scope Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"scopefunctions"}},{"returntype":"struct","slug":"mapper.scope","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Scope routes to a specific controller.\n    // All routes inside will use the `freeForAll` controller.\n    .scope(controller=&quot;freeForAll&quot;)\n        .get(name=&quot;bananas&quot;, action=&quot;bananas&quot;)\n        .root(action=&quot;index&quot;)\n    .end()\n\n    // 2. Scope routes to a package (subfolder) without affecting the URL.\n    // All routes' controllers inside will be inside the `public` package/subfolder.\n    .scope(package=&quot;public&quot;)\n        .resource(name=&quot;search&quot;, only=&quot;show,create&quot;)\n    .end()\n\n    // 3. Scope routes under a URL path prefix.\n    // All routes inside will be prepended with a URL path of `phones/`.\n    .scope(path=&quot;phones&quot;)\n        .get(name=&quot;newest&quot;, to=&quot;phones##newest&quot;)\n        .get(name=&quot;sortOfNew&quot;, to=&quot;phones##sortOfNew&quot;)\n    .end()\n\n    // 4. Scope routes with both a name prefix and URL path prefix.\n    // Generates named routes like `adminUsers` and `adminPosts`.\n    .scope(name=&quot;admin&quot;, path=&quot;admin&quot;)\n        .resources(name=&quot;users&quot;)\n        .resources(name=&quot;posts&quot;)\n    .end()\n\n    // 5. Scope routes with URL variable constraints applied to all children.\n    .scope(constraints={id=&quot;[0-9]+&quot;})\n        .get(name=&quot;userProfile&quot;, to=&quot;users##profile&quot;)\n        .resources(name=&quot;orders&quot;)\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Set any number of parameters to be inherited by mappers called within this matcher's block. For example, set a package or URL path to be used by all child routes.\n\n","parameters":[{"type":"string","hint":"Name to prepend to child route names for use when building links, forms, and other URLs.","required":false,"name":"name"},{"type":"string","hint":"Path to prefix to all child routes.","required":false,"name":"path"},{"type":"string","hint":"Package namespace to append to controllers.","required":false,"name":"package"},{"type":"string","hint":"Controller to use for routes.","required":false,"name":"controller"},{"type":"boolean","hint":"Turn on shallow resources to eliminate routing added before this one.","required":false,"name":"shallow"},{"type":"string","hint":"Shallow path prefix.","required":false,"name":"shallowPath"},{"type":"string","hint":"Shallow name prefix.","required":false,"name":"shallowName"},{"type":"struct","hint":"Variable patterns to use for matching.","required":false,"name":"constraints"},{"type":"any","required":false,"name":"middleware"},{"type":"any","required":false,"name":"binding"},{"type":"any","hint":"A callback function to define nested routes within this scope. If provided, the scope is automatically closed when the callback completes.","required":false,"name":"callback"},{"type":"string","required":false,"name":"$call","default":"scope"}],"name":"scope","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"model.scopeInfo","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Inspect all named scopes defined on a model\ninfo = model(&quot;Article&quot;).scopeInfo();\n// info -&gt; {\n//   active:    { where: &quot;status = 'active'&quot; },\n//   recent:    { where: &quot;publishedAt &gt; ?&quot;, order: &quot;publishedAt DESC&quot; },\n//   published: { where: &quot;status = 'published'&quot;, order: &quot;publishedAt DESC&quot; }\n// }\n\n// 2. Check whether a specific scope is defined before using it\ninfo = model(&quot;User&quot;).scopeInfo();\nif (structKeyExists(info, &quot;admins&quot;)) {\n    admins = model(&quot;User&quot;).admins().findAll();\n}\n\n// 3. List all scope names registered on a model\ninfo = model(&quot;Post&quot;).scopeInfo();\nwriteOutput(structKeyList(info));\n// -&gt; &quot;featured,archived,byDate&quot;\n</code></pre>","hasExtended":true},"hint":"Returns a struct containing all named scope definitions for this model.\nEach key is the scope name, and the value is a struct with query fragment keys like <code>where</code>, <code>order</code>, <code>select</code>, <code>include</code>.\n\n","parameters":[],"name":"scopeInfo","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.searchField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic search field bound to a model object\n#searchField(objectName=&quot;searchForm&quot;, property=&quot;query&quot;)#\n\n// 2. Search field with a custom label and placeholder attribute\n#searchField(objectName=&quot;searchForm&quot;, property=&quot;query&quot;, label=&quot;Search&quot;, placeholder=&quot;Enter keywords...&quot;)#\n\n// 3. Search field with label placement after the input and a CSS class\n#searchField(objectName=&quot;searchForm&quot;, property=&quot;query&quot;, label=&quot;Search&quot;, labelPlacement=&quot;after&quot;, class=&quot;search-input&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a search field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"searchField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.searchFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic search field with a label and pre-populated value\n#searchFieldTag(name=&quot;q&quot;, value=params.q, label=&quot;Search&quot;)#\n\n// 2. Search field with a placeholder and CSS class (extra HTML attributes are passed through)\n#searchFieldTag(name=&quot;keywords&quot;, label=&quot;Keywords&quot;, placeholder=&quot;Enter keywords...&quot;, class=&quot;search-input&quot;)#\n\n// 3. Search field without a label, value carried from params\n#searchFieldTag(name=&quot;q&quot;, value=params.q)#</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a search field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"searchFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.secondSelectTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage — render a seconds select for a countdown form\n#secondSelectTag(name=&quot;secondsToLaunch&quot;, selected=params.secondsToLaunch)#\n\n// 2. Only show 15-second intervals (0, 15, 30, 45)\n#secondSelectTag(name=&quot;secondsToLaunch&quot;, selected=params.secondsToLaunch, secondStep=15)#\n\n// 3. Include a blank option and wrap with a label\n#secondSelectTag(name=&quot;second&quot;, selected=params.second, includeBlank=true, label=&quot;Second&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing one <code>select</code> form control for the seconds of a minute based on the supplied name.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"The second that should be selected initially.","required":false,"name":"selected","default":""},{"type":"numeric","hint":"Pass in 10 to only show seconds 10, 20, 30, etc.","required":false,"name":"secondStep","default":1},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"date","required":false,"name":"$now","default":"[runtime expression]"}],"name":"secondSelectTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"boolean","slug":"controller.sectionActive","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Une section du site est-elle active ?\nValeur par defaut VRAIE : si l'API ne repond pas, on montre le site plutot\nque de le vider. Un reglage manquant ne doit pas faire disparaitre le\ncontenu.","parameters":[{"type":"string","required":true,"name":"code"}],"name":"sectionActive","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"string","slug":"controller.select","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic select field bound to a model object property\n// Controller\nauthors = model(&quot;Author&quot;).findAll(order=&quot;lastName&quot;);\n// View\n#select(objectName=&quot;book&quot;, property=&quot;authorId&quot;, options=authors)#\n\n// 2. Override which query columns to use for option values and display text\n// Controller\nauthors = model(&quot;Author&quot;).findAll(order=&quot;lastName&quot;);\n// View\n#select(objectName=&quot;book&quot;, property=&quot;authorId&quot;, options=authors, valueField=&quot;id&quot;, textField=&quot;fullName&quot;)#\n\n// 3. Include a blank/placeholder option at the top of the list\n#select(objectName=&quot;order&quot;, property=&quot;statusId&quot;, options=statuses, includeBlank=&quot;-- Select a Status --&quot;)#\n\n// 4. Populate options from a simple list or array instead of a query\n#select(objectName=&quot;profile&quot;, property=&quot;country&quot;, options=&quot;Canada,Mexico,United States&quot;)#\n\n// 5. Allow multiple selections (multi-select box)\n#select(objectName=&quot;post&quot;, property=&quot;tagIds&quot;, options=tags, multiple=true, label=&quot;Tags&quot;)#\n\n// 6. Nested form — select within a hasMany association loop\n// Controller\nshipment = model(&quot;Shipment&quot;).findByKey(params.key, include=&quot;orders&quot;);\nstatuses = model(&quot;Status&quot;).findAll(order=&quot;name&quot;);\n// View\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(shipment.orders)#&quot; index=&quot;i&quot;&gt;\n    #select(\n        label        = &quot;Order ##shipment.orders[i].orderNumber##&quot;,\n        objectName   = &quot;shipment&quot;,\n        association  = &quot;orders&quot;,\n        position     = i,\n        property     = &quot;statusId&quot;,\n        options      = statuses,\n        includeBlank = true\n    )#\n&lt;/cfloop&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a select form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"any","hint":"A collection to populate the select form control with. Can be a query recordSet or an array of objects.","required":false,"name":"options"},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The column or property to use for the value of each list element. Used only when a query or array of objects has been supplied in the options argument.  Required when specifying `textField`","required":false,"name":"valueField","default":""},{"type":"string","hint":"The column or property to use for the value of each list element that the end user will see. Used only when a query or array of objects has been supplied in the options argument. Required when specifying `valueField`","required":false,"name":"textField","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"select","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.selectTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage with a simple list of options\n#selectTag(name=&quot;color&quot;, options=&quot;Red,Green,Blue&quot;)#\n\n// 2. Use a query as the options source, specifying which columns map to value and display text\ncities = model(&quot;City&quot;).findAll(order=&quot;name&quot;);\n#selectTag(name=&quot;cityId&quot;, options=cities, valueField=&quot;id&quot;, textField=&quot;name&quot;)#\n\n// 3. Pre-select a value and include a blank &quot;please choose&quot; option\n#selectTag(name=&quot;cityId&quot;, options=cities, valueField=&quot;id&quot;, textField=&quot;name&quot;, selected=params.cityId, includeBlank=&quot;- Select a City -&quot;)#\n\n// 4. Allow multiple selections\n#selectTag(name=&quot;tagIds&quot;, options=model(&quot;Tag&quot;).findAll(order=&quot;name&quot;), valueField=&quot;id&quot;, textField=&quot;name&quot;, multiple=true)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a select form control based on the supplied name and options.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"any","hint":"A collection to populate the select form control with. Can be a query recordSet or an array of objects.","required":true,"name":"options"},{"type":"string","hint":"Value of option that should be selected by default.","required":false,"name":"selected","default":""},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"boolean","hint":"Whether to allow multiple selection of options in the select form control.","required":false,"name":"multiple","default":false},{"type":"string","hint":"The column or property to use for the value of each list element. Used only when a query or array of objects has been supplied in the options argument.  Required when specifying `textField`","required":false,"name":"valueField","default":""},{"type":"string","hint":"The column or property to use for the value of each list element that the end user will see. Used only when a query or array of objects has been supplied in the options argument. Required when specifying `valueField`","required":false,"name":"textField","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"selectTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"any","slug":"controller.sendEmail","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Send a welcome email to a new member, passing custom variables to the template\nnewMember = model(&quot;Member&quot;).findByKey(params.member.id);\nsendEmail(\n\tfrom=&quot;welcome@example.com&quot;,\n\tto=newMember.email,\n\tsubject=&quot;Thank You for Becoming a Member&quot;,\n\ttemplate=&quot;welcomeEmail&quot;,\n\trecipientName=newMember.name,\n\tstartDate=newMember.startDate\n);\n\n// 2. Send a multipart email (text + HTML) using two templates\nsendEmail(\n\tfrom=&quot;news@example.com&quot;,\n\tto=params.subscriber.email,\n\tsubject=&quot;Your Weekly Newsletter&quot;,\n\ttemplate=&quot;newsletterText,newsletterHtml&quot;,\n\tlayout=false,\n\tissueDate=Now()\n);\n\n// 3. Send an email with a file attachment and suppress actual delivery (e.g. during testing)\nsendEmail(\n\tfrom=&quot;billing@example.com&quot;,\n\tto=params.customer.email,\n\tsubject=&quot;Your Invoice&quot;,\n\ttemplate=&quot;invoiceEmail&quot;,\n\tfile=&quot;invoice_2024.pdf&quot;,\n\tdeliver=false\n);\n</code></pre>","hasExtended":true},"hint":"Sends an email using a template and an optional layout to wrap it in.\nBesides the Wheels-specific arguments documented here, you can also pass in any argument that is accepted by the <code>cfmail</code> tag as well as your own arguments to be used by the view.\nNote that only arguments whose names match a known <code>cfmail</code> attribute are passed through to <code>cfmail</code>; every other argument is made available to the email view as a variable instead.\n\n","parameters":[{"type":"string","hint":"The path to the email template or two paths if you want to send a multipart email (a maximum of two templates, one text and one html version, is supported). if the `detectMultipart` argument is `false`, the template for the text version should be the first one in the list. This argument is also aliased as `templates`.","required":false,"name":"template","default":""},{"type":"string","hint":"Email address to send from.","required":true,"name":"from","default":""},{"type":"string","hint":"List of email addresses to send the email to.","required":true,"name":"to","default":""},{"type":"string","hint":"The subject line of the email.","required":true,"name":"subject","default":""},{"type":"any","hint":"Layout(s) to wrap the email template in. This argument is also aliased as `layouts`.","required":false,"name":"layout","default":false},{"type":"string","hint":"A list of the names of the files to attach to the email. This will reference files stored in the `files` folder (or a path relative to it). This argument is also aliased as `files`.","required":false,"name":"file","default":""},{"type":"boolean","hint":"When set to `true` and multiple values are provided for the `template` argument, Wheels will detect which of the templates is text and which one is HTML (by counting the `<` characters).","required":false,"name":"detectMultipart","default":true},{"type":"boolean","hint":"When set to `false`, the email will not be sent.","required":false,"name":"deliver","default":true},{"type":"string","hint":"The file to which the email contents will be written","required":false,"name":"writeToFile","default":""}],"name":"sendEmail","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"controller.sendFile","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Send a PDF file to the user from the default files folder\nsendFile(file=&quot;wheels_tutorial_20081028_J657D6HX.pdf&quot;);\n\n// 2. Send the same file but give the user a friendlier name in the browser download dialog\nsendFile(file=&quot;wheels_tutorial_20081028_J657D6HX.pdf&quot;, name=&quot;Tutorial.pdf&quot;);\n\n// 3. Display the file inline in the browser instead of forcing a download dialog\nsendFile(file=&quot;report.pdf&quot;, disposition=&quot;inline&quot;);\n\n// 4. Send a file with an explicit MIME type\nsendFile(file=&quot;export.csv&quot;, type=&quot;text/csv&quot;, name=&quot;data-export.csv&quot;);\n\n// 5. Send a file located outside of the web root using an absolute directory path\nsendFile(file=&quot;invoice_2024_001.pdf&quot;, directory=&quot;/var/app/private/invoices&quot;);\n\n// 6. Send a file and delete it from the server after delivery (e.g., a temporary export)\nsendFile(file=&quot;temp_export_J657D6HX.csv&quot;, name=&quot;export.csv&quot;, deleteFile=true);\n\n// 7. Send a file stored in the RAM virtual file system\nsendFile(file=&quot;ram://generated_report.pdf&quot;, name=&quot;report.pdf&quot;);\n</code></pre>","hasExtended":true},"hint":"Sends a file to the user (from the <code>files</code> folder or a path relative to it by default).\n\n","parameters":[{"type":"string","hint":"The file to send to the user. Values containing the `..` character sequence anywhere (even as part of a legitimate file name) are rejected to prevent path traversal.","required":true,"name":"file"},{"type":"string","hint":"The file name to show in the browser download dialog box.","required":false,"name":"name","default":""},{"type":"string","hint":"The HTTP content type to deliver the file as.","required":false,"name":"type","default":""},{"type":"string","hint":"Set to `inline` to have the browser handle the opening of the file (possibly inline in the browser) or set to `attachment` to force a download dialog box.","required":false,"name":"disposition","default":"attachment"},{"type":"string","hint":"Directory outside of the web root where the file exists. Must be a full path. Values containing the `..` character sequence are rejected to prevent path traversal.","required":false,"name":"directory","default":""},{"type":"boolean","hint":"Pass in `true` to delete the file on the server after sending it.","required":false,"name":"deleteFile","default":false},{"type":"boolean","hint":"When set to `false`, the file will not be sent to the browser (used for testing).","required":false,"name":"deliver","default":true}],"name":"sendFile","tags":{"category":"Miscellaneous Functions","sectionClass":"controller","section":"Controller","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"controller.sendSSEComment","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Send an SSE comment (keep-alive ping) through a streaming writer.","parameters":[{"type":"any","hint":"The writer object returned by initSSEStream().","required":true,"name":"writer"},{"type":"string","hint":"Optional comment text.","required":false,"name":"comment","default":"ping"}],"name":"sendSSEComment","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"void","slug":"controller.sendSSEEvent","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Send an SSE event through a streaming writer obtained from initSSEStream().","parameters":[{"type":"any","hint":"The writer object returned by initSSEStream().","required":true,"name":"writer"},{"type":"string","hint":"The event data to send.","required":true,"name":"data"},{"type":"string","hint":"Optional event type name.","required":false,"name":"event","default":""},{"type":"string","hint":"Optional event ID.","required":false,"name":"id","default":""},{"type":"numeric","hint":"Optional reconnection time in milliseconds.","required":false,"name":"retry","default":0}],"name":"sendSSEEvent","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"any","slug":"controller.service","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Resolve a registered service and call a method on it\nmailer = service(&quot;MailerService&quot;);\nmailer.send(to=&quot;user@example.com&quot;, subject=&quot;Welcome!&quot;);\n\n// 2. Resolve a payment gateway service and process a charge\ngateway = service(&quot;PaymentGateway&quot;);\nresult = gateway.charge(amount=params.amount, token=params.stripeToken);\n\n// 3. Use a service in a model callback to send a notification\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        afterCreate(method=&quot;notifyAdmin&quot;);\n    }\n\n    private function notifyAdmin() {\n        notifier = service(&quot;NotificationService&quot;);\n        notifier.notify(event=&quot;userCreated&quot;, userId=this.id);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Resout un composant de la couche de services du front.\nMeme principe que dans l'API, en plus simple : le front n'a aucun modele,\ndonc rien a injecter que la configuration. Un service ne connait ni\n<code>params</code>, ni les entetes.\nCache de portee REQUETE : le contrat (§8) interdit de compter sur un etat\nen memoire entre requetes.","parameters":[{"type":"string","required":true,"name":"name"}],"name":"service","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"void","slug":"controller.set","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Set the `URLRewriting` global setting to `Partial`.\nset(URLRewriting=&quot;Partial&quot;);\n\n// 2. Set default argument values for the `buttonTo` view helper.\n// This pattern works for most Wheels helper functions and their arguments.\nset(functionName=&quot;buttonTo&quot;, onlyPath=true, host=&quot;&quot;, protocol=&quot;&quot;, port=0, text=&quot;&quot;, confirm=&quot;&quot;, image=&quot;&quot;, disable=&quot;&quot;);\n\n// 3. Set default values for the `textField` form helper to control label placement and wrapping markup.\nset(functionName=&quot;textField&quot;, labelPlacement=&quot;before&quot;, prependToLabel=&quot;&lt;div&gt;&quot;, append=&quot;&lt;/div&gt;&quot;, appendToLabel=&quot;&lt;br&gt;&quot;);\n\n// 4. Apply the same defaults to multiple helper functions at once by passing a comma-delimited list to `functionName`.\nset(functionName=&quot;textField,passwordField,textArea&quot;, labelPlacement=&quot;before&quot;);\n</code></pre>","hasExtended":true},"hint":"Use to configure a global setting or set a default for a function.\n\n","parameters":[],"name":"set","tags":{"category":"Miscellaneous Functions","sectionClass":"configuration","section":"Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"controller.setFilterChain","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Set the entire filter chain directly using an array of structs\nsetFilterChain([\n\t{through=&quot;restrictAccess&quot;},\n\t{through=&quot;isLoggedIn, checkIPAddress&quot;, except=&quot;home, login&quot;},\n\t{type=&quot;after&quot;, through=&quot;logConversion&quot;, only=&quot;thankYou&quot;}\n]);\n\n// 2. Replace an inherited filter chain in a child controller by starting fresh\n// In app/controllers/Admin.cfc config():\nparentChain = filterChain();\n// Modify parentChain as needed, then reassign it wholesale\nsetFilterChain([\n\t{through=&quot;requireAdmin&quot;},\n\t{through=&quot;loadCurrentUser&quot;, except=&quot;login&quot;},\n\t{type=&quot;after&quot;, through=&quot;auditAction&quot;}\n]);\n\n// 3. Conditionally swap the filter chain based on application mode\nif (get(&quot;environment&quot;) == &quot;testing&quot;) {\n\tsetFilterChain([\n\t\t{through=&quot;stubAuthentication&quot;}\n\t]);\n} else {\n\tsetFilterChain([\n\t\t{through=&quot;requireSSL&quot;},\n\t\t{through=&quot;authenticate&quot;},\n\t\t{type=&quot;after&quot;, through=&quot;trackPageView&quot;}\n\t]);\n}\n</code></pre>","hasExtended":true},"hint":"Use this function if you need a more low level way of setting the entire filter chain for a controller.\n\n","parameters":[{"type":"array","hint":"An array of structs, each of which represent an `argumentCollection` that get passed to the `filters` function. This should represent the entire filter chain that you want to use for this controller.","required":true,"name":"chain"}],"name":"setFilterChain","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"void","slug":"controller.setFlashStorage","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Switch flash storage to cookie for the current request only\nsetFlashStorage(storage=&quot;cookie&quot;);\nflashInsert(notice=&quot;Switching to cookie-based flash.&quot;);\n\n// 2. Switch flash storage to session (the default) for the current request only\nsetFlashStorage(storage=&quot;session&quot;);\n\n// 3. Update flash storage globally so all subsequent requests also use cookie storage\nsetFlashStorage(storage=&quot;cookie&quot;, setGlobally=true);\n</code></pre>","hasExtended":true},"hint":"Dynamically sets flashStorage during request lifecycle.\n\n","parameters":[{"type":"string","hint":"Accepts \"session\" or \"cookie\"","required":false,"name":"storage","default":"session"},{"type":"boolean","hint":"If true, updates both app-level and controller-level flashStorage","required":false,"name":"setGlobally","default":false}],"name":"setFlashStorage","tags":{"category":"Flash Functions","sectionClass":"controller","section":"Controller","categoryClass":"flashfunctions"}},{"returntype":"void","slug":"controller.setPagination","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage: paginate a custom query inside a model method, letting the CFML engine handle pagination\n// In app/models/User.cfc\nfunction searchByName(required string name, numeric page = 1, numeric perPage = 25) {\n\tlocal.allMatches = QueryExecute(\n\t\t&quot;SELECT * FROM users WHERE firstName LIKE :name ORDER BY lastName&quot;,\n\t\t{ name = { value = &quot;%&quot; &amp; arguments.name &amp; &quot;%&quot;, cfsqltype = &quot;cf_sql_varchar&quot; } },\n\t\t{ datasource = get(&quot;dataSourceName&quot;) }\n\t);\n\tsetPagination(\n\t\ttotalRecords = local.allMatches.recordCount,\n\t\tcurrentPage  = arguments.page,\n\t\tperPage      = arguments.perPage,\n\t\thandle       = &quot;userSearch&quot;\n\t);\n\treturn local.allMatches;\n}\n\n// In app/controllers/Users.cfc\nfunction search() {\n\tparam name=&quot;params.page&quot;    default=&quot;1&quot;;\n\tparam name=&quot;params.perPage&quot; default=&quot;25&quot;;\n\tsearchResults = model(&quot;User&quot;).searchByName(\n\t\tname    = params.q,\n\t\tpage    = params.page,\n\t\tperPage = params.perPage\n\t);\n\tpaginationData = pagination(&quot;userSearch&quot;);\n}\n\n&lt;!--- In app/views/users/search.cfm ---&gt;\n&lt;!--- Use startRow / endRow to page through the full query result ---&gt;\n&lt;ul&gt;\n\t&lt;cfloop query=&quot;searchResults&quot;\n\t        startRow=&quot;#paginationData.startRow#&quot;\n\t        endRow=&quot;#paginationData.endRow#&quot;&gt;\n\t\t&lt;li&gt;#searchResults.firstName# #searchResults.lastName#&lt;/li&gt;\n\t&lt;/cfloop&gt;\n&lt;/ul&gt;\n#paginationLinks(handle=&quot;userSearch&quot;)#\n\n// 2. Database-level pagination: run a COUNT query and a page-slice query separately\n// In app/models/Article.cfc\nfunction pagedResults(numeric page = 1, numeric perPage = 10) {\n\tlocal.countQuery = QueryExecute(\n\t\t&quot;SELECT COUNT(*) AS total FROM articles WHERE publishedAt IS NOT NULL&quot;,\n\t\t[],\n\t\t{ datasource = get(&quot;dataSourceName&quot;) }\n\t);\n\tlocal.pageQuery = QueryExecute(\n\t\t&quot;SELECT * FROM articles WHERE publishedAt IS NOT NULL ORDER BY publishedAt DESC LIMIT :perPage OFFSET :offset&quot;,\n\t\t{\n\t\t\tperPage = { value = arguments.perPage, cfsqltype = &quot;cf_sql_integer&quot; },\n\t\t\toffset  = { value = (arguments.page - 1) * arguments.perPage, cfsqltype = &quot;cf_sql_integer&quot; }\n\t\t},\n\t\t{ datasource = get(&quot;dataSourceName&quot;) }\n\t);\n\t// Use the COUNT result so paginationLinks reflects the total, not just this page\n\tsetPagination(\n\t\ttotalRecords = local.countQuery.total,\n\t\tcurrentPage  = arguments.page,\n\t\tperPage      = arguments.perPage,\n\t\thandle       = &quot;articles&quot;\n\t);\n\treturn local.pageQuery;\n}\n\n// In app/controllers/Articles.cfc\nfunction index() {\n\tparam name=&quot;params.page&quot;    default=&quot;1&quot;;\n\tparam name=&quot;params.perPage&quot; default=&quot;10&quot;;\n\tarticles = model(&quot;Article&quot;).pagedResults(\n\t\tpage    = params.page,\n\t\tperPage = params.perPage\n\t);\n}\n\n&lt;!--- In app/views/articles/index.cfm ---&gt;\n&lt;ul&gt;\n\t&lt;cfloop query=&quot;articles&quot;&gt;\n\t\t&lt;li&gt;#articles.title#&lt;/li&gt;\n\t&lt;/cfloop&gt;\n&lt;/ul&gt;\n#paginationLinks(handle=&quot;articles&quot;)#\n\n// 3. Use the default handle name so paginationLinks() needs no handle argument\n// In app/models/Product.cfc\nfunction featured(numeric page = 1) {\n\tlocal.q = QueryExecute(\n\t\t&quot;SELECT * FROM products WHERE featured = 1 ORDER BY name&quot;,\n\t\t[],\n\t\t{ datasource = get(&quot;dataSourceName&quot;) }\n\t);\n\t// Omitting handle defaults it to &quot;query&quot;, matching paginationLinks() default\n\tsetPagination(totalRecords = local.q.recordCount, currentPage = arguments.page);\n\treturn local.q;\n}\n\n// In app/controllers/Products.cfc\nfunction index() {\n\tparam name=&quot;params.page&quot; default=&quot;1&quot;;\n\tproducts     = model(&quot;Product&quot;).featured(page = params.page);\n\tpagingData   = pagination(); // uses default handle &quot;query&quot;\n}\n\n&lt;!--- In app/views/products/index.cfm ---&gt;\n&lt;ul&gt;\n\t&lt;cfloop query=&quot;products&quot;\n\t        startRow=&quot;#pagingData.startRow#&quot;\n\t        endRow=&quot;#pagingData.endRow#&quot;&gt;\n\t\t&lt;li&gt;#products.name#&lt;/li&gt;\n\t&lt;/cfloop&gt;\n&lt;/ul&gt;\n#paginationLinks()#\n</code></pre>","hasExtended":true},"hint":"Allows you to set a pagination handle for a custom query so you can perform pagination on it in your view with <code>paginationLinks</code>.\n\n","parameters":[{"type":"numeric","hint":"Total count of records that should be represented by the paginated links.","required":true,"name":"totalRecords"},{"type":"numeric","hint":"Page number that should be represented by the data being fetched and the paginated links.","required":false,"name":"currentPage","default":1},{"type":"numeric","hint":"Number of records that should be represented on each page of data.","required":false,"name":"perPage","default":25},{"type":"string","hint":"Name of handle to reference in `paginationLinks`.","required":false,"name":"handle","default":"query"}],"name":"setPagination","tags":{"category":"Pagination Functions","sectionClass":"controller","section":"Controller","categoryClass":"paginationfunctions"}},{"returntype":"void","slug":"model.setPrimaryKey","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. In `models/User.cfc`, define the primary key as a column called `userID`\n//    instead of the Wheels default of `id`.\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tsetPrimaryKey(&quot;userID&quot;);\n\t}\n}\n\n// 2. Define a composite primary key for a join model using two columns.\n//    `setPrimaryKeys()` is an alias for `setPrimaryKey()` that reads more\n//    naturally when multiple properties are involved.\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\ttable(&quot;users_roles&quot;);\n\t\tsetPrimaryKeys(&quot;userID,roleID&quot;);\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Allows you to pass in the name(s) of the property(s) that should be used as the primary key(s).\nPass as a list if defining a composite primary key.\nThis function is also aliased as <code>setPrimaryKeys()</code>.\n\n","parameters":[{"type":"string","hint":"Property (or list of properties) to set as the primary key.","required":true,"name":"property"}],"name":"setPrimaryKey","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"model.setPrimaryKeys","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. In `models/Subscription.cfc`, define the primary key as a composite of `customerId` and `publicationId`.\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tsetPrimaryKeys(&quot;customerId,publicationId&quot;);\n\t}\n}\n\n// 2. In `models/OrderItem.cfc`, define a composite primary key using three columns.\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tsetPrimaryKeys(&quot;orderId,productId,warehouseId&quot;);\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Alias for <code>setPrimaryKey()</code>.\nUse this for better readability when you're setting multiple properties as the primary key.\n\n","parameters":[{"type":"string","hint":"Property (or list of properties) to set as the primary key.","required":true,"name":"property"}],"name":"setPrimaryKeys","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"model.setProperties","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Update properties from a form post struct\nuser = model(&quot;User&quot;).findByKey(1);\nuser.setProperties(params.user);\n\n// 2. Pass a struct literal directly to set multiple properties at once\nuser = model(&quot;User&quot;).findByKey(1);\nuser.setProperties({firstName: &quot;Jane&quot;, lastName: &quot;Doe&quot;, email: &quot;jane@example.com&quot;});\nuser.save();\n\n// 3. Use named arguments instead of a struct (named args are merged with the properties struct)\nuser = model(&quot;User&quot;).findByKey(1);\nuser.setProperties(firstName=&quot;John&quot;, lastName=&quot;Smith&quot;);\nuser.save();\n</code></pre>","hasExtended":true},"hint":"Allows you to set all the properties of an object at once by passing in a structure with keys matching the property names.\n\n","parameters":[{"type":"struct","hint":"The properties you want to set on the object (can also be passed in as named arguments).","required":false,"name":"properties","default":"[runtime expression]"}],"name":"setProperties","tags":{"category":"Miscellaneous Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"controller.setResponse","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Override the response body with a plain string\nsetResponse(&quot;Maintenance mode active. Please try again later.&quot;);\n\n// 2. Modify an already-rendered response in an after filter\n// (e.g. append a debug comment to every HTML response)\nprivate void function appendDebugComment() {\n    current = response();\n    setResponse(current &amp; &quot;&lt;!-- rendered at #Now()# --&gt;&quot;);\n}\n\n// 3. Replace the response with serialized data after a renderView() call\n// (useful in tests or custom middleware-style filters)\nsetResponse(serializeJSON({status: &quot;ok&quot;, timestamp: Now()}));\n</code></pre>","hasExtended":true},"hint":"Sets content that Wheels will send to the client in response to the request.\n\n","parameters":[{"type":"string","hint":"The content to send to the client.","required":true,"name":"content"}],"name":"setResponse","tags":{"category":"Rendering Functions","sectionClass":"controller","section":"Controller","categoryClass":"renderingfunctions"}},{"returntype":"void","slug":"model.setTableNamePrefix","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. In `models/User.cfc`, prepend `tbl` to the default table name so\n//    Wheels queries the `tblusers` table instead of `users`.\nfunction config() {\n\tsetTableNamePrefix(&quot;tbl&quot;);\n}\n\n// 2. Use a schema-style prefix to namespace legacy tables shared across\n//    multiple applications on the same database.\n// models/Order.cfc\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tsetTableNamePrefix(&quot;legacy_&quot;);\n\t\t// Wheels will now query `legacy_orders` for this model.\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Sets a prefix to prepend to the table name when this model runs SQL queries.\n\n","parameters":[{"type":"string","hint":"A prefix to prepend to the table name.","required":true,"name":"prefix"}],"name":"setTableNamePrefix","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"controller.setVerificationChain","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Set the entire verification chain directly using an array of structs\nsetVerificationChain([\n\t{only=&quot;handleForm&quot;, post=true},\n\t{only=&quot;edit&quot;, get=true, params=&quot;userId&quot;, paramsTypes=&quot;integer&quot;},\n\t{only=&quot;delete&quot;, post=true, session=&quot;currentUser&quot;, handler=&quot;accessDenied&quot;}\n]);\n\n// 2. Get the existing chain, modify it, and set it back\nchain = verificationChain();\nArrayAppend(chain, {only=&quot;create,update&quot;, post=true});\nsetVerificationChain(chain);\n\n// 3. Replace the chain built by a parent controller with a stricter one\nsetVerificationChain([\n\t{except=&quot;index,show&quot;, post=true, session=&quot;isAdmin&quot;, handler=&quot;requireAdmin&quot;},\n\t{only=&quot;destroy&quot;, post=true}\n]);\n</code></pre>","hasExtended":true},"hint":"Use this function if you need a more low level way of setting the entire verification chain for a controller.\n\n","parameters":[{"type":"array","hint":"An array of structs, each of which represent an `argumentCollection` that get passed to the `verifies` function. This should represent the entire verification chain that you want to use for this controller.","required":true,"name":"chain"}],"name":"setVerificationChain","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"void","slug":"model.sharedModel","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Mark the Tenant model as shared so it always reads from the central database\n// models/Tenant.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        sharedModel();\n    }\n}\n\n// 2. Use sharedModel() for lookup tables that live in the central database,\n//    not in per-tenant databases\n// models/Plan.cfc\ncomponent extends=&quot;Model&quot; {\n    function config() {\n        sharedModel();\n        // All finder calls on Plan will use the default application datasource\n        // regardless of which tenant is currently active.\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Marks this model as shared — it will always use the default application datasource\neven when a tenant is active. Use this for models like <code>Tenant</code>, <code>Plan</code>, or any\nlookup table that lives in the central database rather than per-tenant databases.\n\n","parameters":[],"name":"sharedModel","tags":{"category":"Multi-Tenancy","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"multi-tenancy"}},{"returntype":"string","slug":"controller.simpleFormat","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Format a blog post body — newlines become &lt;br&gt; and blank lines become paragraph breaks\nwriteOutput(simpleFormat(post.bodyText));\n// A single newline becomes &lt;br&gt;\n// A blank line (two newlines) becomes &lt;/p&gt;&lt;p&gt;\n// The result is wrapped in &lt;p&gt;...&lt;/p&gt; by default\n\n// 2. Demonstrate the HTML output with literal input\ntext = &quot;I love this post!&quot; &amp; Chr(10) &amp; Chr(10) &amp; &quot;Here's why:&quot; &amp; Chr(10) &amp; &quot;* Short&quot; &amp; Chr(10) &amp; &quot;* Succinct&quot;;\nwriteOutput(simpleFormat(text));\n// -&gt; &lt;p&gt;I love this post!&lt;/p&gt;\n//\n//    &lt;p&gt;Here's why:&lt;br&gt;\n//    * Short&lt;br&gt;\n//    * Succinct&lt;/p&gt;\n\n// 3. Skip the wrapping paragraph tag (wrap=false) when you are composing markup yourself\nwriteOutput(&quot;&lt;div&gt;&quot; &amp; simpleFormat(text=post.excerpt, wrap=false) &amp; &quot;&lt;/div&gt;&quot;);\n\n// 4. Disable XSS encoding when the text is already trusted/pre-encoded HTML\nwriteOutput(simpleFormat(text=post.bodyText, encode=false));\n</code></pre>","hasExtended":true},"hint":"Returns formatted text using HTML break tags (<code><br></code>) and HTML paragraph elements (<code><p></p></code>) based on the newline characters and carriage returns in the <code>text</code> that is passed in.\n\n","parameters":[{"type":"string","hint":"The text to format.","required":true,"name":"text"},{"type":"boolean","hint":"Set to `true` to wrap the result in a paragraph HTML element.","required":false,"name":"wrap","default":true},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"simpleFormat","tags":{"category":"Miscellaneous Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.singularize","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Singularize a regular plural word\nsingular = singularize(&quot;languages&quot;);\n// singular -&gt; &quot;language&quot;\n\n// 2. Singularize an irregular plural\nsingular = singularize(&quot;children&quot;);\n// singular -&gt; &quot;child&quot;\n\n// 3. Singularize a camelCased word (only the last part is singularized)\nsingular = singularize(&quot;blogPosts&quot;);\n// singular -&gt; &quot;blogPost&quot;\n</code></pre>","hasExtended":true},"hint":"Returns the singular form of the passed in word.\n\n","parameters":[{"type":"string","hint":"The word to singularize.","required":true,"name":"word"}],"name":"singularize","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"string","slug":"controller.startFormTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic form posting to a specific action in the current controller\n#startFormTag(action=&quot;create&quot;)#\n    &lt;!--- form controls go here ---&gt;\n#endFormTag()#\n\n// 2. Form targeting a different controller and action, using HTTP GET\n#startFormTag(controller=&quot;search&quot;, action=&quot;results&quot;, method=&quot;get&quot;)#\n    &lt;!--- search fields ---&gt;\n#endFormTag()#\n\n// 3. Multipart form for file uploads\n#startFormTag(action=&quot;upload&quot;, multipart=true)#\n    &lt;!--- file input and other controls ---&gt;\n#endFormTag()#\n\n// 4. Form using a named route with extra HTML attributes (id, class)\n#startFormTag(route=&quot;newRegistration&quot;, id=&quot;registration-form&quot;, class=&quot;form-horizontal&quot;)#\n    &lt;!--- registration fields ---&gt;\n#endFormTag()#\n\n// 5. Form that sends a PUT request (e.g., update an existing record)\n#startFormTag(action=&quot;update&quot;, key=params.key, method=&quot;put&quot;)#\n    &lt;!--- edit fields ---&gt;\n#endFormTag()#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing the opening <code>form</code> tag.\nThe form's action will be built according to the same rules as <code>URLFor</code>.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"The type of `method` to use in the `form` tag (`delete`, `get`, `patch`, `post`, and `put` are the options).","required":false,"name":"method","default":"post"},{"type":"boolean","hint":"Set to `true` if the form should be able to upload files.","required":false,"name":"multipart","default":false},{"type":"string","hint":"Name of a route that you have configured in `config/routes.cfm`.","required":false,"name":"route","default":""},{"type":"string","hint":"Name of the controller to include in the URL.","required":false,"name":"controller","default":""},{"type":"string","hint":"Name of the action to include in the URL.","required":false,"name":"action","default":""},{"type":"any","hint":"Key(s) to include in the URL.","required":false,"name":"key","default":""},{"type":"string","hint":"Any additional parameters to be set in the query string (example: wheels=cool&x=y). Please note that Wheels uses the & and = characters to split the parameters and encode them properly for you. However, if you need to pass in & or = as part of the value, then you need to encode them (and only them), example: a=cats%26dogs%3Dtrouble!&b=1.","required":false,"name":"params","default":""},{"type":"string","hint":"Sets an anchor name to be appended to the path.","required":false,"name":"anchor","default":""},{"type":"boolean","hint":"If true, returns only the relative URL (no protocol, host name or port).","required":false,"name":"onlyPath","default":true},{"type":"string","hint":"Set this to override the current host.","required":false,"name":"host","default":""},{"type":"string","hint":"Set this to override the current protocol.","required":false,"name":"protocol","default":""},{"type":"numeric","hint":"Set this to override the current port number.","required":false,"name":"port","default":0},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"startFormTag","tags":{"category":"General Form Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"generalformfunctions"}},{"returntype":"any","slug":"tabledefinition.string","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single string column to a new table\nt = createTable(name='users');\n\tt.string(columnNames='username', limit=100, allowNull=false);\n\tt.string(columnNames='email', limit=255, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple string columns at once with a default value\nt = createTable(name='products');\n\tt.string(columnNames='name,sku,status', limit=100, default='', allowNull=false);\n\tt.integer(columnNames='stock', default=0, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Alter an existing table to add a string column with a limit\nt = changeTable(name='orders');\n\tt.string(columnNames='trackingNumber', limit=50, allowNull=true);\nt.change();\n</code></pre>","hasExtended":true},"hint":"adds string columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"limit"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"string","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"controller.stripLinks","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Remove a link from an HTML string, leaving only the link text\nresult = stripLinks('&lt;strong&gt;Wheels&lt;/strong&gt; is a framework for &lt;a href=&quot;http://www.adobe.com/products/coldfusion&quot;&gt;ColdFusion&lt;/a&gt;.');\n// result -&gt; &quot;&lt;strong&gt;Wheels&lt;/strong&gt; is a framework for ColdFusion.&quot;\n\n// 2. Strip multiple links from a string\nresult = stripLinks('Visit &lt;a href=&quot;https://cfwheels.org&quot;&gt;CFWheels&lt;/a&gt; or read the &lt;a href=&quot;https://cfwheels.org/docs&quot;&gt;docs&lt;/a&gt; for more info.');\n// result -&gt; &quot;Visit CFWheels or read the docs for more info.&quot;\n\n// 3. Strip links while skipping XSS encoding (e.g. when you trust the source HTML)\nresult = stripLinks('&lt;p&gt;Check out &lt;a href=&quot;https://cfwheels.org&quot;&gt;CFWheels&lt;/a&gt;!&lt;/p&gt;', encode=false);\n// result -&gt; &quot;&lt;p&gt;Check out CFWheels!&lt;/p&gt;&quot;\n</code></pre>","hasExtended":true},"hint":"Removes all links from an HTML string, leaving just the link text.\n\n","parameters":[{"type":"string","hint":"The HTML to remove links from.","required":true,"name":"html"},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"stripLinks","tags":{"category":"Sanitization Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"sanitizationfunctions"}},{"returntype":"string","slug":"controller.stripTags","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Strip all HTML tags from a string, leaving plain text\nresult = stripTags('&lt;strong&gt;CFWheels&lt;/strong&gt; is a framework for &lt;a href=&quot;http://www.adobe.com/products/coldfusion&quot;&gt;ColdFusion&lt;/a&gt;.');\n// result -&gt; &quot;CFWheels is a framework for ColdFusion.&quot;\n\n// 2. Strip tags from a richer HTML fragment\nresult = stripTags('&lt;h1&gt;Welcome&lt;/h1&gt;&lt;p&gt;This is a &lt;em&gt;great&lt;/em&gt; framework.&lt;/p&gt;');\n// result -&gt; &quot;WelcomeThis is a great framework.&quot;\n\n// 3. Strip tags while skipping XSS encoding (e.g. when you trust the source HTML)\nresult = stripTags('&lt;p&gt;Hello, &lt;strong&gt;world&lt;/strong&gt;!&lt;/p&gt;', encode=false);\n// result -&gt; &quot;Hello, world!&quot;\n</code></pre>","hasExtended":true},"hint":"Removes all HTML tags from a string.\n\n","parameters":[{"type":"string","hint":"The HTML to remove tag markup from.","required":true,"name":"html"},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"stripTags","tags":{"category":"Sanitization Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"sanitizationfunctions"}},{"returntype":"string","slug":"controller.styleSheetLinkTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Include a single stylesheet from the `stylesheets` folder\n// Generates: &lt;link rel=&quot;stylesheet&quot; href=&quot;/stylesheets/app.css&quot; ...&gt;\nwriteOutput(styleSheetLinkTag(&quot;app&quot;));\n\n// 2. Include multiple stylesheets with a comma-delimited list\n// Generates two separate &lt;link&gt; tags for blog.css and comments.css\nwriteOutput(styleSheetLinkTag(&quot;blog,comments&quot;));\n\n// 3. Include a stylesheet for print media only\nwriteOutput(styleSheetLinkTag(sources=&quot;print&quot;, media=&quot;print&quot;));\n\n// 4. Include an external stylesheet via full URL\nwriteOutput(styleSheetLinkTag(&quot;https://fonts.googleapis.com/css2?family=Roboto&quot;));\n\n// 5. Push a stylesheet into the &lt;head&gt; from anywhere in the view\n// The tag is injected into the &lt;head&gt; section rather than rendered inline\nwriteOutput(styleSheetLinkTag(sources=&quot;tabs&quot;, head=true));\n\n// 6. Use a pipe delimiter instead of the default comma\nwriteOutput(styleSheetLinkTag(sources=&quot;reset|layout|theme&quot;, delim=&quot;|&quot;));\n</code></pre>","hasExtended":true},"hint":"Returns a <code>link</code> tag for a stylesheet (or several) based on the supplied arguments.\n\n","parameters":[{"type":"string","hint":"The name of one or many CSS files in the stylesheets folder, minus the `.css` extension. Pass a full URL to generate a tag for an external style sheet. Can also be called with the `source` argument.","required":false,"name":"sources","default":""},{"type":"string","hint":"The `type` attribute for the `link` tag.","required":false,"name":"type","default":"text/css"},{"type":"string","hint":"The `media` attribute for the `link` tag.","required":false,"name":"media","default":"all"},{"type":"string","hint":"The `rel` attribute for the relation between the tag and href.","required":false,"name":"rel"},{"type":"boolean","hint":"Set to `true` to place the output in the `head` area of the HTML page instead of the default behavior (which is to place the output where the function is called from).","required":false,"name":"head","default":false},{"type":"string","hint":"The delimiter to use for the list of CSS files.","required":false,"name":"delim","default":","},{"type":"boolean","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"styleSheetLinkTag","tags":{"category":"Asset Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"assetfunctions"}},{"returntype":"string","slug":"controller.submitTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic submit button inside a form\n#startFormTag(action=&quot;save&quot;)#\n    &lt;!--- form controls go here ---&gt;\n    #submitTag()#\n#endFormTag()#\n// -&gt; &lt;form action=&quot;/products/save&quot; method=&quot;post&quot;&gt;...&lt;input type=&quot;submit&quot; value=&quot;Save changes&quot;&gt;&lt;/form&gt;\n\n// 2. Custom button label\n#submitTag(value=&quot;Create Account&quot;)#\n// -&gt; &lt;input type=&quot;submit&quot; value=&quot;Create Account&quot;&gt;\n\n// 3. Image submit button\n#submitTag(image=&quot;submit-button.png&quot;)#\n// -&gt; &lt;input type=&quot;image&quot; src=&quot;/images/submit-button.png&quot;&gt;\n\n// 4. Submit button with extra HTML attributes (class and id)\n#submitTag(value=&quot;Place Order&quot;, class=&quot;btn btn-primary&quot;, id=&quot;order-submit&quot;)#\n// -&gt; &lt;input type=&quot;submit&quot; value=&quot;Place Order&quot; class=&quot;btn btn-primary&quot; id=&quot;order-submit&quot;&gt;\n\n// 5. Submit button wrapped with HTML using prepend and append\n#submitTag(value=&quot;Save&quot;, prepend=&quot;&lt;div class=&quot;&quot;actions&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n// -&gt; &lt;div class=&quot;actions&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Save&quot;&gt;&lt;/div&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a submit button form control.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Message to display in the button form control.","required":false,"name":"value","default":"Save changes"},{"type":"string","hint":"File name of the image file to use in the button form control.","required":false,"name":"image","default":""},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"submitTag","tags":{"category":"General Form Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"generalformfunctions"}},{"returntype":"void","slug":"controller.subscribeToChannel","availableIn":["controller"],"extended":{"docs":"","hasExtended":false},"hint":"Subscribe to a channel and stream events to the client via SSE.\nOpens a long-lived SSE connection that delivers matching events\nuntil the client disconnects or the timeout is reached.\nFor the \"memory\" adapter, subscribes to the in-memory Channel\nengine and buffers events for delivery. For the \"database\" adapter,\npolls the wheels_events table at regular intervals.","parameters":[{"type":"string","hint":"The channel name to subscribe to (e.g. \"user.42\").","required":true,"name":"channel"},{"type":"string","hint":"Comma-delimited list of event types to filter. Empty = all events.","required":false,"name":"events","default":""},{"type":"string","hint":"Resume from this event ID. Auto-detected from Last-Event-ID header if empty.","required":false,"name":"lastEventId","default":""},{"type":"string","hint":"\"memory\" (default) or \"database\".","required":false,"name":"adapter","default":""},{"type":"numeric","hint":"Seconds between polls for database adapter (default 2).","required":false,"name":"pollInterval","default":2},{"type":"numeric","hint":"Maximum connection duration in seconds (default 300 = 5 minutes).","required":false,"name":"timeout","default":300},{"type":"numeric","hint":"Seconds between keep-alive pings (default 15).","required":false,"name":"heartbeatInterval","default":15}],"name":"subscribeToChannel","tags":{"category":"","sectionClass":"","section":"","categoryClass":""}},{"returntype":"any","slug":"model.sum","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the sum of all salaries\nallSalaries = model(&quot;Employee&quot;).sum(&quot;salary&quot;);\n\n// 2. Get the sum of all salaries for employees in a given country\nallAustralianSalaries = model(&quot;Employee&quot;).sum(property=&quot;salary&quot;, include=&quot;country&quot;, where=&quot;countryname='Australia'&quot;);\n\n// 3. Make sure a numeric value is always returned, even if there are no records analyzed by the query\nsalarySum = model(&quot;Employee&quot;).sum(property=&quot;salary&quot;, where=&quot;salary BETWEEN #params.min# AND #params.max#&quot;, ifNull=0);\n\n// 4. Sum only distinct (unique) salary values\ndistinctSum = model(&quot;Employee&quot;).sum(property=&quot;salary&quot;, distinct=true);\n\n// 5. Get the total salary per department using grouping\nbyDepartment = model(&quot;Employee&quot;).sum(property=&quot;salary&quot;, group=&quot;departmentId&quot;);\n// byDepartment is a query with columns: departmentId, salarysum\n</code></pre>","hasExtended":true},"hint":"Calculates the sum of values for a given property.\nUses the SQL function <code>SUM</code>.\nIf no records can be found to perform the calculation on you can use the <code>ifNull</code> argument to decide what should be returned.\n\n","parameters":[{"type":"string","hint":"Name of the property to get the sum for (must be a property of a numeric data type).","required":true,"name":"property"},{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"boolean","hint":"When true, SUM returns the sum of unique values only.","required":false,"name":"distinct","default":false},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"any","hint":"The value returned if no records are found. Common usage is to set this to `0` to make sure a numeric value is always returned instead of a blank string.","required":false,"name":"ifNull","default":""},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"},{"type":"string","hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"group"}],"name":"sum","tags":{"category":"Statistics Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"statisticsfunctions"}},{"returntype":"void","slug":"controller.switchTenant","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Switch to a different tenant mid-request (minimal required argument)\nswitchTenant(tenant = {dataSource = &quot;tenant_db_acme&quot;});\n\n// 2. Switch with a full tenant struct (id and per-tenant config override)\nswitchTenant(\n    tenant = {\n        dataSource = &quot;tenant_db_beta&quot;,\n        id         = &quot;beta&quot;,\n        config     = {timeZone = &quot;America/New_York&quot;}\n    }\n);\n\n// 3. Force-switch even when the current tenant is locked by TenantResolver middleware\nswitchTenant(\n    tenant = {dataSource = &quot;tenant_db_admin&quot;, id = &quot;admin&quot;},\n    force  = true\n);\n</code></pre>","hasExtended":true},"hint":"Switches the active tenant mid-request. Throws if the current tenant is locked\n(set by TenantResolver middleware) unless <code>force</code> is true.\n\n","parameters":[{"type":"struct","hint":"Struct with at minimum a `dataSource` key. Optional: `id`, `config`.","required":true,"name":"tenant"},{"type":"boolean","hint":"If true, overrides the lock set by TenantResolver middleware.","required":false,"name":"force","default":false}],"name":"switchTenant","tags":{"category":"Multi-Tenancy","sectionClass":"configuration","section":"Configuration","categoryClass":"multi-tenancy"}},{"returntype":"void","slug":"model.table","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Map the `User` model to a non-standard table name.\n// In models/User.cfc\nfunction config() {\n\t// Tell Wheels to use `tbl_USERS` instead of the default `users` table.\n\ttable(&quot;tbl_USERS&quot;);\n}\n\n// 2. Map a model to a table with a legacy prefix.\n// In models/Product.cfc\nfunction config() {\n\ttable(&quot;legacy_products&quot;);\n}\n\n// 3. Declare a model that has no backing database table at all.\n// In models/ApiResponse.cfc\nfunction config() {\n\ttable(false);\n}\n</code></pre>","hasExtended":true},"hint":"Use this method to tell Wheels what database table to connect to for this model.\nYou only need to use this method when your table naming does not follow the standard Wheels convention of a singular object name mapping to a plural table name.\nTo not use a table for your model at all, call <code>table(false)</code>.\n\n","parameters":[{"type":"any","hint":"Name of the table to map this model to.","required":true,"name":"name"}],"name":"table","tags":{"category":"Miscellaneous Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"model.tableName","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check what table the User model is mapped to (Wheels convention: singular model -&gt; plural table)\nname = model(&quot;User&quot;).tableName();\n// name -&gt; &quot;users&quot;\n\n// 2. Check the table for a model that uses a custom table name (set via table() in config())\n// In models/StaffMember.cfc: table(&quot;employees&quot;);\nname = model(&quot;StaffMember&quot;).tableName();\n// name -&gt; &quot;employees&quot;\n\n// 3. Use the table name dynamically in a log message or custom SQL fragment\ntableUsed = model(&quot;Order&quot;).tableName();\nwriteOutput(&quot;Querying table: &quot; &amp; tableUsed);\n// Outputs: Querying table: orders\n</code></pre>","hasExtended":true},"hint":"Returns the name of the database table that this model is mapped to.\nThis is a getter and takes no arguments — the table setter is <code>table()</code>.\nCalling <code>tableName()</code> with an argument has always been a silent no-op (CFML\naccepts the extra argument and the model keeps its convention table), a trap\nsome 4.0-era docs taught as a setter. When error information is shown\n(development / testing — the same gate <code>exists()</code> uses above) it now fails\nloud; in production it stays a no-op so an upgrade never breaks a running\napp. See issue #3079.\n\n","parameters":[],"name":"tableName","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"string","slug":"controller.telField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>&lt;!--- Provide a `label` and the required `objectName` and `property` ---&gt;\\n#telField(label=&quot;Phone Number&quot;, objectName=&quot;contact&quot;, property=&quot;phone&quot;)#\\n\\n&lt;!--- Add a CSS class and a placeholder for formatting guidance ---&gt;\\n#telField(label=&quot;Mobile&quot;, objectName=&quot;user&quot;, property=&quot;mobile&quot;, class=&quot;tel-input&quot;, placeholder=&quot;+1-555-000-0000&quot;)#\\n\\n&lt;!--- Render telephone fields for each phone number in a nested association ---&gt;\\n&lt;fieldset&gt;\\n\\t&lt;legend&gt;Phone Numbers&lt;/legend&gt;\\n\\t&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(contact.phoneNumbers)#&quot; index=&quot;i&quot;&gt;\\n\\t\\t#telField(label=&quot;Phone ##i#&quot;, objectName=&quot;contact&quot;, association=&quot;phoneNumbers&quot;, position=i, property=&quot;number&quot;)#\\n\\t&lt;/cfloop&gt;\\n&lt;/fieldset&gt;</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a telephone field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"telField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.telFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic telephone field with a pre-filled value\n#telFieldTag(name=&quot;phone&quot;, value=&quot;555-867-5309&quot;)#\n\n// 2. Telephone field with a label and a CSS class\n#telFieldTag(name=&quot;mobilePhone&quot;, value=&quot;&quot;, label=&quot;Mobile Phone&quot;, class=&quot;tel-input&quot;)#\n\n// 3. Telephone field with label placement and prepend/append wrappers\n#telFieldTag(name=&quot;officePhone&quot;, label=&quot;Office Phone&quot;, labelPlacement=&quot;before&quot;, prepend=&quot;&lt;div class=&quot;&quot;field&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a telephone field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"telFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"struct","slug":"controller.tenant","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the active tenant struct (when a tenant is set)\nt = tenant();\n// t -&gt; {id: &quot;acme&quot;, dataSource: &quot;tenant_db_acme&quot;, config: {}, $locked: true}\n\n// 2. Check whether a tenant is active before using its properties\nt = tenant();\nif (!structIsEmpty(t)) {\n    writeOutput(&quot;Current tenant: &quot; &amp; t.id);\n} else {\n    writeOutput(&quot;No tenant active — using application defaults.&quot;);\n}\n\n// 3. Access a per-tenant config value set via switchTenant()\nt = tenant();\nif (structKeyExists(t, &quot;config&quot;) &amp;&amp; structKeyExists(t.config, &quot;timeZone&quot;)) {\n    writeOutput(&quot;Tenant time zone: &quot; &amp; t.config.timeZone);\n}\n</code></pre>","hasExtended":true},"hint":"Returns the current tenant struct, or an empty struct if no tenant is active.\nThe tenant struct contains: <code>id</code>, <code>dataSource</code>, <code>config</code>, and <code>$locked</code>.\nA tenant only counts as active when it carries a non-empty <code>dataSource</code> — the same test\n<code>$tenantDataSource()</code> applies before it routes a query. Anything else on the key reads as\nno tenant rather than being handed back as though it were a resolved one, so a malformed\nvalue degrades to a no-op instead of wrong behaviour (#3336). Every framework producer\n(<code>switchTenant()</code>, <code>TenantResolver</code>, <code>Job.$restoreTenantContext()</code>, <code>TenantMigrator</code>)\nalready guarantees a non-empty <code>dataSource</code>, so this only filters foreign values.\n\n","parameters":[],"name":"tenant","tags":{"category":"Multi-Tenancy","sectionClass":"configuration","section":"Configuration","categoryClass":"multi-tenancy"}},{"returntype":"any","slug":"tabledefinition.text","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single text column to a table\nt.text(&quot;body&quot;);\n\n// 2. Add multiple text columns at once\nt.text(&quot;summary,description,notes&quot;);\n\n// 3. Add a text column that defaults to an empty string and disallows nulls\nt.text(columnNames=&quot;bio&quot;, default=&quot;&quot;, allowNull=false);\n\n// 4. Add a MEDIUMTEXT column in MySQL (16MB capacity; ignored on other databases)\nt.text(columnNames=&quot;content&quot;, size=&quot;mediumtext&quot;);\n\n// 5. Add a LONGTEXT column in MySQL (4GB capacity; ignored on other databases)\nt.text(columnNames=&quot;rawHtml&quot;, size=&quot;longtext&quot;);\n\n// 6. Full migration example using text() inside createTable\nt = createTable(&quot;articles&quot;);\nt.string(&quot;title&quot;);\nt.text(&quot;body&quot;);\nt.text(columnNames=&quot;excerpt&quot;, allowNull=true);\nt.timestamps();\nt.create();\n</code></pre>","hasExtended":true},"hint":"Adds text columns to table definition.\nIn MySQL databases, you can specify different text sizes:\n- Regular TEXT (65KB) - default when no size is specified\n- MEDIUMTEXT (16MB) - specify size=\"mediumtext\"\n- LONGTEXT (4GB) - specify size=\"longtext\"\nFor other database engines, the size parameter is ignored and the default text type is used.\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"},{"type":"string","required":false,"name":"size"}],"name":"text","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"controller.textArea","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic text area bound to a model object property\n#textArea(objectName=&quot;article&quot;, property=&quot;overview&quot;, label=&quot;Overview&quot;)#\n\n// 2. Text area with custom rows/cols attributes and a placeholder\n#textArea(objectName=&quot;post&quot;, property=&quot;body&quot;, label=&quot;Body&quot;, rows=10, cols=60, placeholder=&quot;Write your post here...&quot;)#\n\n// 3. Text areas for a nested hasMany association (screenshots)\n&lt;fieldset&gt;\n\t&lt;legend&gt;Screenshots&lt;/legend&gt;\n\t&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(site.screenshots)#&quot; index=&quot;i&quot;&gt;\n\t\t#fileField(objectName=&quot;site&quot;, association=&quot;screenshots&quot;, position=i, property=&quot;file&quot;, label=&quot;File ##i#&quot;)#\n\t\t#textArea(objectName=&quot;site&quot;, association=&quot;screenshots&quot;, position=i, property=&quot;caption&quot;, label=&quot;Caption ##i#&quot;)#\n\t&lt;/cfloop&gt;\n&lt;/fieldset&gt;\n\n// 4. Text area with label placement after and appended helper text\n#textArea(objectName=&quot;user&quot;, property=&quot;bio&quot;, label=&quot;Bio&quot;, labelPlacement=&quot;before&quot;, append=&quot;&lt;small&gt;Max 500 characters&lt;/small&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a text area field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"textArea","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.textAreaTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic textarea with a label and pre-populated content from params\n#textAreaTag(name=&quot;description&quot;, label=&quot;Description&quot;, content=params.description)#\n\n// 2. Textarea without a label, adding extra HTML attributes via additional arguments\n#textAreaTag(name=&quot;bio&quot;, rows=&quot;6&quot;, cols=&quot;40&quot;)#\n\n// 3. Textarea with label placement controlled and content wrapped with HTML using prepend/append\n#textAreaTag(name=&quot;notes&quot;, label=&quot;Notes&quot;, labelPlacement=&quot;before&quot;, prepend=&quot;&lt;div class=&quot;&quot;field&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a text area form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Content to display in textarea on page load.","required":false,"name":"content","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"textAreaTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.textField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic text field bound to an object property\n#textField(objectName=&quot;user&quot;, property=&quot;firstName&quot;, label=&quot;First Name&quot;)#\n\n// 2. Use an HTML5 input type (email, tel, url, etc.) via the `type` argument\n#textField(objectName=&quot;user&quot;, property=&quot;email&quot;, label=&quot;Email Address&quot;, type=&quot;email&quot;)#\n\n// 3. Render fields for a hasMany association using `association` and `position`\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(contact.phoneNumbers)#&quot; index=&quot;i&quot;&gt;\n\t#textField(objectName=&quot;contact&quot;, association=&quot;phoneNumbers&quot;, position=i, property=&quot;phoneNumber&quot;, label=&quot;Phone ##i#&quot;)#\n&lt;/cfloop&gt;\n\n// 4. Wrap the field with extra markup using `prepend` and `append`\n#textField(objectName=&quot;user&quot;, property=&quot;username&quot;, label=&quot;Username&quot;, prepend=&quot;&lt;div class=&quot;&quot;field&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a text field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"string","hint":"Input type attribute. Common examples in HTML5 and later are text (default), email, tel, and url.","required":false,"name":"type","default":"text"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"textField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.textFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic search field with a label and a pre-filled value from params\n#textFieldTag(name=&quot;q&quot;, label=&quot;Search&quot;, value=params.q)#\n\n// 2. Email input using the HTML5 type attribute\n#textFieldTag(name=&quot;email&quot;, label=&quot;Email address&quot;, type=&quot;email&quot;, value=params.email)#\n\n// 3. Field with label placed before the input and extra HTML attributes\n#textFieldTag(name=&quot;username&quot;, label=&quot;Username&quot;, labelPlacement=&quot;before&quot;, class=&quot;form-control&quot;, placeholder=&quot;Enter username&quot;)#\n\n// 4. Wrapping the input with Bootstrap input-group markup using prepend and append\n#textFieldTag(name=&quot;website&quot;, label=&quot;Website&quot;, type=&quot;url&quot;, prepend=&quot;&lt;div class=&quot;&quot;input-group&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a text field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"Input type attribute. Common examples in HTML5 and later are text (default), email, tel, and url.","required":false,"name":"type","default":"text"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"textFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"any","slug":"tabledefinition.time","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single time column to a new table\nt = createTable(name='schedules');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.time(columnNames='startTime', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple time columns at once\nt = createTable(name='shifts');\n\tt.string(columnNames='employeeName', limit=100, allowNull=false);\n\tt.time(columnNames='clockIn,clockOut', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a nullable time column with a default to an existing table\nt = changeTable(name='stores');\n\tt.time(columnNames='openTime', allowNull=true, default='09:00:00');\nt.change();\n</code></pre>","hasExtended":true},"hint":"adds time columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"time","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"any","slug":"controller.timeAgoInWords","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Show how long ago a date was (relative to now)\naWhileAgo = DateAdd(&quot;d&quot;, -90, Now());\n// Returns something like &quot;3 months&quot;\nwriteOutput(timeAgoInWords(aWhileAgo));\n\n// 2. Include seconds for a very recent timestamp\njustNow = DateAdd(&quot;s&quot;, -8, Now());\n// Returns &quot;less than 10 seconds&quot;\nwriteOutput(timeAgoInWords(fromTime=justNow, includeSeconds=true));\n\n// 3. Compare against a specific reference point instead of now\npostDate = CreateDateTime(2024, 1, 15, 9, 0, 0);\nreferenceDate = CreateDateTime(2024, 3, 20, 9, 0, 0);\n// Returns &quot;about 2 months&quot;\nwriteOutput(timeAgoInWords(fromTime=postDate, toTime=referenceDate));\n</code></pre>","hasExtended":true},"hint":"Returns a string describing the approximate time difference between the date passed in and the current date.\n\n","parameters":[{"type":"date","hint":"Date to compare from.","required":true,"name":"fromTime"},{"type":"boolean","hint":"Whether or not to include the number of seconds in the returned string.","required":false,"name":"includeSeconds","default":false},{"type":"date","hint":"Date to compare to.","required":false,"name":"toTime","default":"[runtime expression]"}],"name":"timeAgoInWords","tags":{"category":"Date Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"datefunctions"}},{"returntype":"string","slug":"controller.timeSelect","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>&lt;!--- Basic time select bound to a model object (hour, minute, second) ---&gt;\n#timeSelect(objectName=&quot;business&quot;, property=&quot;openUntil&quot;)#\n\n&lt;!--- Show fields for hour and minute only ---&gt;\n#timeSelect(objectName=&quot;business&quot;, property=&quot;openUntil&quot;, order=&quot;hour,minute&quot;)#\n\n&lt;!--- Only show 15-minute intervals ---&gt;\n#timeSelect(objectName=&quot;appointment&quot;, property=&quot;dateTimeStart&quot;, minuteStep=15)#\n\n&lt;!--- Display in 12-hour format with AM/PM ---&gt;\n#timeSelect(objectName=&quot;appointment&quot;, property=&quot;dateTimeStart&quot;, twelveHour=true)#\n\n&lt;!--- Include a blank option and use a custom separator ---&gt;\n#timeSelect(objectName=&quot;shift&quot;, property=&quot;startTime&quot;, includeBlank=&quot;- Select -&quot;, separator=&quot; | &quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing three <code>select</code> form controls for hour, minute, and second based on the supplied objectName and property.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":false,"name":"objectName","default":""},{"type":"string","hint":"The name of the property to use in the form control.","required":false,"name":"property","default":""},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"Use to change the order of or exclude time select tags.","required":false,"name":"order","default":"hour,minute,second"},{"type":"string","hint":"Use to change the character that is displayed between the time select tags.","required":false,"name":"separator","default":":"},{"type":"numeric","hint":"Pass in 10 to only show minute 10, 20, 30, etc.","required":false,"name":"minuteStep","default":1},{"type":"numeric","hint":"Pass in 10 to only show seconds 10, 20, 30, etc.","required":false,"name":"secondStep","default":1},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":false},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"boolean","hint":"Set to false to not combine the select parts into a single DateTime object.","required":false,"name":"combine"},{"type":"boolean","hint":"whether to display the hours in 24 or 12 hour format. 12 hour format has AM/PM drop downs","required":false,"name":"twelveHour","default":false},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"timeSelect","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.timeSelectTags","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic usage - render hour, minute, and second selects unbound from a model object\n#timeSelectTags(name=&quot;timeOfMeeting&quot;, selected=params.timeOfMeeting)#\n\n// 2. Show only hour and minute fields\n#timeSelectTags(name=&quot;timeOfMeeting&quot;, selected=params.timeOfMeeting, order=&quot;hour,minute&quot;)#\n\n// 3. Use 12-hour format with AM/PM and jump minutes in 15-minute increments\n#timeSelectTags(name=&quot;appointmentTime&quot;, selected=params.appointmentTime, twelveHour=true, minuteStep=15, order=&quot;hour,minute&quot;)#\n\n// 4. Include a blank option and add a label\n#timeSelectTags(name=&quot;startTime&quot;, selected=params.startTime, includeBlank=true, label=&quot;Start Time&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing three <code>select</code> form controls for hour, minute, and second based on name.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value of option that should be selected by default.","required":false,"name":"selected","default":""},{"type":"string","hint":"Use to change the order of or exclude time select tags.","required":false,"name":"order","default":"hour,minute,second"},{"type":"string","hint":"Use to change the character that is displayed between the time select tags.","required":false,"name":"separator","default":":"},{"type":"numeric","hint":"Pass in 10 to only show minute 10, 20, 30, etc.","required":false,"name":"minuteStep","default":1},{"type":"numeric","hint":"Pass in 10 to only show seconds 10, 20, 30, etc.","required":false,"name":"secondStep","default":1},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"boolean","hint":"Set to false to not combine the select parts into a single DateTime object.","required":false,"name":"combine"},{"type":"boolean","hint":"whether to display the hours in 24 or 12 hour format. 12 hour format has AM/PM drop downs","required":false,"name":"twelveHour","default":false},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"timeSelectTags","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"any","slug":"tabledefinition.timestamp","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single timestamp column to a new table\nt = createTable(name='sessions');\n\tt.string(columnNames='token', limit=64, allowNull=false);\n\tt.timestamp(columnNames='expiresAt', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple timestamp columns at once\nt = createTable(name='events');\n\tt.string(columnNames='name', limit=255, allowNull=false);\n\tt.timestamp(columnNames='startsAt,endsAt', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a nullable timestamp column with a default to an existing table\nt = changeTable(name='articles');\n\tt.timestamp(columnNames='publishedAt', allowNull=true, default='NOW()');\nt.change();\n\n// 4. Override the underlying column type (e.g. use 'timestamp' instead of the default 'datetime')\nt = createTable(name='logs');\n\tt.string(columnNames='message', limit=255, allowNull=false);\n\tt.timestamp(columnNames='occurredAt', columnType='timestamp', allowNull=false);\n\tt.timestamps();\nt.create();\n</code></pre>","hasExtended":true},"hint":"adds timestamp columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default"},{"type":"boolean","required":false,"name":"allowNull"},{"type":"string","required":false,"name":"columnType","default":"datetime"}],"name":"timestamp","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"any","slug":"tabledefinition.timestamps","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add Wheels convention timestamp and soft-delete columns to a new table\n// Adds createdAt, updatedAt, and deletedAt (all nullable datetime columns)\nt = createTable(name='articles');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.text(columnNames='body');\n\tt.timestamps();\nt.create();\n\n// 2. Use timestamps() alongside other column definitions in a full migration\nt = createTable(name='posts');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.string(columnNames='slug', limit=255, allowNull=false);\n\tt.text(columnNames='body');\n\tt.boolean(columnNames='published', default=false, allowNull=false);\n\tt.references(columnNames='author');\n\tt.timestamps();\nt.create();\n</code></pre>","hasExtended":true},"hint":"adds Wheels convention automatic timestamp and soft delete columns to table definition\n\n","parameters":[],"name":"timestamps","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"string","slug":"controller.timeUntilInWords","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Show approximate time until a future date\nnextYear = DateAdd(&quot;yyyy&quot;, 1, Now());\nwriteOutput(timeUntilInWords(nextYear));\n// -&gt; &quot;about 1 year&quot;\n\n// 2. Include seconds for a near-future time\nsoonish = DateAdd(&quot;s&quot;, 8, Now());\nwriteOutput(timeUntilInWords(toTime=soonish, includeSeconds=true));\n// -&gt; &quot;less than 10 seconds&quot;\n\n// 3. Compare two explicit dates (custom fromTime)\nlaunchDate = CreateDate(2025, 6, 1);\ndeadline   = CreateDate(2025, 9, 15);\nwriteOutput(timeUntilInWords(toTime=deadline, fromTime=launchDate));\n// -&gt; &quot;about 3 months&quot;\n</code></pre>","hasExtended":true},"hint":"Returns a string describing the approximate time difference between the current date and the date passed in.\n\n","parameters":[{"type":"date","hint":"Date to compare to.","required":true,"name":"toTime"},{"type":"boolean","hint":"Whether or not to include the number of seconds in the returned string.","required":false,"name":"includeSeconds","default":false},{"type":"date","hint":"Date to compare from.","required":false,"name":"fromTime","default":"[runtime expression]"}],"name":"timeUntilInWords","tags":{"category":"Date Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"datefunctions"}},{"returntype":"string","slug":"controller.titleize","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Capitalize each word in a plain sentence\nresult = titleize(&quot;the quick brown fox&quot;);\n// result -&gt; &quot;The Quick Brown Fox&quot;\n\n// 2. Capitalize a page title that is already mixed case\nresult = titleize(&quot;CFWheels is a framework for ColdFusion&quot;);\n// result -&gt; &quot;CFWheels Is A Framework For ColdFusion&quot;\n\n// 3. Use titleize to format a record name for display\narticle = model(&quot;Article&quot;).findByKey(params.key);\nwriteOutput(titleize(article.title));\n</code></pre>","hasExtended":true},"hint":"Capitalizes all words in the text to create a nicer looking title.\n\n","parameters":[{"type":"string","hint":"The text to turn into a title.","required":true,"name":"word"}],"name":"titleize","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"boolean","slug":"model.toggle","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Toggle a boolean property and save it immediately (default behavior)\nuser = model(&quot;User&quot;).findByKey(58);\n// Returns true if the record was saved successfully, false otherwise\nisSuccess = user.toggle(&quot;isActive&quot;);\n\n// 2. Toggle a boolean property without saving to the database\nuser = model(&quot;User&quot;).findByKey(58);\nuser.toggle(property=&quot;isActive&quot;, save=false);\n// user.isActive is now flipped in memory; call user.save() later to persist\n\n// 3. Use the dynamic toggle helper generated by Wheels\nuser = model(&quot;User&quot;).findByKey(58);\nisSuccess = user.toggleIsActive();\n</code></pre>","hasExtended":true},"hint":"Assigns to the property specified the opposite of the property's current boolean value.\nThrows an error if the property cannot be converted to a boolean value.\nReturns this object if save called internally is <code>false</code>.\n\n","parameters":[{"type":"string","required":true,"name":"property"},{"type":"boolean","hint":"Argument to decide whether save the property after it has been toggled.","required":false,"name":"save","default":true}],"name":"toggle","tags":{"category":"CRUD Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"crudfunctions"}},{"returntype":"string","slug":"controller.truncate","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Truncate to a specific character length (defaults to &quot;...&quot; suffix)\ntruncated = truncate(text=&quot;CFWheels is a framework for ColdFusion&quot;, length=20);\n// truncated -&gt; &quot;CFWheels is a fra...&quot;\n\n// 2. Use a custom truncate string instead of the default ellipsis\ntruncated = truncate(text=&quot;CFWheels is a framework for ColdFusion&quot;, truncateString=&quot; (more)&quot;);\n// truncated -&gt; &quot;CFWheels is a framework fo (more)&quot;\n\n// 3. Text shorter than the length limit is returned unchanged\ntruncated = truncate(text=&quot;Hello&quot;, length=30);\n// truncated -&gt; &quot;Hello&quot;\n</code></pre>","hasExtended":true},"hint":"Truncates text to the specified length and replaces the last characters with the specified truncate string (which defaults to \"...\").\n\n","parameters":[{"type":"string","hint":"The text to truncate.","required":true,"name":"text"},{"type":"numeric","hint":"Length to truncate the text to.","required":false,"name":"length","default":30},{"type":"string","hint":"String to replace the last characters with.","required":false,"name":"truncateString","default":"..."}],"name":"truncate","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"any","slug":"tabledefinition.uniqueidentifier","availableIn":["tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Add a single UUID column with the default newid() value\nt = createTable(name='sessions');\n\tt.uniqueidentifier(columnNames='token');\n\tt.timestamps();\nt.create();\n\n// 2. Add a UUID column that allows NULL values\nt = createTable(name='invitations');\n\tt.string(columnNames='email', limit=255, allowNull=false);\n\tt.uniqueidentifier(columnNames='inviteToken', allowNull=true);\n\tt.timestamps();\nt.create();\n\n// 3. Alter an existing table to add multiple UUID columns at once\nt = changeTable(name='documents');\n\tt.uniqueidentifier(columnNames='publicId,shareToken', allowNull=false);\nt.change();\n</code></pre>","hasExtended":true},"hint":"adds UUID columns to table definition\n\n","parameters":[{"type":"string","required":false,"name":"columnNames"},{"type":"any","required":false,"name":"default","default":"newid()"},{"type":"boolean","required":false,"name":"allowNull"}],"name":"uniqueidentifier","tags":{"category":"Table Definition Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"tabledefinitionfunctions"}},{"returntype":"void","slug":"migration.up","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Create a new table (typical migration forward)\nfunction up() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\tt = createTable(name=&quot;posts&quot;);\n\t\t\tt.string(columnNames=&quot;title&quot;, limit=255);\n\t\t\tt.text(columnNames=&quot;body&quot;);\n\t\t\tt.boolean(columnNames=&quot;published&quot;, default=0);\n\t\t\tt.timestamps();\n\t\t\tt.create();\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (structKeyExists(state, &quot;exception&quot;)) {\n\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\tthrow(\n\t\t\t\terrorCode = &quot;1&quot;,\n\t\t\t\tdetail    = state.exception.detail,\n\t\t\t\tmessage   = state.exception.message,\n\t\t\t\ttype      = &quot;any&quot;\n\t\t\t);\n\t\t} else {\n\t\t\ttransaction action=&quot;commit&quot;;\n\t\t}\n\t}\n}\n\n// 2. Add a column to an existing table\nfunction up() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\taddColumn(table=&quot;users&quot;, columnType=&quot;string&quot;, columnName=&quot;avatarUrl&quot;, limit=500, allowNull=true);\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (structKeyExists(state, &quot;exception&quot;)) {\n\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\tthrow(\n\t\t\t\terrorCode = &quot;1&quot;,\n\t\t\t\tdetail    = state.exception.detail,\n\t\t\t\tmessage   = state.exception.message,\n\t\t\t\ttype      = &quot;any&quot;\n\t\t\t);\n\t\t} else {\n\t\t\ttransaction action=&quot;commit&quot;;\n\t\t}\n\t}\n}\n\n// 3. Run raw SQL and seed initial data in the same migration\nfunction up() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\texecute(&quot;ALTER TABLE products ADD COLUMN sku VARCHAR(50)&quot;);\n\t\t\taddRecord(table=&quot;settings&quot;, key=&quot;maintenance_mode&quot;, value=&quot;false&quot;);\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (structKeyExists(state, &quot;exception&quot;)) {\n\t\t\ttransaction action=&quot;rollback&quot;;\n\t\t\tthrow(\n\t\t\t\terrorCode = &quot;1&quot;,\n\t\t\t\tdetail    = state.exception.detail,\n\t\t\t\tmessage   = state.exception.message,\n\t\t\t\ttype      = &quot;any&quot;\n\t\t\t);\n\t\t} else {\n\t\t\ttransaction action=&quot;commit&quot;;\n\t\t}\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Migrates up: will be executed when migrating your schema forward\nAlong with down(), these are the two main functions in any migration file\nOnly available in a migration CFC\n\n","parameters":[],"name":"up","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"boolean","slug":"model.update","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Find a post and update its title\npost = model(&quot;Post&quot;).findByKey(33);\npost.update(title=&quot;New version of Wheels just released&quot;);\n\n// 2. Update multiple properties from form/URL params on an existing object\npost = model(&quot;Post&quot;).findByKey(params.key);\nisSuccess = post.update(title=&quot;New version of Wheels just released&quot;, properties=params.post);\n\n// 3. Skip validations when updating (useful for admin operations)\npost = model(&quot;Post&quot;).findByKey(params.key);\nisSuccess = post.update(properties=params.post, validate=false);\n\n// 4. Scoped call via a hasOne association (setBio calls bio.update(authorId=author.id) internally)\nauthor = model(&quot;Author&quot;).findByKey(params.authorId);\nbio = model(&quot;Bio&quot;).findByKey(params.bioId);\nauthor.setBio(bio);\n\n// 5. Scoped call via a hasMany association (addCar calls car.update(ownerId=owner.id) internally)\nanOwner = model(&quot;Owner&quot;).findByKey(params.ownerId);\naCar = model(&quot;Car&quot;).findByKey(params.carId);\nanOwner.addCar(aCar);\n\n// 6. Scoped call to disassociate a record (removeComment calls comment.update(postId=&quot;&quot;) internally)\naPost = model(&quot;Post&quot;).findByKey(params.postId);\naComment = model(&quot;Comment&quot;).findByKey(params.commentId);\naPost.removeComment(aComment);\n</code></pre>","hasExtended":true},"hint":"Updates the object with the supplied <code>properties</code> and saves it to the database.\nReturns <code>true</code> if the object was saved successfully to the database and <code>false</code> otherwise.\n\n","parameters":[{"type":"struct","hint":"The properties you want to set on the object (can also be passed in as named arguments).","required":false,"name":"properties","default":"[runtime expression]"},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"boolean","hint":"Set to `false` to skip validations for this operation.","required":false,"name":"validate","default":true},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":true},{"type":"boolean","hint":"Set this to `true` to allow explicit assignment of `createdAt` or `updatedAt` properties","required":false,"name":"allowExplicitTimestamps","default":false}],"name":"update","tags":{"category":"CRUD Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"crudfunctions"}},{"returntype":"numeric","slug":"model.updateAll","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Update a single property on all matching records (returns count of updated rows)\nrecordsUpdated = model(&quot;post&quot;).updateAll(published=1, where=&quot;published=0&quot;);\n\n// 2. Update multiple properties on matching records using named arguments\nrecordsUpdated = model(&quot;post&quot;).updateAll(\n\tpublished=1,\n\tpublishedAt=Now(),\n\twhere=&quot;published=0&quot;\n);\n\n// 3. Update using a properties struct instead of named arguments\nprops = {status=&quot;archived&quot;, updatedBy=&quot;system&quot;};\nrecordsUpdated = model(&quot;post&quot;).updateAll(properties=props, where=&quot;createdAt &lt; '#DateAdd(&quot;yyyy&quot;, -2, Now())#'&quot;);\n\n// 4. Instantiate each matching object so that callbacks and validations run\nrecordsUpdated = model(&quot;user&quot;).updateAll(active=0, where=&quot;lastLoginAt &lt; '#DateAdd(&quot;d&quot;, -365, Now())#'&quot;, instantiate=true);\n\n// 5. Scoped call via a hasMany association — equivalent to\n//    model(&quot;comment&quot;).updateAll(postId=&quot;&quot;, where=&quot;postId=#post.id#&quot;)\npost = model(&quot;post&quot;).findByKey(params.postId);\npost.removeAllComments();\n</code></pre>","hasExtended":true},"hint":"Updates all properties for the records that match the <code>where</code> argument.\nProperty names and values can be passed in either using named arguments or as a struct to the <code>properties</code> argument.\nBy default, objects will not be instantiated and therefore callbacks and validations are not invoked.\nYou can change this behavior by passing in <code>instantiate=true</code>.\nThis method returns the number of records that were updated.\n\n","parameters":[{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","required":false,"name":"include","default":""},{"type":"struct","hint":"The properties you want to set on the object (can also be passed in as named arguments).","required":false,"name":"properties","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"boolean","hint":"Whether or not to instantiate the object(s) first. When objects are not instantiated, any callbacks and validations set on them will be skipped.","required":false,"name":"instantiate","default":false},{"type":"struct","hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","required":false,"name":"useIndex","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to skip validations for this operation.","required":false,"name":"validate","default":"true"},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":"true"},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"}],"name":"updateAll","tags":{"category":"Update Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"updatefunctions"}},{"returntype":"boolean","slug":"model.updateByKey","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Update a post using a positional key and a params struct\nresult = model(&quot;post&quot;).updateByKey(33, params.post);\n\n// 2. Update a post using named arguments\nresult = model(&quot;post&quot;).updateByKey(key=33, title=&quot;New version of Wheels just released&quot;, published=1);\n\n// 3. Skip validations when updating a record (useful for admin operations)\nresult = model(&quot;post&quot;).updateByKey(key=33, validate=false, status=&quot;archived&quot;);\n\n// 4. Include soft-deleted records when looking up the key to update\nresult = model(&quot;post&quot;).updateByKey(key=33, includeSoftDeletes=true, restoredAt=Now());\n</code></pre>","hasExtended":true},"hint":"Finds the object with the supplied <code>key</code> and saves it (if validation permits it) with the supplied <code>properties</code> and / or named arguments.\nProperty names and values can be passed in either using named arguments or as a struct to the <code>properties</code> argument.\nReturns <code>true</code> if the object was found and updated successfully, <code>false</code> otherwise.\n\n","parameters":[{"type":"any","hint":"Primary key value(s) of the record to fetch. Separate with comma if passing in multiple primary key values. Accepts a string, list, or a numeric value.","required":true,"name":"key"},{"type":"struct","hint":"The properties you want to set on the object (can also be passed in as named arguments).","required":false,"name":"properties","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"boolean","hint":"Set to `false` to skip validations for this operation.","required":false,"name":"validate","default":"true"},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":"true"},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"false"}],"name":"updateByKey","tags":{"category":"Update Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"updatefunctions"}},{"returntype":"boolean","slug":"model.updateOne","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Update the most recently released product by setting its `featured` flag\nresult = model(&quot;Product&quot;).updateOne(order=&quot;releaseDate DESC&quot;, featured=1);\n\n// 2. Update a specific record matching a `where` clause\nresult = model(&quot;Order&quot;).updateOne(where=&quot;status='pending' AND createdAt &lt; '#DateAdd('d', -7, Now())#'&quot;, status=&quot;expired&quot;);\n\n// 3. Skip validations when updating, e.g. to force a status change\nresult = model(&quot;Article&quot;).updateOne(where=&quot;status='draft'&quot;, order=&quot;createdAt ASC&quot;, status=&quot;published&quot;, validate=false);\n\n// 4. Scoped call via a `hasOne` association (calls `updateOne` internally)\n// Given `hasOne(name=&quot;profile&quot;)` on the User model:\naUser = model(&quot;User&quot;).findByKey(params.userId);\naUser.removeProfile();\n</code></pre>","hasExtended":true},"hint":"Gets an object based on the arguments used and updates it with the supplied <code>properties</code>.\nReturns <code>true</code> if an object was found and updated successfully, <code>false</code> otherwise.\n\n","parameters":[{"type":"string","hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"where","default":""},{"type":"string","hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","required":false,"name":"order","default":""},{"type":"struct","hint":"The properties you want to set on the object (can also be passed in as named arguments).","required":false,"name":"properties","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","required":false,"name":"reload","default":false},{"type":"boolean","hint":"Set to `false` to skip validations for this operation.","required":false,"name":"validate","default":"true"},{"type":"struct","hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","required":false,"name":"useIndex","default":"[runtime expression]"},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":"true"},{"type":"boolean","required":false,"name":"includeSoftDeletes","default":"false"}],"name":"updateOne","tags":{"category":"Update Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"updatefunctions"}},{"returntype":"boolean","slug":"model.updateProperty","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Set a boolean flag on an existing record (the primary use case)\nproduct = model(&quot;Product&quot;).findByKey(56);\nproduct.updateProperty(&quot;new&quot;, 1);\n\n// 2. Mark a user account as active without triggering validations\nuser = model(&quot;User&quot;).findByKey(params.userId);\nuser.updateProperty(&quot;active&quot;, true);\n\n// 3. Update a property and skip callbacks\npost = model(&quot;Post&quot;).findByKey(params.id);\npost.updateProperty(property=&quot;featured&quot;, value=true, callbacks=false);\n</code></pre>","hasExtended":true},"hint":"Updates a single <code>property</code> and saves the record without going through the normal validation procedure.\nThis is especially useful for boolean flags on existing records.\n\n","parameters":[{"type":"string","hint":"Name of the property to update the value for globally.","required":false,"name":"property"},{"type":"any","hint":"Value to set on the given property globally.","required":false,"name":"value"},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":"true"}],"name":"updateProperty","tags":{"category":"CRUD Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"crudfunctions"}},{"returntype":"void","slug":"migration.updateRecord","availableIn":["migration"],"extended":{"docs":"<pre><code class='javascript'>// 1. Update a single column for all rows in a table\nupdateRecord(\n    table = &quot;settings&quot;,\n    value = &quot;My Updated App&quot;\n);\n\n// 2. Update specific columns using a where clause to target matching rows\nupdateRecord(\n    table = &quot;users&quot;,\n    where = &quot;role = 'guest'&quot;,\n    active = false\n);\n\n// 3. Update multiple columns during a migration's up() function\ncomponent extends=&quot;wheels.migrator.Migration&quot; {\n    function up() {\n        updateRecord(\n            table = &quot;users&quot;,\n            where = &quot;id = 1&quot;,\n            firstName = &quot;Bruce&quot;,\n            lastName = &quot;Wayne&quot;,\n            email = &quot;bruce@wayneenterprises.com&quot;\n        );\n    }\n    function down() {\n        updateRecord(\n            table = &quot;users&quot;,\n            where = &quot;id = 1&quot;,\n            firstName = &quot;Clark&quot;,\n            lastName = &quot;Kent&quot;,\n            email = &quot;clark@dailyplanet.com&quot;\n        );\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Updates an existing record in a table\nOnly available in a migration CFC\n\n","parameters":[{"type":"string","hint":"The table name where the record is","required":true,"name":"table"},{"type":"string","hint":"The where clause, i.e admin = 1","required":false,"name":"where","default":""}],"name":"updateRecord","tags":{"category":"Migration Functions","sectionClass":"migrator","section":"Migrator","categoryClass":"migrationfunctions"}},{"returntype":"struct","slug":"model.upsertAll","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Upsert a batch of products using their SKU as the unique constraint\nrecords = [\n    {sku: &quot;WIDGET-001&quot;, name: &quot;Widget Standard&quot;, price: 9.99, stock: 100},\n    {sku: &quot;WIDGET-002&quot;, name: &quot;Widget Deluxe&quot;,   price: 19.99, stock: 50},\n    {sku: &quot;GADGET-001&quot;, name: &quot;Gadget Pro&quot;,       price: 49.99, stock: 25}\n];\nresult = model(&quot;Product&quot;).upsertAll(records=records, uniqueBy=&quot;sku&quot;);\n// result -&gt; {upsertedCount: 3}\n\n// 2. Upsert with a composite unique constraint (e.g., userId + date for daily stats)\nstats = [\n    {userId: 1, reportDate: &quot;2024-06-01&quot;, pageViews: 42, clicks: 7},\n    {userId: 2, reportDate: &quot;2024-06-01&quot;, pageViews: 18, clicks: 3}\n];\nresult = model(&quot;DailyStat&quot;).upsertAll(records=stats, uniqueBy=&quot;userId,reportDate&quot;);\n// result -&gt; {upsertedCount: 2}\n\n// 3. Upsert without automatic timestamps (e.g., when importing legacy data)\nimports = [\n    {externalId: &quot;EXT-100&quot;, title: &quot;Legacy Record A&quot;, status: &quot;active&quot;},\n    {externalId: &quot;EXT-101&quot;, title: &quot;Legacy Record B&quot;, status: &quot;archived&quot;}\n];\nresult = model(&quot;ImportedRecord&quot;).upsertAll(\n    records    = imports,\n    uniqueBy   = &quot;externalId&quot;,\n    timestamps = false\n);\n// result -&gt; {upsertedCount: 2}\n</code></pre>","hasExtended":true},"hint":"Inserts or updates multiple records in a single batch operation (upsert).\nUses database-specific conflict resolution syntax (e.g., <code>ON CONFLICT ... DO UPDATE</code> for PostgreSQL/SQLite).\nThe <code>uniqueBy</code> argument specifies which properties form the unique constraint for conflict detection.\n\n","parameters":[{"type":"array","hint":"Array of structs, each containing property name/value pairs.","required":true,"name":"records"},{"type":"string","hint":"Comma-delimited list of property names that form the unique constraint for conflict detection.","required":true,"name":"uniqueBy"},{"type":"boolean","hint":"Set to `false` to skip automatic `createdAt`/`updatedAt` timestamping.","required":false,"name":"timestamps","default":true},{"type":"string","hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","required":false,"name":"transaction","default":"[runtime expression]"},{"type":"any","hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","required":false,"name":"parameterize","default":true}],"name":"upsertAll","tags":{"category":"Create Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"createfunctions"}},{"returntype":"string","slug":"controller.urlField","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic URL field bound to an object property\n#urlField(objectName=&quot;profile&quot;, property=&quot;websiteUrl&quot;)#\n\n// 2. URL field with a custom label and a CSS class\n#urlField(label=&quot;Website URL&quot;, objectName=&quot;profile&quot;, property=&quot;websiteUrl&quot;, class=&quot;form-control&quot;)#\n\n// 3. Nested URL field for a contacts association (hasMany)\n&lt;cfloop from=&quot;1&quot; to=&quot;#ArrayLen(company.contacts)#&quot; index=&quot;i&quot;&gt;\n\t#urlField(label=&quot;Contact Website ##i#&quot;, objectName=&quot;company&quot;, association=&quot;contacts&quot;, position=i, property=&quot;websiteUrl&quot;)#\n&lt;/cfloop&gt;\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a URL field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"any","hint":"The variable name of the object to build the form control for.","required":true,"name":"objectName"},{"type":"string","hint":"The name of the property to use in the form control.","required":true,"name":"property"},{"type":"string","hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","required":false,"name":"association"},{"type":"string","hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","required":false,"name":"position"},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":"useDefaultLabel"},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"string","hint":"HTML tag to wrap the form control with when the object contains errors.","required":false,"name":"errorElement","default":"span"},{"type":"string","hint":"The class name of the HTML tag that wraps the form control when there are errors.","required":false,"name":"errorClass","default":"field-with-errors"},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"urlField","tags":{"category":"Form Object Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formobjectfunctions"}},{"returntype":"string","slug":"controller.urlFieldTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic URL field with a label\n#urlFieldTag(name=&quot;website&quot;, label=&quot;Website&quot;)#\n\n// 2. Pre-filled with a value from params and a placeholder attribute\n#urlFieldTag(name=&quot;homepage&quot;, label=&quot;Homepage&quot;, value=params.homepage, placeholder=&quot;https://example.com&quot;)#\n\n// 3. Label placed before the field with an extra CSS class\n#urlFieldTag(name=&quot;profileUrl&quot;, label=&quot;Profile URL&quot;, labelPlacement=&quot;before&quot;, class=&quot;form-control&quot;)#\n\n// 4. Field wrapped with markup using prepend and append\n#urlFieldTag(name=&quot;website&quot;, label=&quot;Website&quot;, prepend=&quot;&lt;div class=&quot;&quot;input-group&quot;&quot;&gt;&quot;, append=&quot;&lt;/div&gt;&quot;)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a URL field form control based on the supplied name.\nNote: Pass any additional arguments like <code>class</code>, <code>rel</code>, and <code>id</code>, and the generated tag will also include those values as HTML attributes.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"Value to populate in tag's value attribute.","required":false,"name":"value","default":""},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true}],"name":"urlFieldTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}},{"returntype":"string","slug":"controller.URLFor","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Create the URL for the `logOut` action on the `account` controller, typically resulting in `/account/log-out`\nurlFor(controller=&quot;account&quot;, action=&quot;logOut&quot;)\n\n// 2. Create a URL with an anchor appended to it\nurlFor(action=&quot;comments&quot;, anchor=&quot;comment10&quot;)\n\n// 3. Create a URL based on a named route that expects `categorySlug` and `productSlug` params\nurlFor(route=&quot;product&quot;, categorySlug=&quot;accessories&quot;, productSlug=&quot;battery-charger&quot;)\n\n// 4. Generate an absolute URL (including protocol and host) to use in an email or external link\nurlFor(controller=&quot;account&quot;, action=&quot;confirm&quot;, key=user.key(), onlyPath=false, protocol=&quot;https&quot;)\n\n// 5. Append extra query string params not covered by the route pattern\nurlFor(controller=&quot;products&quot;, action=&quot;index&quot;, params=&quot;sort=price&amp;dir=asc&quot;)\n</code></pre>","hasExtended":true},"hint":"Creates an internal URL based on supplied arguments.\n\n","parameters":[{"type":"string","hint":"Name of a route that you have configured in `config/routes.cfm`.","required":false,"name":"route","default":""},{"type":"string","hint":"Name of the controller to include in the URL.","required":false,"name":"controller","default":""},{"type":"string","hint":"Name of the action to include in the URL.","required":false,"name":"action","default":""},{"type":"any","hint":"Key(s) to include in the URL.","required":false,"name":"key","default":""},{"type":"string","hint":"Any additional parameters to be set in the query string (example: `wheels=cool&x=y`). Please note that Wheels uses the `&` and `=` characters to split the parameters and encode them properly for you. However, if you need to pass in `&` or `=` as part of the value, then you need to encode them (and only them), example: `a=cats%26dogs%3Dtrouble!&b=1`.","required":false,"name":"params","default":""},{"type":"string","hint":"Sets an anchor name to be appended to the path.","required":false,"name":"anchor","default":""},{"type":"boolean","hint":"If `true`, returns only the relative URL (no protocol, host name or port).","required":false,"name":"onlyPath","default":true},{"type":"string","hint":"Set this to override the current host.","required":false,"name":"host","default":""},{"type":"string","hint":"Set this to override the current protocol.","required":false,"name":"protocol","default":""},{"type":"numeric","hint":"Set this to override the current port number.","required":false,"name":"port","default":0},{"type":"boolean","hint":"Encode URL parameters using `EncodeForURL()`. Please note that this does not make the string safe for placement in HTML attributes, for that you need to wrap the result in `EncodeForHtmlAttribute()` or use `linkTo()`, `startFormTag()` etc instead.","required":false,"name":"encode","default":true},{"type":"boolean","required":false,"name":"$encodeForHtmlAttribute","default":false},{"type":"string","required":false,"name":"$URLRewriting","default":"[runtime expression]"}],"name":"URLFor","tags":{"category":"Miscellaneous Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"miscellaneousfunctions"}},{"returntype":"void","slug":"controller.usesLayout","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Use a custom layout for the entire controller, except for one action.\n// Declared inside the controller's config() function.\nusesLayout(template=&quot;myLayout&quot;, except=&quot;myAjax&quot;);\n\n// 2. Apply a custom layout only to specific actions; all other actions\n// use the default layout.cfm.\nusesLayout(template=&quot;myLayout&quot;, only=&quot;termsOfService,shippingPolicy&quot;);\n\n// 3. Serve a lightweight layout for AJAX requests while normal requests\n// still receive the full layout.\nusesLayout(template=&quot;myLayout&quot;, ajax=&quot;ajaxLayout&quot;);\n\n// 4. Delegate layout selection to a private function. The function receives\n// the current action name and should return the layout template name or\n// true to fall back to the default layout.cfm.\nusesLayout(&quot;chooseLayout&quot;);\n\n// Example chooseLayout() function in the same controller:\n// private function chooseLayout(action) {\n//   if (action == &quot;print&quot;) return &quot;printLayout&quot;;\n//   return true; // fall back to default layout.cfm\n// }\n\n// 5. Use a function-based layout but fall back to layout.cfm when the\n// function returns nothing (useDefault defaults to true).\nusesLayout(template=&quot;chooseLayout&quot;, useDefault=true);\n</code></pre>","hasExtended":true},"hint":"Used within a controller's <code>config()</code> function to specify controller- or action-specific layouts.\n\n","parameters":[{"type":"string","hint":"Name of the layout template or function name you want to use.","required":true,"name":"template"},{"type":"string","hint":"Name of the layout template you want to use for AJAX requests.","required":false,"name":"ajax","default":""},{"type":"string","hint":"List of actions that should not get the layout.","required":false,"name":"except"},{"type":"string","hint":"List of actions that should only get the layout.","required":false,"name":"only"},{"type":"boolean","hint":"When specifying conditions or a function, pass in `true` to use the default `layout.cfm` if none of the conditions are met.","required":false,"name":"useDefault","default":true}],"name":"usesLayout","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"boolean","slug":"model.valid","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Check if a new user object passes validation before proceeding\nuser = model(&quot;User&quot;).new(params.user);\n\nif (user.valid()) {\n    // object passed all validations, safe to proceed\n    redirectTo(action=&quot;dashboard&quot;);\n} else {\n    renderView(action=&quot;new&quot;);\n}\n\n// 2. Validate without running before/after validation callbacks\nuser = model(&quot;User&quot;).new(params.user);\n\nif (user.valid(callbacks=false)) {\n    user.save(callbacks=false);\n}\n\n// 3. Validate the object and any associated (nested) objects together\norder = model(&quot;Order&quot;).new(params.order);\n\nif (order.valid(validateAssociations=true)) {\n    order.save();\n} else {\n    // errors may include issues from associated line items\n    writeOutput(order.errorsAsHTML());\n}\n</code></pre>","hasExtended":true},"hint":"Runs the validation on the object and returns <code>true</code> if it passes it.\nWheels will run the validation process automatically whenever an object is saved to the database, but sometimes it's useful to be able to run this method to see if the object is valid without saving it to the database.\n\n","parameters":[{"type":"boolean","hint":"Set to `false` to disable callbacks for this method.","required":false,"name":"callbacks","default":"true"},{"type":"boolean","required":false,"name":"validateAssociations","default":false}],"name":"valid","tags":{"category":"Error Functions","sectionClass":"modelobject","section":"Model Object","categoryClass":"errorfunctions"}},{"returntype":"void","slug":"model.validate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a custom validation method to run on every save\nfunction config() {\n\t// `checkPhoneNumber` will be called whenever an object is created or updated.\n\tvalidate(&quot;checkPhoneNumber&quot;);\n}\n\nfunction checkPhoneNumber() {\n\t// Make sure the area code is `614`.\n\treturn Left(this.phoneNumber, 3) == &quot;614&quot;;\n}\n\n// 2. Register multiple custom validation methods at once\nfunction config() {\n\tvalidate(methods=&quot;checkPhoneNumber,checkEmailDomain&quot;);\n}\n\n// 3. Limit validation to create or update only\nfunction config() {\n\t// Only run `checkTrialExpiry` when updating an existing record.\n\tvalidate(methods=&quot;checkTrialExpiry&quot;, when=&quot;onUpdate&quot;);\n}\n\n// 4. Run a custom validation only when a condition is met\nfunction config() {\n\t// `checkBillingAddress` is skipped when the order is free.\n\tvalidate(methods=&quot;checkBillingAddress&quot;, condition=&quot;this.totalAmount gt 0&quot;);\n}\n\n// 5. Skip a custom validation when an `unless` expression is true\nfunction config() {\n\t// `checkCreditCard` is skipped for admin users.\n\tvalidate(methods=&quot;checkCreditCard&quot;, unless=&quot;this.isAdmin&quot;);\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called to validate objects before they are saved.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names to call. Can also be called with the `method` argument.","required":false,"name":"methods","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"}],"name":"validate","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validateOnCreate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a custom method to validate new objects before insert\nfunction config() {\n\t// `checkPhoneNumber` will only be called when creating a new record.\n\tvalidateOnCreate(&quot;checkPhoneNumber&quot;);\n}\n\nfunction checkPhoneNumber() {\n\t// Make sure area code is `614`.\n\treturn Left(this.phoneNumber, 3) == &quot;614&quot;;\n}\n\n// 2. Register multiple validation methods at once\nfunction config() {\n\tvalidateOnCreate(&quot;checkPhoneNumber,checkReferralCode&quot;);\n}\n\nfunction checkPhoneNumber() {\n\treturn Left(this.phoneNumber, 3) == &quot;614&quot;;\n}\n\nfunction checkReferralCode() {\n\tif (Len(this.referralCode) &amp;&amp; !isValidReferral(this.referralCode)) {\n\t\taddError(property=&quot;referralCode&quot;, message=&quot;Invalid referral code.&quot;);\n\t}\n}\n\n// 3. Only run the validation when a condition is met\nfunction config() {\n\t// Only validate the phone number on create when the user is in the US.\n\tvalidateOnCreate(methods=&quot;checkPhoneNumber&quot;, condition=&quot;this.country eq 'US'&quot;);\n}\n\nfunction checkPhoneNumber() {\n\treturn IsNumeric(this.phoneNumber);\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called to validate new objects before they are inserted.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names to call. Can also be called with the `method` argument.","required":false,"name":"methods","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""}],"name":"validateOnCreate","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validateOnUpdate","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Register a single custom validation method to run only on updates\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tvalidateOnUpdate(&quot;checkPhoneNumber&quot;);\n\t}\n\n\tprivate boolean function checkPhoneNumber() {\n\t\t// Make sure area code is 614\n\t\treturn Left(this.phoneNumber, 3) == &quot;614&quot;;\n\t}\n}\n\n// 2. Register multiple custom validation methods for updates\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tvalidateOnUpdate(methods=&quot;checkStatus,checkExpiry&quot;);\n\t}\n\n\tprivate boolean function checkStatus() {\n\t\treturn ListFindNoCase(&quot;active,pending,suspended&quot;, this.status);\n\t}\n\n\tprivate boolean function checkExpiry() {\n\t\treturn this.expiresAt &gt; Now();\n\t}\n}\n\n// 3. Only validate when a condition is met (run only for premium accounts)\ncomponent extends=&quot;Model&quot; {\n\tfunction config() {\n\t\tvalidateOnUpdate(methods=&quot;checkBillingAddress&quot;, condition=&quot;this.accountType eq 'premium'&quot;);\n\t}\n\n\tprivate boolean function checkBillingAddress() {\n\t\treturn Len(Trim(this.billingAddress)) GT 0;\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Registers method(s) that should be called to validate existing objects before they are updated.\n\n","parameters":[{"type":"string","hint":"Method name or list of method names to call. Can also be called with the `method` argument.","required":false,"name":"methods","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""}],"name":"validateOnUpdate","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validatesConfirmationOf","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Require a confirmed password when creating a new user account\n// The form should include a `passwordConfirmation` field that the user types their password into a second time\nvalidatesConfirmationOf(property=&quot;password&quot;, when=&quot;onCreate&quot;, message=&quot;Your password and its confirmation do not match. Please try again.&quot;);\n\n// 2. Confirm an email address on every save (default `when=&quot;onSave&quot;`)\n// A matching `emailConfirmation` property must be set on the object before saving\nvalidatesConfirmationOf(property=&quot;email&quot;);\n\n// 3. Confirm multiple properties and use a case-sensitive comparison\n// Both `passwordConfirmation` and `pinConfirmation` must match exactly (including letter case)\nvalidatesConfirmationOf(properties=&quot;password,pin&quot;, caseSensitive=true);\n</code></pre>","hasExtended":true},"hint":"Validates that the value of the specified property also has an identical confirmation value.\nThis is common when having a user type in their email address a second time to confirm, confirming a password by typing it a second time, etc.\nThe confirmation value only exists temporarily and never gets saved to the database.\nBy convention, the confirmation property has to be named the same as the property with \"Confirmation\" appended at the end.\nUsing the password example, to confirm our password property, we would create a property called <code>passwordConfirmation</code>.\n\n","parameters":[{"type":"string","hint":"Name of property or list of property names to validate against (can also be called with the `property` argument).","required":false,"name":"properties","default":""},{"type":"string","hint":"Supply a custom error message here to override the built-in one.","required":false,"name":"message","default":"[property] should match confirmation"},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""},{"type":"boolean","hint":"Ensure the confirmed property comparison is case sensitive","required":false,"name":"caseSensitive","default":false}],"name":"validatesConfirmationOf","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validatesExclusionOf","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Prevent reserved words from being saved as a programming language name\nvalidatesExclusionOf(property=&quot;language&quot;, list=&quot;php,fortran&quot;, message=&quot;[property] is reserved. Try a real language.&quot;);\n\n// 2. Validate multiple properties against the same exclusion list (e.g. reserved usernames)\nvalidatesExclusionOf(properties=&quot;username,displayName&quot;, list=&quot;admin,root,superuser,moderator&quot;);\n\n// 3. Only enforce the exclusion on create, and skip validation when the value is blank\nvalidatesExclusionOf(property=&quot;referralCode&quot;, list=&quot;FREE,GRATIS,FREEBIE&quot;, when=&quot;onCreate&quot;, allowBlank=true);\n\n// 4. Conditionally enforce the exclusion based on a model property\nvalidatesExclusionOf(property=&quot;status&quot;, list=&quot;banned,suspended&quot;, condition=&quot;this.isAdmin&quot;);\n</code></pre>","hasExtended":true},"hint":"Validates that the value of the specified property does not exist in the supplied list.\n\n","parameters":[{"type":"string","hint":"Name of property or list of property names to validate against (can also be called with the `property` argument).","required":false,"name":"properties","default":""},{"type":"string","hint":"Single value or list of values that should not be allowed.","required":true,"name":"list"},{"type":"string","hint":"Supply a custom error message here to override the built-in one.","required":false,"name":"message","default":"[property] is reserved"},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"},{"type":"boolean","hint":"If set to `true`, validation will be skipped if the property value is an empty string or doesn't exist at all. This is useful if you only want to run this validation after it passes the `validatesPresenceOf` test, thus avoiding duplicate error messages if it doesn't.","required":false,"name":"allowBlank","default":false},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""}],"name":"validatesExclusionOf","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validatesFormatOf","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Validate that a credit card number is in the correct format\nvalidatesFormatOf(property=&quot;creditCard&quot;, type=&quot;creditcard&quot;);\n\n// 2. Validate an email address using a regular expression\nvalidatesFormatOf(property=&quot;email&quot;, type=&quot;email&quot;);\n\n// 3. Validate a US phone number with a custom regex and allow blank values\nvalidatesFormatOf(\n\tproperty=&quot;phone&quot;,\n\tregEx=&quot;^\\d{3}-\\d{3}-\\d{4}$&quot;,\n\tallowBlank=true,\n\tmessage=&quot;[property] must be in the format 555-867-5309.&quot;\n);\n\n// 4. Validate that an email ends with `.se` only when a condition is met and it's not Sunday\nvalidatesFormatOf(\n\tproperty=&quot;email&quot;,\n\tregEx=&quot;^.*@.*\\.se$&quot;,\n\tcondition=&quot;ipCheck()&quot;,\n\tunless=&quot;DayOfWeek() eq 1&quot;,\n\tmessage=&quot;Sorry, you must have a Swedish email address to use this website.&quot;\n);\n</code></pre>","hasExtended":true},"hint":"Validates that the value of the specified property is formatted correctly by matching it against a regular expression using the regEx argument and / or against a built-in CFML validation type using the type argument (creditcard, date, email, etc.).\n\n","parameters":[{"type":"string","hint":"Name of property or list of property names to validate against (can also be called with the `property` argument).","required":false,"name":"properties","default":""},{"type":"string","hint":"Regular expression to verify against.","required":false,"name":"regEx","default":""},{"type":"string","hint":"One of the following types to verify against: creditcard, date, email, eurodate, guid, social_security_number, ssn, telephone, time, URL, USdate, UUID, variableName, zipcode (will be passed through to your CFML engine's IsValid() function).","required":false,"name":"type","default":""},{"type":"string","hint":"Supply a custom error message here to override the built-in one.","required":false,"name":"message","default":"[property] is invalid"},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"},{"type":"boolean","hint":"If set to `true`, validation will be skipped if the property value is an empty string or doesn't exist at all. This is useful if you only want to run this validation after it passes the `validatesPresenceOf` test, thus avoiding duplicate error messages if it doesn't.","required":false,"name":"allowBlank","default":false},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""}],"name":"validatesFormatOf","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validatesInclusionOf","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Validate that a user selects a valid framework choice\nvalidatesInclusionOf(property=&quot;frameworkOfChoice&quot;, list=&quot;cfwheels,rails,django&quot;, message=&quot;Please select a supported framework.&quot;);\n\n// 2. Validate a status field and skip validation if the value is blank\nvalidatesInclusionOf(property=&quot;status&quot;, list=&quot;active,inactive,pending&quot;, allowBlank=true);\n\n// 3. Validate a role only when creating a new record\nvalidatesInclusionOf(property=&quot;role&quot;, list=&quot;admin,editor,viewer&quot;, when=&quot;onCreate&quot;);\n\n// 4. Validate a priority field only when a condition is met\nvalidatesInclusionOf(property=&quot;priority&quot;, list=&quot;low,medium,high&quot;, condition=&quot;this.isAssigned()&quot;);\n</code></pre>","hasExtended":true},"hint":"Validates that the value of the specified property exists in the supplied list.\n\n","parameters":[{"type":"string","hint":"Name of property or list of property names to validate against (can also be called with the `property` argument).","required":false,"name":"properties","default":""},{"type":"string","hint":"List of allowed values.","required":true,"name":"list"},{"type":"string","hint":"Supply a custom error message here to override the built-in one.","required":false,"name":"message","default":"[property] is not included in the list"},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"},{"type":"boolean","hint":"If set to `true`, validation will be skipped if the property value is an empty string or doesn't exist at all. This is useful if you only want to run this validation after it passes the `validatesPresenceOf` test, thus avoiding duplicate error messages if it doesn't.","required":false,"name":"allowBlank","default":false},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""}],"name":"validatesInclusionOf","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validatesLengthOf","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Validate a maximum length on multiple properties, using [property] in the\n// message so the property label is injected dynamically at runtime\nvalidatesLengthOf(\n    properties=&quot;firstName,lastName&quot;,\n    maximum=50,\n    message=&quot;Please shorten your [property] (50 characters max).&quot;\n);\n\n// 2. Validate that a password falls within a range of character lengths\nvalidatesLengthOf(\n    property=&quot;password&quot;,\n    within=&quot;4,20&quot;,\n    message=&quot;The password must be between 4 and 20 characters.&quot;\n);\n\n// 3. Validate an exact length only on create, skipping blank values\nvalidatesLengthOf(\n    property=&quot;postalCode&quot;,\n    exactly=5,\n    when=&quot;onCreate&quot;,\n    allowBlank=true,\n    message=&quot;Postal code must be exactly 5 characters.&quot;\n);\n</code></pre>","hasExtended":true},"hint":"Validates that the value of the specified property matches the length requirements supplied.\nUse the <code>exactly</code>, <code>maximum</code>, <code>minimum</code> and <code>within</code> arguments to specify the length requirements.\n\n","parameters":[{"type":"string","hint":"Name of property or list of property names to validate against (can also be called with the `property` argument).","required":false,"name":"properties","default":""},{"type":"string","hint":"Supply a custom error message here to override the built-in one.","required":false,"name":"message","default":"[property] is the wrong length"},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"},{"type":"boolean","hint":"If set to `true`, validation will be skipped if the property value is an empty string or doesn't exist at all. This is useful if you only want to run this validation after it passes the `validatesPresenceOf` test, thus avoiding duplicate error messages if it doesn't.","required":false,"name":"allowBlank","default":false},{"type":"numeric","hint":"The exact length that the property value must be.","required":false,"name":"exactly","default":0},{"type":"numeric","hint":"The maximum length that the property value can be.","required":false,"name":"maximum","default":0},{"type":"numeric","hint":"The minimum length that the property value can be.","required":false,"name":"minimum","default":0},{"type":"string","hint":"A list of two values (minimum and maximum) that the length of the property value must fall within.","required":false,"name":"within","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""}],"name":"validatesLengthOf","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validatesNumericalityOf","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Validate that the `age` property is a number\nvalidatesNumericalityOf(property=&quot;age&quot;);\n\n// 2. Validate that the `score` property is a whole number (no decimals), allowing blank so that\n// records can be saved without a score (resulting in a NULL in the database)\nvalidatesNumericalityOf(property=&quot;score&quot;, onlyInteger=true, allowBlank=true, message=&quot;Please enter a whole number for score.&quot;);\n\n// 3. Validate that a `price` value is greater than zero and no more than 10000\nvalidatesNumericalityOf(property=&quot;price&quot;, greaterThan=0, lessThanOrEqualTo=10000);\n\n// 4. Validate that `quantity` is at least 1, is an integer, and only on create\nvalidatesNumericalityOf(property=&quot;quantity&quot;, onlyInteger=true, greaterThanOrEqualTo=1, when=&quot;onCreate&quot;);\n\n// 5. Validate that `rating` must be exactly 5 only when a condition is met\nvalidatesNumericalityOf(property=&quot;rating&quot;, equalTo=5, condition=&quot;this.isPerfect()&quot;);\n\n// 6. Validate that `luckyNumber` is an odd number\nvalidatesNumericalityOf(property=&quot;luckyNumber&quot;, odd=true, message=&quot;[property] must be an odd number.&quot;);\n</code></pre>","hasExtended":true},"hint":"Validates that the value of the specified property is numeric.\n\n","parameters":[{"type":"string","hint":"Name of property or list of property names to validate against (can also be called with the `property` argument).","required":false,"name":"properties","default":""},{"type":"string","hint":"Supply a custom error message here to override the built-in one.","required":false,"name":"message","default":"[property] is not a number"},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"},{"type":"boolean","hint":"If set to `true`, validation will be skipped if the property value is an empty string or doesn't exist at all. This is useful if you only want to run this validation after it passes the `validatesPresenceOf` test, thus avoiding duplicate error messages if it doesn't.","required":false,"name":"allowBlank","default":false},{"type":"boolean","hint":"Specifies whether the property value must be an integer.","required":false,"name":"onlyInteger","default":false},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""},{"type":"boolean","required":false,"name":"odd","default":""},{"type":"boolean","required":false,"name":"even","default":""},{"type":"numeric","hint":"Specifies whether or not the value must be greater than the supplied value.","required":false,"name":"greaterThan","default":""},{"type":"numeric","hint":"Specifies whether or not the value must be greater than or equal the supplied value.","required":false,"name":"greaterThanOrEqualTo","default":""},{"type":"numeric","hint":"Specifies whether or not the value must be equal to the supplied value.","required":false,"name":"equalTo","default":""},{"type":"numeric","hint":"Specifies whether or not the value must be less than the supplied value.","required":false,"name":"lessThan","default":""},{"type":"numeric","hint":"Specifies whether or not the value must be less than or equal the supplied value.","required":false,"name":"lessThanOrEqualTo","default":""}],"name":"validatesNumericalityOf","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validatesPresenceOf","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Require a single property (must exist and not be blank)\nvalidatesPresenceOf(&quot;emailAddress&quot;);\n\n// 2. Require multiple properties at once\nvalidatesPresenceOf(properties=&quot;firstName,lastName,emailAddress&quot;);\n\n// 3. Supply a custom error message\nvalidatesPresenceOf(properties=&quot;title&quot;, message=&quot;A title is required.&quot;);\n\n// 4. Only validate on create (skip when updating an existing record)\nvalidatesPresenceOf(properties=&quot;password&quot;, when=&quot;onCreate&quot;);\n\n// 5. Conditionally require a property based on another property value\nvalidatesPresenceOf(properties=&quot;companyName&quot;, condition=&quot;this.accountType eq 'business'&quot;);\n\n// 6. Skip validation when a certain condition is true\nvalidatesPresenceOf(properties=&quot;bio&quot;, unless=&quot;this.isGuest()&quot;);\n</code></pre>","hasExtended":true},"hint":"Validates that the specified property exists and that its value is not blank.\n\n","parameters":[{"type":"string","hint":"Name of property or list of property names to validate against (can also be called with the `property` argument).","required":false,"name":"properties","default":""},{"type":"string","hint":"Supply a custom error message here to override the built-in one.","required":false,"name":"message","default":"[property] can't be empty"},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""}],"name":"validatesPresenceOf","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"void","slug":"model.validatesUniquenessOf","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Ensure no two users share the same username\nvalidatesUniquenessOf(property=&quot;username&quot;, message=&quot;Sorry, that username is already taken.&quot;);\n\n// 2. Scope uniqueness to an account — the same username is allowed in different accounts\nvalidatesUniquenessOf(property=&quot;username&quot;, scope=&quot;accountId&quot;);\n\n// 3. Validate multiple properties for uniqueness in one call\nvalidatesUniquenessOf(properties=&quot;email,username&quot;);\n\n// 4. Skip the check when the email field is blank (pair with validatesPresenceOf to avoid duplicate errors)\nvalidatesUniquenessOf(property=&quot;email&quot;, allowBlank=true);\n\n// 5. Only enforce uniqueness on create, not on update\nvalidatesUniquenessOf(property=&quot;slug&quot;, when=&quot;onCreate&quot;);\n\n// 6. Run the check only when a condition is true\nvalidatesUniquenessOf(property=&quot;referralCode&quot;, condition=&quot;this.isAffiliate()&quot;);\n\n// 7. Exclude soft-deleted records from the uniqueness check so a previously-deleted value can be reused\nvalidatesUniquenessOf(property=&quot;username&quot;, includeSoftDeletes=false);\n</code></pre>","hasExtended":true},"hint":"Validates that the value of the specified property is unique in the database table.\nUseful for ensuring that two users can't sign up to a website with identical usernames for example.\nWhen a new record is created, a check is made to make sure that no record already exists in the database table with the given value for the specified property.\nWhen the record is updated, the same check is made but disregarding the record itself.\n\n","parameters":[{"type":"string","hint":"Name of property or list of property names to validate against (can also be called with the `property` argument).","required":false,"name":"properties","default":""},{"type":"string","hint":"Supply a custom error message here to override the built-in one.","required":false,"name":"message","default":"[property] has already been taken"},{"type":"string","hint":"Pass in `onCreate` or `onUpdate` to limit when this validation occurs (by default validation will occur on both create and update, i.e. `onSave`).","required":false,"name":"when","default":"onSave"},{"type":"boolean","hint":"If set to `true`, validation will be skipped if the property value is an empty string or doesn't exist at all. This is useful if you only want to run this validation after it passes the `validatesPresenceOf` test, thus avoiding duplicate error messages if it doesn't.","required":false,"name":"allowBlank","default":false},{"type":"string","hint":"One or more properties by which to limit the scope of the uniqueness constraint.","required":false,"name":"scope","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `true` validation will run).","required":false,"name":"condition","default":""},{"type":"string","hint":"String expression to be evaluated that decides if validation will be run (if the expression returns `false` validation will run).","required":false,"name":"unless","default":""},{"type":"boolean","hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","required":false,"name":"includeSoftDeletes","default":"true"}],"name":"validatesUniquenessOf","tags":{"category":"Validation Functions","sectionClass":"modelconfiguration","section":"Model Configuration","categoryClass":"validationfunctions"}},{"returntype":"struct","slug":"model.validationInfo","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Inspect all validation rules defined on the User model\ninfo = model(&quot;User&quot;).validationInfo();\n// info is keyed by trigger: onSave, onCreate, onUpdate\n// Each key holds an array of rule structs, e.g.:\n// info.onSave[1] -&gt; {method: &quot;validatesPresenceOf&quot;, properties: &quot;email&quot;, message: &quot;can't be blank&quot;, ...}\n// info.onCreate -&gt; []\n// info.onUpdate -&gt; []\n\n// 2. Count how many rules fire on every save\ninfo = model(&quot;User&quot;).validationInfo();\nwriteOutput(&quot;Rules on save: &quot; &amp; arrayLen(info.onSave));\n\n// 3. List the validation methods used across all triggers\ninfo = model(&quot;User&quot;).validationInfo();\nfor (trigger in info) {\n    for (rule in info[trigger]) {\n        writeOutput(trigger &amp; &quot;: &quot; &amp; rule.method &amp; &quot; on &quot; &amp; rule.properties);\n    }\n}\n</code></pre>","hasExtended":true},"hint":"Returns a struct containing all validation rules for this model, keyed by trigger (<code>onSave</code>, <code>onCreate</code>, <code>onUpdate</code>).\nEach trigger contains an array of validation rule structs with <code>method</code>, <code>properties</code>, <code>message</code>, and other parameters.\n\n","parameters":[],"name":"validationInfo","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"any","slug":"model.validationTypeForProperty","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the validation type for a string column (e.g. firstName is varchar)\ntype = model(&quot;Employee&quot;).validationTypeForProperty(&quot;firstName&quot;);\n// type -&gt; &quot;string&quot;\n\n// 2. Get the validation type for a numeric column (e.g. salary is integer)\ntype = model(&quot;Employee&quot;).validationTypeForProperty(&quot;salary&quot;);\n// type -&gt; &quot;numeric&quot;\n\n// 3. Get the validation type for a date column (e.g. hireDate is a date/datetime column)\ntype = model(&quot;Employee&quot;).validationTypeForProperty(&quot;hireDate&quot;);\n// type -&gt; &quot;date&quot;\n\n// 4. Property does not exist on the model — returns &quot;string&quot; as the default\ntype = model(&quot;Employee&quot;).validationTypeForProperty(&quot;nonExistentProperty&quot;);\n// type -&gt; &quot;string&quot;\n</code></pre>","hasExtended":true},"hint":"Returns the validation type for the property.\n\n","parameters":[{"type":"string","hint":"Name of column to retrieve data for.","required":true,"name":"property"}],"name":"validationTypeForProperty","tags":{"category":"Miscellaneous Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"miscellaneousfunctions"}},{"returntype":"array","slug":"controller.verificationChain","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get verification chain, remove the first item, and set it back.\nmyVerificationChain = verificationChain();\narrayDeleteAt(myVerificationChain, 1);\nsetVerificationChain(myVerificationChain);\n\n// 2. Inspect the number of verifications registered on this controller.\nchain = verificationChain();\nwriteOutput(&quot;Verifications registered: &quot; &amp; arrayLen(chain));\n\n// 3. Loop over the chain to find verifications that apply to a specific action.\nchain = verificationChain();\nfor (item in chain) {\n\tif (listFindNoCase(item.only, &quot;create&quot;)) {\n\t\twriteOutput(&quot;Verification applies to create: &quot; &amp; serializeJSON(item));\n\t}\n}\n</code></pre>","hasExtended":true},"hint":"Returns an array of all the verifications set on this controller in the order in which they will be executed.\n\n","parameters":[],"name":"verificationChain","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"void","slug":"controller.verifies","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Verify that the `handleForm` action is always a POST request.\nverifies(only=&quot;handleForm&quot;, post=true);\n\n// 2. Verify that the `edit` action is a GET request, that `userId` exists in `params`, and that it is an integer.\nverifies(only=&quot;edit&quot;, get=true, params=&quot;userId&quot;, paramsTypes=&quot;integer&quot;);\n\n// 3. Same as above, but invoke a custom handler function on failure instead of aborting.\nverifies(only=&quot;edit&quot;, get=true, params=&quot;userId&quot;, paramsTypes=&quot;integer&quot;, handler=&quot;accessDenied&quot;);\n\n// 4. Same verification, but redirect to the `index` action with a flash error message on failure.\nverifies(only=&quot;edit&quot;, get=true, params=&quot;userId&quot;, paramsTypes=&quot;integer&quot;, action=&quot;index&quot;, error=&quot;Invalid userId&quot;);\n\n// 5. Verify that a session variable named `userId` exists for all actions except `login` and `register`.\nverifies(except=&quot;login,register&quot;, session=&quot;userId&quot;);\n\n// 6. Verify that the `subscribe` action is an AJAX POST request and that `email` exists in `params` as a valid email address.\nverifies(only=&quot;subscribe&quot;, ajax=true, post=true, params=&quot;email&quot;, paramsTypes=&quot;email&quot;);\n</code></pre>","hasExtended":true},"hint":"Instructs Wheels to verify that some specific criteria are met before running an action.\nNote that all undeclared arguments will be passed to <code>redirectTo()</code> call if a <code>handler</code> is not specified.\n\n","parameters":[{"type":"string","hint":"List of action names to limit this verification to.","required":false,"name":"only","default":""},{"type":"string","hint":"List of action names to exclude this verification from.","required":false,"name":"except","default":""},{"type":"any","hint":"Set to true to verify that this is a `POST` request.","required":false,"name":"post","default":""},{"type":"any","hint":"Set to true to verify that this is a `GET` request.","required":false,"name":"get","default":""},{"type":"any","hint":"Set to true to verify that this is an `AJAX` request.","required":false,"name":"ajax","default":""},{"type":"string","hint":"Verify that the passed in variable name exists in the cookie scope.","required":false,"name":"cookie","default":""},{"type":"string","hint":"Verify that the passed in variable name exists in the session scope.","required":false,"name":"session","default":""},{"type":"string","hint":"Verify that the passed in variable name exists in the params struct.","required":false,"name":"params","default":""},{"type":"string","hint":"Pass in the name of a function that should handle failed verifications. The default is to just abort the request when a verification fails.","required":false,"name":"handler","default":""},{"type":"string","hint":"List of types to check each listed cookie value against (will be passed through to your CFML engine's `IsValid` function).","required":false,"name":"cookieTypes","default":""},{"type":"string","hint":"List of types to check each list session value against (will be passed through to your CFML engine's `IsValid` function).","required":false,"name":"sessionTypes","default":""},{"type":"string","hint":"List of types to check each params value against (will be passed through to your CFML engine's `IsValid` function).","required":false,"name":"paramsTypes","default":""}],"name":"verifies","tags":{"category":"Configuration Functions","sectionClass":"controller","section":"Controller","categoryClass":"configurationfunctions"}},{"returntype":"struct","slug":"mapper.version","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\n// 1. Basic versioned API routes using api() and version() together\nmapper()\n    .api()\n        .version(number=1)\n            // Route name:  apiV1Users\n            // Example URL: /api/v1/users\n            .resources(&quot;users&quot;)\n        .end()\n\n        .version(number=2)\n            // Route name:  apiV2Users\n            // Example URL: /api/v2/users\n            .resources(&quot;users&quot;)\n        .end()\n    .end()\n.end();\n\n// 2. Using a callback to define routes within the version scope\nmapper()\n    .api(callback=function(r) {\n        r.version(number=1, callback=function(r) {\n            // Route name:  apiV1Products\n            // Example URL: /api/v1/products\n            r.resources(&quot;products&quot;);\n        });\n    })\n.end();\n\n// 3. Overriding the path and name prefixes\nmapper()\n    .api()\n        .version(number=1, path=&quot;version-one&quot;, name=&quot;versionOne&quot;)\n            // Route name:  apiVersionOneOrders\n            // Example URL: /api/version-one/orders\n            .resources(&quot;orders&quot;)\n        .end()\n    .end()\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Scope routes under a version prefix within an API group. Creates a URL path prefix of <code>v{number}</code> (e.g., <code>/api/v1/users</code>) and a name prefix of <code>v{number}</code> for named route generation.\n\n","parameters":[{"type":"numeric","hint":"The version number (e.g., `1` creates path prefix `v1`).","required":true,"name":"number"},{"type":"string","hint":"Override the path prefix. Defaults to `v{number}`.","required":false,"name":"path","default":"[runtime expression]"},{"type":"string","hint":"Override the name prefix. Defaults to `v{number}`.","required":false,"name":"name","default":"[runtime expression]"},{"type":"any","hint":"A callback function to define nested routes within this version scope.","required":false,"name":"callback"}],"name":"version","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"string","slug":"controller.viteAsset","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Get the resolved URL for a Vite JS entrypoint\n// In production, returns a fingerprinted path like &quot;/dist/assets/main-Dz8C9a3m.js&quot;\n// In development, returns the Vite dev server URL like &quot;http://localhost:5173/src/main.js&quot;\nassetUrl = viteAsset(&quot;src/main.js&quot;);\n\n// 2. Use the resolved URL directly in an image or font tag\nlogoUrl = viteAsset(&quot;src/images/logo.png&quot;);\nwriteOutput('&lt;img src=&quot;#logoUrl#&quot; alt=&quot;Logo&quot;&gt;');\n\n// 3. Resolve a CSS entrypoint URL for manual use (e.g. a preload hint)\ncssUrl = viteAsset(&quot;src/main.css&quot;);\nwriteOutput('&lt;link rel=&quot;preload&quot; as=&quot;style&quot; href=&quot;#cssUrl#&quot;&gt;');\n</code></pre>","hasExtended":true},"hint":"Returns the resolved URL for a Vite entrypoint. In production, reads the Vite manifest\nto return the fingerprinted asset path. In development, returns the Vite dev server URL.\n\n","parameters":[{"type":"string","hint":"The source entrypoint path as defined in your Vite config (e.g. \"src/main.js\").","required":true,"name":"entrypoint"}],"name":"viteAsset","tags":{"category":"Asset Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"assetfunctions"}},{"returntype":"string","slug":"controller.vitePreloadTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Emit modulepreload tags into &lt;head&gt; for a JS entrypoint (default behavior)\n// In production, injects &lt;link rel=&quot;modulepreload&quot;&gt; for the entrypoint and all\n// transitive chunk imports into &lt;head&gt;. Returns an empty string.\n// In development, returns an empty string (Vite handles modules dynamically).\nvitePreloadTag(&quot;src/main.js&quot;);\n\n// 2. Return modulepreload markup inline instead of injecting into &lt;head&gt;\n// Pass head=false to receive the raw HTML for manual placement, for example\n// inside a Turbo Drive hover-preload data attribute or a custom &lt;head&gt; partial.\npreloadMarkup = vitePreloadTag(entrypoint=&quot;src/main.js&quot;, head=false);\n// preloadMarkup -&gt; '&lt;link rel=&quot;modulepreload&quot; href=&quot;/dist/assets/main-Dz8C9a3m.js&quot; /&gt;\\n&lt;link rel=&quot;modulepreload&quot; href=&quot;/dist/assets/vendor-BpC2d1a0.js&quot; /&gt;\\n'\n\n// 3. Warm assets for a page the user is likely to navigate to next\n// Call from a controller action to preload a separate route's entry module\n// so the browser fetches chunks before the user clicks the link.\nvitePreloadTag(&quot;src/checkout.js&quot;);\n</code></pre>","hasExtended":true},"hint":"Returns <code><link rel=\"modulepreload\"></code> tags for a Vite entrypoint and its transitive\nchunk imports. Useful for Turbo Drive hover-preload patterns or for explicitly warming\nassets a subsequent navigation will need.\nIn development mode, returns an empty string — Vite handles module resolution\ndynamically and modulepreload is unnecessary.\n\n\nemits via <code>$viteHtmlHead()</code> so tags land in <code><head></code>.","parameters":[{"type":"string","hint":"The source entrypoint path (e.g. \"src/main.js\").","required":true,"name":"entrypoint"},{"type":"boolean","hint":"Set to `false` to return the markup for inline placement; default `true`","required":false,"name":"head","default":true}],"name":"vitePreloadTag","tags":{"category":"Asset Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"assetfunctions"}},{"returntype":"string","slug":"controller.viteScriptTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Emit a script tag for a Vite JS entrypoint inline (default)\n// In development, also injects the Vite HMR client.\n// In production, emits &lt;link&gt; tags for any associated CSS and a &lt;script type=&quot;module&quot;&gt; tag.\nwriteOutput(viteScriptTag(&quot;src/main.js&quot;));\n\n// 2. Place the script tag in the &lt;head&gt; instead of inline\n// Passes the generated markup to $htmlHead() so it is buffered into the page &lt;head&gt;.\n// Returns an empty string; nothing is printed at the call site.\nviteScriptTag(entrypoint=&quot;src/main.js&quot;, head=true);\n\n// 3. Emit a script tag for a page-specific entrypoint\n// Each entrypoint gets its own script tag; CSS chunks discovered in the\n// manifest are automatically included as &lt;link rel=&quot;stylesheet&quot;&gt; tags.\nwriteOutput(viteScriptTag(&quot;src/checkout.js&quot;));\n</code></pre>","hasExtended":true},"hint":"Returns 'script' tags for a Vite JS entrypoint. In development, also injects the Vite\nclient for Hot Module Replacement (HMR). In production, includes any associated CSS files\nfrom the manifest as <code><link></code> tags.\n\n","parameters":[{"type":"string","hint":"The source entrypoint path (e.g. \"src/main.js\").","required":true,"name":"entrypoint"},{"type":"boolean","hint":"Set to `true` to place output in the `<head>` area instead of inline.","required":false,"name":"head","default":false}],"name":"viteScriptTag","tags":{"category":"Asset Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"assetfunctions"}},{"returntype":"string","slug":"controller.viteStyleTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Emit a &lt;link&gt; tag for a standalone CSS entrypoint inline (default)\n// In development, returns an empty string — Vite injects CSS via the HMR JS client.\n// In production, outputs a fingerprinted &lt;link rel=&quot;stylesheet&quot;&gt; tag.\nwriteOutput(viteStyleTag(&quot;src/main.css&quot;));\n\n// 2. Place the &lt;link&gt; tag in the &lt;head&gt; instead of inline\n// Passes the generated markup to $htmlHead() so it is buffered into the page &lt;head&gt;.\n// Returns an empty string; nothing is printed at the call site.\nviteStyleTag(entrypoint=&quot;src/main.css&quot;, head=true);\n\n// 3. Emit a &lt;link&gt; tag for a page-specific CSS entrypoint\n// Useful when a particular view has its own standalone stylesheet entrypoint\n// defined in your Vite config alongside the primary JS bundle.\nwriteOutput(viteStyleTag(&quot;src/checkout.css&quot;));\n</code></pre>","hasExtended":true},"hint":"Returns a <code><link></code> tag for a Vite CSS entrypoint. In development, Vite injects CSS via\nthe JS client so this returns an empty string. In production, resolves the fingerprinted path.\n\n","parameters":[{"type":"string","hint":"The source CSS entrypoint path (e.g. \"src/main.css\").","required":true,"name":"entrypoint"},{"type":"boolean","hint":"Set to `true` to place output in the `<head>` area instead of inline.","required":false,"name":"head","default":false}],"name":"viteStyleTag","tags":{"category":"Asset Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"assetfunctions"}},{"returntype":"struct","slug":"mapper.whereAlpha","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Constrain a single route variable to alphabetic characters only\n    //    The [locale] segment will only match values like &quot;en&quot;, &quot;fr&quot;, &quot;de&quot;\n    .get(name=&quot;localizedHome&quot;, pattern=&quot;[locale]/home&quot;, to=&quot;home##index&quot;)\n    .whereAlpha(&quot;locale&quot;)\n\n    // 2. Constrain multiple variables at once using a comma-delimited list\n    //    Both [lang] and [region] must contain only a-z / A-Z characters\n    .get(name=&quot;localizedPage&quot;, pattern=&quot;[lang]/[region]/[action]&quot;, to=&quot;pages##show&quot;)\n    .whereAlpha(&quot;lang,region&quot;)\n\n    // 3. Chain with other constraint helpers for mixed-type route variables\n    //    [category] must be alphabetic; [id] must be numeric\n    .resources(name=&quot;articles&quot;)\n    .get(name=&quot;articleByCategory&quot;, pattern=&quot;articles/[category]/[id]&quot;, to=&quot;articles##byCategory&quot;)\n    .whereAlpha(&quot;category&quot;)\n    .whereNumber(&quot;id&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Constrain a route variable to only match alphabetic characters (a-zA-Z). Similar to Laravel's <code>whereAlpha()</code> or ASP.NET's <code>:alpha</code> constraint.\n\n","parameters":[{"type":"string","hint":"The route variable name to constrain. Can also be a comma-delimited list.","required":true,"name":"variableName"}],"name":"whereAlpha","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"mapper.whereAlphaNumeric","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Constrain a single route variable to alphanumeric characters only\n    .get(name=&quot;profile&quot;, pattern=&quot;profiles/[username]&quot;, to=&quot;profiles##show&quot;)\n    .whereAlphaNumeric(&quot;username&quot;)\n\n    // 2. Constrain multiple variables to alphanumeric in one call (comma-delimited list)\n    .get(name=&quot;teamMember&quot;, pattern=&quot;teams/[teamCode]/members/[memberCode]&quot;, to=&quot;teams##member&quot;)\n    .whereAlphaNumeric(&quot;teamCode,memberCode&quot;)\n\n    // 3. Chain whereAlphaNumeric with a resources block to restrict the key variable\n    .resources(name=&quot;products&quot;)\n    .whereAlphaNumeric(&quot;key&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Constrain a route variable to only match alphanumeric characters (a-zA-Z0-9). Similar to Laravel's <code>whereAlphaNumeric()</code>.\n\n","parameters":[{"type":"string","hint":"The route variable name to constrain. Can also be a comma-delimited list.","required":true,"name":"variableName"}],"name":"whereAlphaNumeric","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"mapper.whereIn","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Constrain a route variable to a fixed set of allowed string values\n    //    The [status] segment will only match &quot;active&quot;, &quot;inactive&quot;, or &quot;pending&quot;\n    .get(name=&quot;usersByStatus&quot;, pattern=&quot;users/[status]&quot;, to=&quot;users##byStatus&quot;)\n    .whereIn(variableName=&quot;status&quot;, values=&quot;active,inactive,pending&quot;)\n\n    // 2. Constrain a locale segment to a known list of supported languages\n    //    Requests like /en/home match; /xx/home returns a 404\n    .get(name=&quot;localizedHome&quot;, pattern=&quot;[locale]/home&quot;, to=&quot;home##index&quot;)\n    .whereIn(variableName=&quot;locale&quot;, values=&quot;en,fr,de,es&quot;)\n\n    // 3. Chain whereIn with whereNumber for mixed-type segment constraints\n    //    [type] must be one of the listed values; [id] must be numeric\n    .get(name=&quot;typedItem&quot;, pattern=&quot;items/[type]/[id]&quot;, to=&quot;items##show&quot;)\n    .whereIn(variableName=&quot;type&quot;, values=&quot;book,magazine,journal&quot;)\n    .whereNumber(&quot;id&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Constrain a route variable to only match one of a set of allowed values. Similar to an enum constraint.\n\n","parameters":[{"type":"string","hint":"The route variable name to constrain.","required":true,"name":"variableName"},{"type":"string","hint":"A comma-delimited list of allowed values (e.g., `\"active,inactive,pending\"`).","required":true,"name":"values"}],"name":"whereIn","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"mapper.whereMatch","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Constrain a route variable to a custom regex pattern (year: 4-digit number)\n    .get(name=&quot;archiveYear&quot;, pattern=&quot;archive/[year]&quot;, to=&quot;posts##archiveByYear&quot;)\n    .whereMatch(variableName=&quot;year&quot;, pattern=&quot;\\d{4}&quot;)\n\n    // 2. Constrain a slug variable to lowercase letters and hyphens only\n    .get(name=&quot;articleShow&quot;, pattern=&quot;articles/[slug]&quot;, to=&quot;articles##show&quot;)\n    .whereMatch(variableName=&quot;slug&quot;, pattern=&quot;[a-z][a-z0-9-]+&quot;)\n\n    // 3. Chained with resources — constrain the key to a specific format (e.g. SKU like AB-12345)\n    .resources(&quot;products&quot;)\n    .whereMatch(variableName=&quot;key&quot;, pattern=&quot;[A-Z]{2}-\\d{5}&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Constrain a route variable with a custom regex pattern.\n\n","parameters":[{"type":"string","hint":"The route variable name to constrain.","required":true,"name":"variableName"},{"type":"string","hint":"The regex pattern the variable must match.","required":true,"name":"pattern"}],"name":"whereMatch","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"mapper.whereNumber","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Constrain a single route variable to numeric digits only\n    //    The [id] segment will only match values like &quot;1&quot;, &quot;42&quot;, &quot;1000&quot;\n    .get(name=&quot;article&quot;, pattern=&quot;articles/[id]&quot;, to=&quot;articles##show&quot;)\n    .whereNumber(&quot;id&quot;)\n\n    // 2. Constrain multiple variables at once using a comma-delimited list\n    //    Both [year] and [month] must contain only digit characters\n    .get(name=&quot;archiveMonth&quot;, pattern=&quot;archive/[year]/[month]&quot;, to=&quot;posts##archive&quot;)\n    .whereNumber(&quot;year,month&quot;)\n\n    // 3. Chain with other constraint helpers for mixed-type route variables\n    //    [category] must be alphabetic; [id] must be numeric\n    .get(name=&quot;categoryItem&quot;, pattern=&quot;[category]/[id]&quot;, to=&quot;items##show&quot;)\n    .whereAlpha(&quot;category&quot;)\n    .whereNumber(&quot;id&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Constrain a route variable to only match numeric values (digits). Similar to Laravel's <code>whereNumber()</code> or ASP.NET's <code>:int</code> constraint.\n\n","parameters":[{"type":"string","hint":"The route variable name to constrain (e.g., `\"id\"`). Can also be a comma-delimited list to constrain multiple variables.","required":true,"name":"variableName"}],"name":"whereNumber","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"mapper.whereSlug","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Constrain a single slug variable — matches &quot;my-article-title&quot; but not &quot;My Article&quot; or &quot;abc123!&quot;\n    .get(name=&quot;article&quot;, to=&quot;articles##show&quot;)\n    .whereSlug(&quot;slug&quot;)\n\n    // 2. Chain with another constraint helper after a resource route\n    .resources(name=&quot;posts&quot;)\n    .whereSlug(&quot;postSlug&quot;)\n\n    // 3. Constrain multiple slug variables at once using a comma-delimited list\n    .get(name=&quot;categoryPost&quot;, pattern=&quot;[category]/[postSlug]&quot;, to=&quot;posts##showByCategory&quot;)\n    .whereSlug(&quot;category,postSlug&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Constrain a route variable to only match URL-friendly slug values (lowercase alphanumeric and hyphens).\n\n","parameters":[{"type":"string","hint":"The route variable name to constrain. Can also be a comma-delimited list.","required":true,"name":"variableName"}],"name":"whereSlug","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"mapper.whereUuid","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Constrain a single route variable to UUID values only\n    //    The [id] segment will only match values like &quot;550e8400-e29b-41d4-a716-446655440000&quot;\n    .get(name=&quot;document&quot;, pattern=&quot;documents/[id]&quot;, to=&quot;documents##show&quot;)\n    .whereUuid(&quot;id&quot;)\n\n    // 2. Constrain multiple variables to UUID format using a comma-delimited list\n    //    Both [userId] and [sessionId] must be valid UUID values\n    .get(name=&quot;userSession&quot;, pattern=&quot;users/[userId]/sessions/[sessionId]&quot;, to=&quot;sessions##show&quot;)\n    .whereUuid(&quot;userId,sessionId&quot;)\n\n    // 3. Chain with other constraint helpers for mixed-type route variables\n    //    [type] must be alphabetic; [id] must be a UUID\n    .get(name=&quot;typedResource&quot;, pattern=&quot;resources/[type]/[id]&quot;, to=&quot;resources##show&quot;)\n    .whereAlpha(&quot;type&quot;)\n    .whereUuid(&quot;id&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Constrain a route variable to only match UUID values. Similar to ASP.NET's <code>:guid</code> constraint.\n\n","parameters":[{"type":"string","hint":"The route variable name to constrain. Can also be a comma-delimited list.","required":true,"name":"variableName"}],"name":"whereUuid","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"struct","slug":"mapper.wildcard","availableIn":["mapper"],"extended":{"docs":"<pre><code class='javascript'>&lt;cfscript&gt;\n\nmapper()\n    // 1. Basic wildcard: enables `[controller]` and `[controller]/[action]`\n    //    patterns via GET requests only.\n    .wildcard()\n\n    // 2. Also enable a `[controller]/[action]/[key]` pattern.\n    .wildcard(mapKey=true)\n\n    // 3. Add an optional `.[format]` suffix to every generated pattern,\n    //    e.g. `[controller]/[action].json`.\n    .wildcard(mapFormat=true)\n\n    // 4. Change the default action when only `[controller]` is matched.\n    //    Requests to `/photos` will route to `photos##home` instead of\n    //    `photos##index`.\n    .wildcard(action=&quot;home&quot;)\n\n    // 5. Allow additional HTTP methods beyond GET.\n    //    Note: opening up extra methods can create security holes unless\n    //    you use `verifies` in your controller to guard data-changing actions.\n    .wildcard(method=&quot;get,post&quot;)\n.end();\n\n&lt;/cfscript&gt;\n</code></pre>","hasExtended":true},"hint":"Special wildcard matching generates routes with `\n","parameters":[{"type":"string","hint":"List of HTTP methods (verbs) to generate the wildcard routes for. We strongly recommend leaving the default value of `get` and using other routing mappers if you need to `POST` to a URL endpoint. Pass an empty string to generate the wildcard routes for all verbs (`get`, `post`, `put`, `patch`, and `delete`).","required":false,"name":"method","default":"get"},{"type":"string","hint":"Default action to specify if the value for the `[action]` placeholder is not provided.","required":false,"name":"action","default":"index"},{"type":"boolean","hint":"Whether or not to enable a `[key]` matcher, enabling a `[controller]/[action]/[key]` pattern.","required":false,"name":"mapKey","default":false},{"type":"boolean","hint":"Whether or not to add an optional `.[format]` pattern to the end of the generated routes. This is useful for providing formats via URL like `json`, `xml`, `pdf`, etc.","required":false,"name":"mapFormat","default":false},{"type":"string","hint":"Alias for `method`, provided for better readability when listing multiple methods. Takes precedence over `method` when both are passed.","required":false,"name":"methods"}],"name":"wildcard","tags":{"category":"Routing","sectionClass":"configuration","section":"Configuration","categoryClass":"routing"}},{"returntype":"any","slug":"model.withAdvisoryLock","availableIn":["model"],"extended":{"docs":"<pre><code class='javascript'>// 1. Prevent duplicate processing of a background job\nmodel(&quot;Job&quot;).withAdvisoryLock(name=&quot;process-nightly-report&quot;, callback=function() {\n    job = model(&quot;Job&quot;).findOneByNameAndStatus(name=&quot;nightly-report&quot;, status=&quot;pending&quot;);\n    if (isObject(job)) {\n        job.process();\n    }\n});\n\n// 2. Serialize access to a shared external resource with a custom timeout\nresult = model(&quot;Payment&quot;).withAdvisoryLock(\n    name=&quot;payment-gateway-sync&quot;,\n    timeout=30,\n    callback=function() {\n        return model(&quot;Payment&quot;).syncWithGateway();\n    }\n);\n\n// 3. Ensure only one instance assigns the next batch of records\nmodel(&quot;Task&quot;).withAdvisoryLock(name=&quot;task-batch-assignment&quot;, callback=function() {\n    tasks = model(&quot;Task&quot;).findAll(\n        conditions=&quot;assignedTo IS NULL&quot;,\n        maxRows=10,\n        returnAs=&quot;objects&quot;\n    );\n    for (task in tasks) {\n        task.update(assignedTo=getCurrentWorkerID());\n    }\n});\n</code></pre>","hasExtended":true},"hint":"Executes a callback while holding a database advisory lock.\nThe lock is automatically released when the callback completes, even if an exception is thrown.\nAdvisory locks are database-level locks that don't lock rows or tables. They are useful for\ncoordinating exclusive access to shared resources across application instances.\nSupport varies by database:\n- PostgreSQL: Full support via pg_advisory_lock/pg_advisory_unlock\n- MySQL: Full support via GET_LOCK/RELEASE_LOCK\n- SQL Server: Full support via sp_getapplock/sp_releaseapplock\n- SQLite: No-op (file-level locking only)\n- CockroachDB: Not supported (throws error, use forUpdate() instead)\n- H2: Not supported (throws error)\n- Oracle: Not supported by default (requires DBMS_LOCK package setup)\n\n","parameters":[{"type":"string","hint":"A unique name for the lock. Different callers using the same name will contend for the same lock.","required":true,"name":"name"},{"type":"numeric","hint":"Maximum number of seconds to wait when acquiring the lock (supported by MySQL and SQL Server).","required":false,"name":"timeout","default":10},{"type":"any","hint":"A function or closure to execute while holding the lock. Its return value is returned by this method.","required":true,"name":"callback"}],"name":"withAdvisoryLock","tags":{"category":"Locking Functions","sectionClass":"modelclass","section":"Model Class","categoryClass":"lockingfunctions"}},{"returntype":"string","slug":"controller.wordTruncate","availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"extended":{"docs":"<pre><code class='javascript'>// 1. Truncate text to the first 4 words (default truncate string &quot;...&quot;)\nresult = wordTruncate(text=&quot;CFWheels is a framework for ColdFusion&quot;, length=4);\n// result -&gt; &quot;CFWheels is a framework...&quot;\n\n// 2. Truncate with a custom truncate string\nresult = wordTruncate(text=&quot;The quick brown fox jumps over the lazy dog&quot;, length=5, truncateString=&quot; [read more]&quot;);\n// result -&gt; &quot;The quick brown fox jumps [read more]&quot;\n\n// 3. Text with fewer words than the limit is returned unchanged\nresult = wordTruncate(text=&quot;Short text&quot;, length=10);\n// result -&gt; &quot;Short text&quot;\n</code></pre>","hasExtended":true},"hint":"Truncates text to the specified length of words and replaces the remaining characters with the specified truncate string (which defaults to \"...\").\n\n","parameters":[{"type":"string","hint":"The text to truncate.","required":true,"name":"text"},{"type":"numeric","hint":"Number of words to truncate the text to.","required":false,"name":"length","default":5},{"type":"string","hint":"String to replace the last characters with.","required":false,"name":"truncateString","default":"..."}],"name":"wordTruncate","tags":{"category":"String Functions","sectionClass":"globalhelpers","section":"Global Helpers","categoryClass":"stringfunctions"}},{"returntype":"string","slug":"controller.yearSelectTag","availableIn":["controller"],"extended":{"docs":"<pre><code class='javascript'>// 1. Basic year select tag using the current request params as the selected value\n#yearSelectTag(name=&quot;yearOfBirthday&quot;, selected=params.yearOfBirthday)#\n\n// 2. Restrict the range to the past 50 years with a minimum of 18 years ago\n#yearSelectTag(\n    name=&quot;yearOfBirthday&quot;,\n    selected=params.yearOfBirthday,\n    startYear=Year(Now()) - 50,\n    endYear=Year(Now()) - 18\n)#\n\n// 3. Include a blank prompt and wrap with a label\n#yearSelectTag(\n    name=&quot;yearOfBirthday&quot;,\n    selected=params.yearOfBirthday,\n    includeBlank=&quot;- Select Year -&quot;,\n    label=&quot;Birth Year&quot;,\n    labelPlacement=&quot;before&quot;\n)#\n</code></pre>","hasExtended":true},"hint":"Builds and returns a string containing a <code>select</code> form control for a range of years based on the supplied name.\n\n","parameters":[{"type":"string","hint":"Name to populate in tag's name attribute.","required":true,"name":"name"},{"type":"string","hint":"The year that should be selected initially.","required":false,"name":"selected","default":""},{"type":"numeric","hint":"First year in `select` list.","required":false,"name":"startYear","default":2021},{"type":"numeric","hint":"Last year in `select` list.","required":false,"name":"endYear","default":2031},{"type":"any","hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","required":false,"name":"includeBlank","default":false},{"type":"string","hint":"The label text to use in the form control.","required":false,"name":"label","default":""},{"type":"string","hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","required":false,"name":"labelPlacement","default":"around"},{"type":"string","hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"prepend","default":""},{"type":"string","hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","required":false,"name":"append","default":""},{"type":"string","hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"prependToLabel","default":""},{"type":"string","hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","required":false,"name":"appendToLabel","default":""},{"type":"any","hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","required":false,"name":"encode","default":true},{"type":"date","required":false,"name":"$now","default":"[runtime expression]"}],"name":"yearSelectTag","tags":{"category":"Form Tag Functions","sectionClass":"viewhelpers","section":"View Helpers","categoryClass":"formtagfunctions"}}]}




