Model

Data Modeling base class.  See Overview for more details.

Summary
ModelData Modeling base class.
OverviewIn FlightPath, models (the M in MVC) are represented by the Model class.
Model Conventions
Defining ModelsDatabase Models are defined automatically for tables in the default datasource.
Custom ModelsCustom models are models that do not have a database table back-end.
Properties
managerManager alias for this model.
tableNametable to load instead of the default name.
validationan instance of Myna.Validation.
namethis model’s name, set by FLightPath
idFieldname of the identifying field, normally set in init() for Custom Models
Functions
initInitializes a model instance
applyBehaviorloads a behavior and applies it to this object
addValidatoradds a validation function to this Model’s validation object
createCustom Model Override A model specific create function function.
forceDeleteCustom Model Override A model specific delete function.
queryCustom Model Override A model specific search function.
saveBeanFieldCustom Model Override A model specific save function.
findreturns an array of idField values that match a search
findBeansreturns a Myna.DataSet of <beanField> values that match a search
genKeyGenerates a unique identifier for this Model
getFieldreturns metadata for a field
getFieldreturns array of field metadata objects
getTypereturns type of field
addFieldadds a field to this Model’s beanClass
addFieldsadds multiple fields to this Model’s beanClass
getByIdreturns the beanClass for a given ID, or throws an exception
getDefaultreturns the default value for a given field name
getDefaultsreturns a JS Object where the properties are field names and values are their default values
removeremoves a bean by id
setDefaultsets a default value for a field
setDefaultssets a default values for multiple fields
genLabelgenerates a display label from a field name
getLabelreturns the label for a field name
setLabelsets a label for a field name
setLabelssets multiple labels
getreturns either an instance of an existing bean or the result of getNew
getNewReturns a beanClass representing a new row not yet inserted
belongsToSets a “belongsTo” relationship with another model.
hasOneSets a “hasOne” relationship with another Model.
hasManySets a “hasMany” relationship with another Model.
hasBridgeToSets a “many-to-many” relationship with another Model.
validation. validatorFunctions. uniqueCustom validator that validates a value is unique in a field
beanClassA model’s bean class
Properties
existstrue if this bean exists in the Model
modelThe Model that created this bean
isDirtytrue if this bean has unsaved changes, only applies to deferred beans
deferredDefault false determines whether “set” operations update the database
dataa simple JS object containing this bean’s data
idThe value of the primary key of this bean
fieldNamesThe fieldNames for this bean
Functions
get_<fieldName>gets a value for <fieldName>
set_<fieldName>sets a value for <fieldName>
setFieldsSets multiple fields at once
saveFieldPersists a value to its underlying row
forceDeletealias for Model.forceDelete, which passes this bean’s id
getDatareturn a structure of this bean’s data
getLabelalias for Model.getLabel
removealias for Model.remove, which passes this bean’s id
saveSaves a deferred bean and returns a Myna.ValidationResult object
validateValidates this bean.

Overview

In FlightPath, models (the M in MVC) are represented by the Model class.

How to load a model

By convention, a model with the same name as the controller is automatically loaded and stored in the controller’s “model” property, and as a property with the same name as the model.  If a table with a name that fits the convention (See: Model Conventions).  Models can also be loaded by calling $FP.getModel, or by accessing related models in a beanClass

Models provide access to data.  Normally this is a database data source, but custom Models can access any kind of data.  Models are heavily influenced by Myna.DataManager managers and beans and instances of these classes are used when accessing databases.  Models can also be associated with other models, allowing associated data to be easily accessed.  Each Model has a beanClass property that is a JavaScript class that represents a “row” of data.

See

Model Conventions

  • Model Names are singular, ProperCase, ex: EmployeeAction
  • Model File names are in file_case, ending with “_model”, ex: app/models/employee_action_model.sjs
  • Model definitions are discovered in this order: framework/models/<model_name>_model.sjs, app/models/<model_name>.sjs, app/modules/<module_name>/models/<model_name>_model.sjs
  • The ini() and functions in app/models/global.sjs are applied before any model definitions discovered
  • Table Names are plural and file_case, ex: employee_actions
  • Table columns should be in file_case, ex: employee_id
  • Primary key columns should be named “id”
  • Foreign key columns should be named “<singular_table_name>_id”, ex: employee_action_id
  • Foreign keys defined in the database are automatically detected and applied to models, regardless of naming format.
  • bridge tables, i.e. tables that link two other tables in a many-to-many relationship, will be detected automatically if they consist of only foreign key columns and optionally a primary key
  • column datatype validators are automatically applied
  • columns default values are NOT detected, these must be set in init()

