wheels generate property
Add properties to existing model files.
Synopsis
wheels generate property [name] [options]
wheels g property [name] [options]
Description
The wheels generate property
command generates a database migration to add a property to an existing model and scaffolds it into _form.cfm
and show.cfm
views.
Arguments
name
Table name
Required
Options
column-name
Name of column
Required
data-type
Type of column
string
default
Default value for column
--null
Whether to allow null values
limit
Character or integer size limit for column
precision
Precision value for decimal columns
scale
Scale value for decimal columns
Property Syntax
Basic Format
propertyName:type:option1:option2
Data Type Options
biginteger
- Large integerbinary
- Binary databoolean
- Boolean (true/false)date
- Date onlydatetime
- Date and timedecimal
- Decimal numbersfloat
- Floating pointinteger
- Integerstring
- Variable character (VARCHAR)text
- Long texttime
- Time onlytimestamp
- Timestampuuid
- UUID/GUID
Examples
String property
wheels generate property user column-name=firstname
Creates a string/textField property called firstname
on the User model.
Boolean property with default
wheels generate property user column-name=isActive data-type=boolean default=0
Creates a boolean/checkbox property with default value of 0 (false).
Datetime property
wheels generate property user column-name=lastloggedin data-type=datetime
Creates a datetime property on the User model.
Decimal property with precision
wheels generate property product column-name=price data-type=decimal precision=10 scale=2
Add calculated property
wheels generate property user "fullName:calculated"
Generated Code Examples
Basic Property Addition
Before:
component extends="Model" {
function init() {
// Existing code
}
}
After:
component extends="Model" {
function init() {
// Existing code
// Properties
property(name="email", sql="email");
// Validations
validatesPresenceOf(properties="email");
validatesUniquenessOf(properties="email");
validatesFormatOf(property="email", regEx="^[^@\s]+@[^@\s]+\.[^@\s]+$");
}
}
Multiple Properties
Command:
wheels generate property product "name:string:required description:text price:float:required:default=0.00 inStock:boolean:default=true"
Generated:
component extends="Model" {
function init() {
// Properties
property(name="name", sql="name");
property(name="description", sql="description");
property(name="price", sql="price", default=0.00);
property(name="inStock", sql="in_stock", default=true);
// Validations
validatesPresenceOf(properties="name,price");
validatesNumericalityOf(property="price", allowBlank=false, greaterThanOrEqualTo=0);
}
}
Association Property
Command:
wheels generate property comment "userId:integer:required:belongsTo=user postId:integer:required:belongsTo=post"
Generated:
component extends="Model" {
function init() {
// Associations
belongsTo(name="user", foreignKey="userId");
belongsTo(name="post", foreignKey="postId");
// Properties
property(name="userId", sql="user_id");
property(name="postId", sql="post_id");
// Validations
validatesPresenceOf(properties="userId,postId");
}
}
Calculated Property
Command:
wheels generate property user fullName:calculated --callbacks
Generated:
component extends="Model" {
function init() {
// Properties
property(name="fullName", sql="", calculated=true);
}
// Calculated property getter
function getFullName() {
return this.firstName & " " & this.lastName;
}
}
Migration Generation
When --migrate=true
(default), generates migration:
Migration File
app/migrator/migrations/[timestamp]_add_properties_to_[model].cfc
:
component extends="wheels.migrator.Migration" hint="Add properties to product" {
function up() {
transaction {
addColumn(table="products", columnName="sku", columnType="string", limit=50, null=false);
addColumn(table="products", columnName="price", columnType="decimal", precision=10, scale=2, null=false, default=0.00);
addColumn(table="products", columnName="stock", columnType="integer", null=true, default=0);
addIndex(table="products", columnNames="sku", unique=true);
}
}
function down() {
transaction {
removeIndex(table="products", columnNames="sku");
removeColumn(table="products", columnName="stock");
removeColumn(table="products", columnName="price");
removeColumn(table="products", columnName="sku");
}
}
}
Validation Rules
Automatic Validations
Based on property type and options:
string:required
validatesPresenceOf, validatesLengthOf
string:unique
validatesUniquenessOf
email
validatesFormatOf with email regex
integer
validatesNumericalityOf(onlyInteger=true)
float
validatesNumericalityOf
boolean
validatesInclusionOf(list="true,false,0,1")
date
validatesFormatOf with date pattern
Custom Validations
Add custom validation rules:
wheels generate property user "age:integer:min=18:max=120"
Generated:
validatesNumericalityOf(property="age", greaterThanOrEqualTo=18, lessThanOrEqualTo=120);
Property Callbacks
Generate with callbacks:
wheels generate property user lastLoginAt:datetime --callbacks
Generated:
function init() {
// Properties
property(name="lastLoginAt", sql="last_login_at");
// Callbacks
beforeUpdate("updateLastLoginAt");
}
private function updateLastLoginAt() {
if (hasChanged("lastLoginAt")) {
// Custom logic here
}
}
Complex Properties
Enum-like Property
wheels generate property order "status:string:default=pending:inclusion=pending,processing,shipped,delivered"
Generated:
property(name="status", sql="status", default="pending");
validatesInclusionOf(property="status", list="pending,processing,shipped,delivered");
File Upload Property
wheels generate property user "avatar:string:fileField"
Generated:
property(name="avatar", sql="avatar");
// In the init() method
afterSave("processAvatarUpload");
beforeDelete("deleteAvatarFile");
private function processAvatarUpload() {
if (hasChanged("avatar") && isUploadedFile("avatar")) {
// Handle file upload
}
}
JSON Property
wheels generate property user "preferences:text:json"
Generated:
property(name="preferences", sql="preferences");
function getPreferences() {
if (isJSON(this.preferences)) {
return deserializeJSON(this.preferences);
}
return {};
}
function setPreferences(required struct value) {
this.preferences = serializeJSON(arguments.value);
}
Property Modifiers
Encrypted Property
wheels generate property user "ssn:string:encrypted"
Generated:
property(name="ssn", sql="ssn");
beforeSave("encryptSSN");
afterFind("decryptSSN");
private function encryptSSN() {
if (hasChanged("ssn") && Len(this.ssn)) {
this.ssn = encrypt(this.ssn, application.encryptionKey);
}
}
private function decryptSSN() {
if (Len(this.ssn)) {
this.ssn = decrypt(this.ssn, application.encryptionKey);
}
}
Slugged Property
wheels generate property post "slug:string:unique:fromProperty=title"
Generated:
property(name="slug", sql="slug");
validatesUniquenessOf(property="slug");
beforeValidation("generateSlug");
private function generateSlug() {
if (!Len(this.slug) && Len(this.title)) {
this.slug = createSlug(this.title);
}
}
private function createSlug(required string text) {
return reReplace(
lCase(trim(arguments.text)),
"[^a-z0-9]+",
"-",
"all"
);
}
Batch Operations
Add Multiple Related Properties
wheels generate property user "
profile.bio:text
profile.website:string
profile.twitter:string
profile.github:string
" --nested
Add Timestamped Properties
wheels generate property post "publishedAt:timestamp deletedAt:timestamp:nullable"
Integration with Existing Code
Preserve Existing Structure
The command intelligently adds properties without disrupting:
Existing properties
Current validations
Defined associations
Custom methods
Comments and formatting
Conflict Resolution
wheels generate property user email:string
> Property 'email' already exists. Options:
> 1. Skip this property
> 2. Update existing property
> 3. Add with different name
> Choice:
Best Practices
Add properties incrementally
Always generate migrations
Include appropriate validations
Use semantic property names
Add indexes for query performance
Consider default values carefully
Document complex properties
Common Patterns
Soft Delete
wheels generate property model deletedAt:timestamp:nullable
Versioning
wheels generate property document "version:integer:default=1 versionedAt:timestamp"
Status Tracking
wheels generate property order "status:string:default=pending statusChangedAt:timestamp"
Audit Fields
wheels generate property model "createdBy:integer:belongsTo=user updatedBy:integer:belongsTo=user"
Testing
After adding properties:
# Run migration
wheels dbmigrate latest
# Generate property tests
wheels generate test model user
# Run tests
wheels test
See Also
wheels generate model - Generate models
wheels dbmigrate create column - Create columns
wheels generate test - Generate tests
Last updated
Was this helpful?