Defining Models

Database Models are defined automatically for tables in the default datasource.  However the database does not contain all the necessary meta data to properly configure a Model, so defining a model is a good idea.  Model definitions can be stored in app/models/<model_name>_model.sjs or in a module, app/modules/module_name/models/<model_name>_model.sjs.  The primary source of configuration is the init function.  This is executed after the init() function in app/models/global.sjs.  Any functions or properties defined in this file will be added to final Model instance.

Functions called from init

Functions typically overloaded in definitions

Examples

//app/models/employee_action.sjs

//if the table name doesn't follow convention, i.e "employee_actions",
//you can force it here:
//var tableName="emp_action"

//If you model is not in the "default" datasource alias, you can indicate
//which manager to use by alias name here:
//var manager="alias from $application.config.ds"


//runs after Myna.DataManager and any init() in app/models/global.sjs
function init(){

this.setLabels({//other lables will be generated
payrollgrp:"Payroll Group"
})

this.setDefaults({
action_type:"other",
action_date:function(){return new Date()}
})

//this is only necessary if the foreign key is not defined in the database
this.belongsTo("Employee");

}

//replaces default implementation
function genKey(){
//oracle specific sequence query
// this could be defined in app/models/global.sjs if all tables generate
// keys in the same way
return new Myna.Query({
ds:this.ds,
sql:<ejs>
select
nextval(seq_employee_actions) id
from dual
</ejs>
})[0].id
}

See

  • Myna.DataManager all manager and bean functions and properties are applied to Models and beanClasses
  • Custom Models, for information on non-database models

Custom Models

Custom models are models that do not have a database table back-end.  Because of this, they require more configuration than table-backed models.

Custom models must make one or more calls to addField/addFields, and implement the following functions:

Otherwise Custom models should behave just like table-backed models.

Here is an example of a custom model for managing Myna data sources

function init(){
this.addFields([
{ name:"name", idField:true, type:"string", defaultValue:""},
{ name:"url", type:"string", defaultValue:"" },
{ name:"port", type:"numeric", defaultValue:0 },
{ name:"file", type:"string", defaultValue:"" },
{ name:"server", type:"string", defaultValue:"" },
{ name:"case_sensitive", type:"numeric", label:"Case Sensitive Columns?", defaultValue:0 },
{ name:"username", type:"string", defaultValue:"" },
{ name:"desc", label:"Description", type:"string", defaultValue:"" },
{ name:"type", type:"string", defaultValue:"" },
{ name:"location", type:"string", defaultValue:"" },
{ name:"password", type:"string", defaultValue:"" },
{ name:"driver", type:"string", defaultValue:"" },
{ name:"db", type:"string", label:"Database", defaultValue:"" }
])
this.deferred = true;
this.validation = Myna.Admin.ds.dsValidation.clone()
}


function create(newDs){
var isNew = !this.exists;
var vr =Myna.Admin.ds.save(newDs,isNew)
if (vr.success){
return this.getById(newDs.name)
} else throw vr

}
function forceDelete(name){
new Myna.File($server.rootDir + "WEB-INF/myna/ds/" + name + ".ds").forceDelete()
}
function saveBeanField(bean,fieldName,oldval,newval){
var v = bean.validate(fieldName);

// Don't actually save. Bean instances of this model are always deferred and
// must be saved via "save" which eventually calls "create"

return v
}

function query(pattern,options){
var $this = this;
if (!pattern) pattern={}
if (pattern.select == "*") delete pattern.select

//just in case these database query extensions are passed
var criteria = pattern.filter(function(v,k){
return !"select,where,orderBy".listContains(k)
})
var result= Myna.Admin.ds.getAll()
.filter(function(ds){
if (!criteria.getKeys().length) return true
return criteria.getKeys()
.every(function(key){
if (typeof criteria[key] == "string"){
return criteria[key].toLowerCase() == (ds[key]||"").toLowerCase()
} else {
return criteria[key] == ds[key]
}
})
}).map(function(row){
if (!pattern.select) return row

//support a comma separated field list in "select"
return row.filter(function(v,k){
return pattern.select.listContains(k)
})
})
return new Myna.DataSet({
columns:pattern.select||this.fieldNames,
data:result
})
}

Properties

manager

Manager alias for this model.

This is an alias defined in the application.sjs in the config.ds section.  This causes this model to be loaded form the indicated datasource.  Defined at the top of the model file before init()

Example

// in application.sjs
...
config:{
ds:{
"default":"hr",
"accounting":"gl",
}
...
// in app/models/account_model.sjs

var manager="accounting";

function init(){
}
...

tableName

table to load instead of the default name.

For database backed Models where the table name does not conform to convention.  Defined at the top of the model file before init()

Example

// in app/models/account_model.sjs

var tableName="acc2012";

function init(){
}
...

validation

an instance of Myna.Validation.  Normally built up via addValidator

name

this model’s name, set by FLightPath

idField

name of the identifying field, normally set in init() for Custom Models

Functions

init

Initializes a model instance

Whenever a model is instantiated, init() is run to configure the instance.  First the init() in the Model base class is run, then the init() in app/models/global.sjs, and finally the init() in app/models/<name>_model.sjs

Functions typically called from init

applyBehavior

applyBehavior:function applyBehavior(name)

loads a behavior and applies it to this object

Parameters

nameThe ProperCased name of the behavior to load, or an array of these names

Detail

Loads a behavior by name from app/behaviors/models/ or framework/behaviors/models/, whichever is found first.  Behaviors are functions that are applied to the current object.  applyBehavior should be called from init

Example

//in some_model.sjs
function init(){
this.applyBehavior([
"SomeBehavior",
"SomeOtherBehavior"
]);
}

addValidator

addValidator:function addValidator(colname,
validator,
options)

adds a validation function to this Model’s validation object

Parameters

propertyproperty to validate.  If this is set to null, then this validator will be called for every property
validatorEither a String or a validation function.  If this is a string, it must match one of the standard validation functions stored in <Myna.Validation.validatorFunctions>, or the Model-specific validator <validatorFunctions.unique> This function will be called when needed to validate property See Validator Function below
optionsOptional, default undefined any options needed by the validator

Validator Function

The validator function will be called with a parameters object with these properties obj - Object being validated property - Property being validated label - result of getLabel for property value - value being validated options - validator options.  Most validators define their own specific options, but all validators accept the options below

Validator Options

whenA function that will take the same parameters as a validator function and return true if the validator should be run.  This is normally used conditionally validate one of the built-in validators

Returns

this validation instance

Examples

this.addValidator("first_name","length",{
min:3,
max:25
})

//only validate spouse_name when married is true
this.addValidator("spouse_name","required",{
when:function(params){
return params.obj.married
}
})

function isBob(params){
var vr = new Myna.ValidationResult();
if (params.value != "Bob"){
var msg = params.options.message || params.label + " is not Bob!"
vr.addError(msg,colname)
}
return vr;
}

this.addValidator("first_name",isBob,{
message:"Inferior name entered."
})

See

create

create:function create(requiredFields)

Custom Model Override A model specific create function function.

Parameters

requiredFieldsA JS object where the properties are field names and the values are field values

returns a beanClass instance of the bean created

Custom Models must implement this function.

Database models use ManagerObject.create

forceDelete

forceDelete:function forceDelete(id)

Custom Model Override A model specific delete function.

Parameters

idid of “row” to delete

Custom Models must implement this function.

Database models use ManagerObject.forceDelete

query

query:function query(pattern,
options)

Custom Model Override A model specific search function.

Parameters

patternString or Object.  Search pattern.  Can be either a single string value to search within the id field, or an object where each property is a field name and the values are search patterns
optionsOptional JS Object.  Extra options tothe query

returns a Myna.DataSet of beanClass Objects

Custom Models must implement this function.

Database models use ManagerObject.query from <DataManager>

saveBeanField

saveBeanField:function saveBeanField(bean,
fieldName,
oldval,
newval)

Custom Model Override A model specific save function.

Parameters

beanreference to beanClass instance being saved
fieldNamename of field being saved
oldvalvalue of field before being modified
newvalnew value of field

returns a Myna.ValidationResult object

Custom Models must implement this function.

Database models do not use this function

find

find:function find(pattern,
options)

returns an array of idField values that match a search

Parameters

patternif this is a String, Number, or Date, the primary key will be searched for this value.  If this is an object, each key is expected to by a field name and the value a pattern to search for.
optionsquery options, used by extending classes

Database models use ManagerObject.find which offers more options.  Custom Models may offer extra features as well.

See

findBeans

findBeans:function findBeans(pattern,
options)

returns a Myna.DataSet of <beanField> values that match a search

Parameters

patternif this is a String, Number, or Date, the primary key will be searched for this value.  If this is an object, each key is expected to by a field name and the value a pattern to search for.
optionsquery options, used by extending classes

Database models use ManagerObject.findBeans which offers more options.  Custom Models may offer extra features as well.

See

genKey

Generates a unique identifier for this Model

Database models use ManagerObject.genKey Custom Models should override this this function

See

getField

getField:function getField(name)

returns metadata for a field

Returned Object Properties

namename of field
typetype of field, See: getType
labellabel of field, See: getLabel
defaultValuedefault value, See: getDefault

getField

getFields:function getFields()

returns array of field metadata objects

See

getType

getType:function getType(name)

returns type of field

Parameters

namename of field

Possible Types

  • string
  • numeric
  • date
  • binary

See

addField

addField:function addField(def)

adds a field to this Model’s beanClass

Parameters

defJS Object, see Field Definition below

Field Definition

namename of field
typeOptional field type, one of [“string”,”numeric”,”date”,”binary”]
labelOptional label of field
defaultValueOptional default value of field
idFieldOptional, boolean if true, this will be set as the idField for this model.  There can be only one id field per model

returns this model See:

addFields

addFields:function addFields(fields)

adds multiple fields to this Model’s beanClass

Parameters

fieldsarray of Field Definitions

returns this model See:

getById

getById:function getById(id)

returns the beanClass for a given ID, or throws an exception

Parameters

idid of bean to return

getDefault

getDefault:function getDefault(name)

returns the default value for a given field name

Parameters

namename of field

See

getDefaults

getDefaults:function getDefaults()

returns a JS Object where the properties are field names and values are their default values

Parameters

namename of field

See

remove

remove:function remove(id)

removes a bean by id

Parameters

idid of bean to remove

Note that database models support “soft” deletes via a softDelete Column See:

setDefault

setDefault:function setDefault(name,
value)

sets a default value for a field

Parameters

namename of field
valuedefault value

See

setDefaults

setDefaults:function setDefaults(map)

sets a default values for multiple fields

Parameters

mapJS Object where the properties are field names and the values are default values

See

genLabel

genLabel:function genLabel(colname)

generates a display label from a field name

The default implementation either uses one of the special replacements below, or replaces all underbars with spaces and calls String.titleCap on the result.  You can override this function in your models for custom behavior

Special Replacements

idID

getLabel

getLabel:function getLabel(name)

returns the label for a field name

Parameters

namefield name

See

setLabel

setLabel:function setLabel(name,
label)

sets a label for a field name

Parameters

namefield name
labellabel

See

setLabels

setLabels:function setLabels(map)

sets multiple labels

Parameters

mapJS Object where the properties are field names and the values are labels

See

get

get:function get(values)

returns either an instance of an existing bean or the result of getNew

Parameters

valuesOptionsal, default null JS object containing the values for this object

Detail

This function attempts to create a usable bean even if there is no matching record.  If values is provided with a valid primary key, then getById is called, beanClass.deferred is set to true, and beanClass.setFields is called with values.  Otherwise getNew is called with values.  Regardless, the resulting bean will be deferred and beanClass.save must be called to persist changes

Note

Any defaults set by setDefault will be applied before returning the bean object

Example

//in app/controllers/order_controler.sjs
//crate or update an order from form data:
function save(params){
var order = this.model.get(params)
var result = order.save();
if (result.success) {
...
} else{
...
}
}

getNew

getNew:function getNew(initialValues)

Returns a beanClass representing a new row not yet inserted

Parameters

initialValuesobject representing the initial values of this object.  If this does not include a value for the idField, the idField will be set to the result from genKey.

Note

Any defaults set by setDefault will be applied before returning the bean object

See

belongsTo

belongsTo:function belongsTo(name)

Sets a “belongsTo” relationship with another model.

This function has 3 parameter patterns

Model Name

nameName of model to associate.  Model names

Model Definition object

nameName of model to associate
aliasOptional, default _name_ Name to use when attaching related beans.  Using different alias allows you to model multiple belongsTo relationships to the same Model
conditionsOptional, default null “where” pattern Object to contain this association, see find.  You do NOT need this to constrain by the foreign key
foreignKey*Optional, foreign Model’s idField * Name of field in related Model that this Model refers to.  This is almost always the idField of that Model
localKey*Optional, default file_case alias +”_id” * The field in this Model that contains the foreign key value.  This defaults to the underbar(_) separated alias of the associated model + “_id”
cascadeOptional, default false This affects the treatment of the related model when a record is deleted from this model.  A value of false, undefined or null will do nothing.  The string “null” will set null values for the foreignKey field in the related Model.  The string “delete” will delete the related record in the related Model
this.belongsTo({
name:"Profile",
conditions:{
where:"public = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
}
})

Model definition object array

this.belongsTo([{
name:"Profile",
conditions:{
where:"public = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
}]
},{
name:"Employee"
}])

Detail

This maps a one-to-one relationship with the related Model to this one.  Once set, any beans returned by this manager will include a function with the same name as the related model that represents the result of <relatedModel>.get() for the related row in the related Model.  This is best shown by example

//Person Model
function init(){
this.belongsTo("Profile")
}
//Person controller
function edit(params){
this.set("person",this.Person.get({id:params.id}));
}
//person_edit view
Name: <input name="name" value:"<%=person.name%>"><br>
<!--
this is the same as
$FP.getModel("Profile").findBeans({person_id:person.id}).first().email
-->
Email: <input name="Profile.email" value:"<%=person.Profile().email%>"><br>

hasOne

hasOne:function hasOne(name)

Sets a “hasOne” relationship with another Model.

This function has 3 parameter patterns

Model Name

nameName of model to associate

Model Definition object

nameName of model to associate
aliasOptional, default _name_ Name to use when attaching related beans.  Using different alias allows you to model multiple hasOne relationships to the same Model
conditionsOptional, default null “where” pattern Object to contain this association, see find.  You do NOT need this to constrain by the foreign key
foreignKey*Optional, default modelname +”_id” * name of field in related model that refers to this model
localKey*Optional, default model’s idField * This is the field in this Model that contains the foreign key value.  This is almost always the idField of this Model
cascadeOptional, default false This affects the treatment of the related model when a record is deleted from this model.  A value of false, undefined or null will do nothing.  The string “null” will set null values for the foreignKey field in the related Model.  The string “delete” will delete the related record in the related Model
var Person = dm.getManager("Person")
Person.hasOne({
name:"Profile",
alias:"RecentPublicProfile",
conditions:{
where:"public = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
}
})

Model definition object array

var Person = dm.getManager("Person")
Person.hasOne([{
name:"Profile",
alias:"RecentPublicProfile",
conditions:{
where:"public = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
}]
},{
name:"Profile"
}])

Detail

This maps a one-to-one relationship with the related Model to this one.  Once set, any beans returned by this manager will include a property with the same name as the related model that represents the result of <relatedModel>.get() for the related row in the related Model.  This is best shown by example

// --- from a FlightPath MVC app ---
//Person Model (a DataManager.Model)
function init(){
this.hasOne("Profile")
}
//Person controller
function edit(params){
this.set("person",this.Person.get({id:params.id}));
}
//person_edit view
Name: <input name="name" value:"<%=person.name%>"><br>
<!--
this is the same as
$FP.getModel("Profile").findBeans({person_id:person.id}).first().email
-->
Email: <input name="Profile.email" value:"<%=person.Profile().email%>"><br>

hasMany

hasMany:function hasMany(name)

Sets a “hasMany” relationship with another Model.

This function has 3 parameter patterns

Model Name

namePlural name of model to associate.  Plural Model names are the ProperCased Model name, e.g profiles becomes Profiles, and user_profiles would be UserProfiles
//these are equivalent
var Person = dm.getManager("Person")
Person.hasMany("Posts")
Person.hasMany("posts")

Model Definition object

namePlural name of model to associate.
aliasOptional, default _name_ Name to use when attaching related beans.  Using different alias allows you to model multiple hasMany relationships to the same Model
conditionsOptional, default null “where” pattern Object to contain this association, see Model.find.  You do NOT need this to constrain by the foreign key
foreignKey*Optional, default modelname +”_id” * name of field in related model that refers to this model
localKey*Optional, default model’s idField * This is the field in this Model that contains the foreign key value.  This is almost always the idField of this Model
orderByOptional, default null Valid SQL order by expression. if defined, this will be used to order the related beans.
cascadeOptional, default false This affects the treatment of the related model when a record is deleted from this model.  A value of false, undefined or null will do nothing.  The string “null” will set null values for the foreignKey field in the related Model.  The string “delete” will delete the related record in the related Model
var Person = dm.getManager("Person")
Person.hasMany({
name:"Posts",
alias:"RecentPosts
conditions:{
where:"published = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
},
orderBy:"category_title ASC, date_published DESC"
})

Model definition object array

var Person = dm.getManager("Person")
Person.hasMany([{
name:"Posts",
alias:"RecentPosts
conditions:{
where:"published = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
},
orderBy:"category_title ASC, date_published DESC"
},{
name:"Posts",
orderBy:"category_title ASC, date_published DESC"
},{
name:"Favorites"
}])

Detail

This maps a one-to-many relationship with the related Model to this one.  Once set, any beans returned by this manager will include a function with the same name as the related alias that represents the result of <relatedModel>.findBeans(), constrained by the foreign key relationship.  This is best shown by example

// --- from a FlightPath MVC app ---
//Person Model
function init(){
this.hasMany("Posts")
}
//Person controller
function edit(params){
this.set("person",this.Person.get({id:params.id}));
}
//person_edit view
Name: <input name="name" value:"<%=person.name%>"><br>
<!--
person.Posts is the same as
$FP.getModel("Post").findBeans({person_id:person.person_id})
-->
Posts:
<ul>
<@loop array="person.Posts()" element="post" index="i">
<li> <%=post.title%>
</@loop>
</ul>

hasBridgeTo

hasBridgeTo:function hasBridgeTo(name)

Sets a “many-to-many” relationship with another Model.

This function has 3 parameter patterns

Model Name

namePlural name of model to associate.  Plural Model names are the ProperCased Model name, e.g profiles becomes Profiles, and user_profiles would be UserProfiles
//these are equivalent
var Person = dm.getManager("Person")
Person.hasBridgeTo("Tags")
Person.hasBridgeTo("tags")

Model Definition object

namePlural name of model to associate.
aliasOptional, default _name_ Name to use when attaching related beans.  Using different alias allows you to model multiple hasMany relationships to the same Model
conditionsOptional, default null “where” pattern Object to contain this association, see Model.find.  You do NOT need this to constrain by the foreign key
bridgeModelOptional, default [relatedModel.name,thisModel.name].sort().join(“”) name of bridge Model.  Defaults to the two Models names in alphabetical order, concatenated
localBridgeKeyOptional, default <idField> the field in the bridge Model that stores this Model’s ids
foreignBridgeKeyOptional, default foreign Model <idField> the field in the bridge Model that stores the foreign Model’s ids
foreignKey*Optional, default modelname +”_id” * name of field in related model that refers to this model
localKey*Optional, default model’s idField * This is the field in this Model that contains the foreign key value.  This is almost always the idField of this Model
orderByOptional, default null Valid SQL order by expression. if defined, this will be used to order the related beans.
cascadeOptional, default false This affects the treatment of the related model when a record is deleted from this model.  A value of false, undefined or null will do nothing.  The string “null” will set null values for the foreignKey field in the related Model.  The string “delete” will delete the related record in the related Model
var Person = dm.getManager("Person")
Person.hasBridgeTo({
name:"Tags",
alias:"RecentTags",
conditions:{
where:"published = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
},
orderBy:"category_title ASC, date_published DESC"
})

Model definition object array

var Person = dm.getManager("Person")
Person.hasBridgeTo([{
name:"Tags",
alias:"RecentTags",
conditions:{
where:"published = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
},
orderBy:"category_title ASC, date_published DESC"
},{
name:"Tags",
orderBy:"category_title ASC, date_published DESC"
}])

Detail

This maps a many-to-many relationship with the related Model to this one.  This requires a “bridge” Model i.e a Model that maps the idField of both Models.  Once defined, any beans returned by this manager will include a function with the same name as the related alias that represents the result of <relatedModel>.findBeans(), constrained by the foreign key relationship.  This is best shown by example

// --- from a FlightPath MVC app ---
//Person Model
function init(){
this.hasMany("Tags")
}
//Person controller
function edit(params){
this.set("person",this.Person.get({id:params.id}));
}
//person_edit view
Name: <input name="name" value:"<%=person.name%>"><br>
<!--
person.Posts is the same as
$FP.getModel("Post").findBeans({person_id:person.person_id})
-->
Posts:
<ul>
<@loop array="person.Tags()" element="tag" index="i">
<li> <%=tag.title%>
</@loop>
</ul>

validation. validatorFunctions. unique

Custom validator that validates a value is unique in a field

Parameters

caseSensitiveOptional, default false Set to true for exact matches.  Only applies to character fields

Detail

This will search all instance of this model looking for any instances of this value, NOT associated with this idProperty.  If any are found this validator will add an error

Examples

this.addValidators({
name:{
required:{},

},
slug:{
required:{},
unique:{},//slug must be unique in the table, regardless of case
regex:{
pattern:/^[a-z0-9-]+$/,
message:"Can only contain numbers, lowercase letters, '_' or '-'"
}

},
})
//OR
this.addValidator("slug","unique")

See

beanClass

A model’s bean class

Summary
Properties
existstrue if this bean exists in the Model
modelThe Model that created this bean
isDirtytrue if this bean has unsaved changes, only applies to deferred beans
deferredDefault false determines whether “set” operations update the database
dataa simple JS object containing this bean’s data
idThe value of the primary key of this bean
fieldNamesThe fieldNames for this bean
Functions
get_<fieldName>gets a value for <fieldName>
set_<fieldName>sets a value for <fieldName>
setFieldsSets multiple fields at once
saveFieldPersists a value to its underlying row
forceDeletealias for Model.forceDelete, which passes this bean’s id
getDatareturn a structure of this bean’s data
getLabelalias for Model.getLabel
removealias for Model.remove, which passes this bean’s id
saveSaves a deferred bean and returns a Myna.ValidationResult object
validateValidates this bean.

Properties

exists

true if this bean exists in the Model

model

The Model that created this bean

isDirty

true if this bean has unsaved changes, only applies to deferred beans

See

deferred

Default false determines whether “set” operations update the database

If this is set to true, “set” operations on the bean,only update the data property.  Deferred beans only persist to the database when save is called

See

Model.get Model.getNew

data

a simple JS object containing this bean’s data

id

The value of the primary key of this bean

fieldNames

The fieldNames for this bean

Functions

get_<fieldName>

gets a value for <fieldName>

Detail

This function is generated for every column in the associated table.

set_<fieldName>

sets a value for <fieldName>

Parameters

newvalnew value for the column

Returns

Myna.ValidationResult object representing the result of the set.

Detail

This function is generated for every column in the associated table, except for the primary key.

setFields

Sets multiple fields at once

Parameters

fieldsan object of column names and their values

Returns

Myna.ValidationResult representing the result of this action.

Detail

This function will examine each non-function property of fields and call the corresponding “set” function, if available.  Properties that do not match a “set” function are ignored

saveField

Persists a value to its underlying row

Parameters

fieldNameA column name in the row to savee a value to
newvalThe value to save

Returns

Myna.ValidationResult representing the result of this action.

Detail

This function is normally called from the “set” function, but may be useful when overriding the generated “set” function.  This will not actually persist its value if deferred is true

forceDelete

alias for Model.forceDelete, which passes this bean’s id

getData

return a structure of this bean’s data

Parameters

depthOptional, default 1 Number of levels of related beans to include in this data.  Set this to 0 to only include this bean’s data

Detail

This is a copy of the data, so it will not change when the object is modified

getLabel

alias for Model.getLabel

remove

alias for Model.remove, which passes this bean’s id

save

Saves a deferred bean and returns a Myna.ValidationResult object

If called against a deferred BeanObject, all values in data are persisted to the database.  Afterwards, this bean’s deferred status is set to the Model’s deferred status

validate

Validates this bean.

Calls all of the validator functions added via Model.addValidator against this bean and returns the merged Myna.ValidationResult object

Parameters

fieldNameOptional, default null If defined, limits validation to a single column See:
A store for validation functions that can be used to validate objects
applyBehavior:function applyBehavior(name)
loads a behavior and applies it to this object
addValidator:function addValidator(colname,
validator,
options)
adds a validation function to this Model’s validation object
an instance of Myna.Validation.
create:function create(requiredFields)
Custom Model Override A model specific create function function.
forceDelete:function forceDelete(id)
Custom Model Override A model specific delete function.
query:function query(pattern,
options)
Custom Model Override A model specific search function.
saveBeanField:function saveBeanField(bean,
fieldName,
oldval,
newval)
Custom Model Override A model specific save function.
find:function find(pattern,
options)
returns an array of idField values that match a search
name of the identifying field, normally set in init() for Custom Models
findBeans:function findBeans(pattern,
options)
returns a Myna.DataSet of beanField values that match a search
A specialized array for working with tabular data
getField:function getField(name)
returns metadata for a field
getType:function getType(name)
returns type of field
addField:function addField(def)
adds a field to this Model’s beanClass
A model’s bean class
addFields:function addFields(fields)
adds multiple fields to this Model’s beanClass
getById:function getById(id)
returns the beanClass for a given ID, or throws an exception
getDefault:function getDefault(name)
returns the default value for a given field name
getDefaults:function getDefaults()
returns a JS Object where the properties are field names and values are their default values
remove:function remove(id)
removes a bean by id
setDefault:function setDefault(name,
value)
sets a default value for a field
setDefaults:function setDefaults(map)
sets a default values for multiple fields
genLabel:function genLabel(colname)
generates a display label from a field name
getLabel:function getLabel(name)
returns the label for a field name
setLabel:function setLabel(name,
label)
sets a label for a field name
setLabels:function setLabels(map)
sets multiple labels
get:function get(values)
returns either an instance of an existing bean or the result of getNew
getNew:function getNew(initialValues)
Returns a beanClass representing a new row not yet inserted
belongsTo:function belongsTo(name)
Sets a “belongsTo” relationship with another model.
hasOne:function hasOne(name)
Sets a “hasOne” relationship with another Model.
hasMany:function hasMany(name)
Sets a “hasMany” relationship with another Model.
hasBridgeTo:function hasBridgeTo(name)
Sets a “many-to-many” relationship with another Model.
Data Modeling base class.
Default false determines whether “set” operations update the database
Stores the results of one or more validation operations
In FlightPath, models (the M in MVC) are represented by the Model class.
function getModel(modelName)
factory function that finds, loads, and initializes a model by name
Creates Objects for reading from and writing to database tables
Database Models are defined automatically for tables in the default datasource.
Myna FlightPath is a Model-View-Controller(MVC) web application framework inspired by CakePHP, CFWheels and Ruby On Rails.
Initializes a model instance
Generates a unique identifier for this Model
Custom models are models that do not have a database table back-end.
Validates this bean.
Creates a record in the database, optionally generating a primary key
Removes a row from the managed table matching the supplied primary key
returns a Myna.DataSet of information from this table
returns an array of primaryKey values that match a search
returns a Myna.DataSet of bean objects that match a search
generates a primary key value
Removes or invalidates a row from the managed table matching the supplied primary key
String.prototype.titleCap=function()
Capitalizes the first letter of every word in string
Sets multiple fields at once
Saves a deferred bean and returns a Myna.ValidationResult object
a simple JS object containing this bean’s data