Creates Objects for reading from and writing to database tables
Myna.DataManager is a dynamic Object-Relational Mapping (ORM) tool to simplify basic Create, Read, Update and Delete (CRUD) operations on database tables.
The basic concept is that for a given table Myna.DataManager can generate a manager object that represents that table and knows how to create and delete rows. That manager can then generate a bean object that represents a specific row in the table that knows how to read and write column values to that row. Both of these types objects can be extended for extra functionality.
+- - - - - - - - - - - - - - - - - -+
| table employees |
+- - - - - - - - - - - - - - - - - -+
| emp_id int4 primary key |
| fname varchar |
| mname varchar |
| lname varchar |
| manager_id int4 |
| hire_date date |
+- - - - - - - - - - - - - - - - - -+
var dm = new Myna.DataManager("hr_datasource");
var empManager = dm.getManager("employees");
var newEmpBean = empManager.create({
fname:"Bob",
lname:"Dobb",
hire_date:Date.parse("02/21/1992","m/d/Y")
})
Myna.println (newEmp.get_emp_id()) // Prints the auto generated primary key
newEmp.set_mname("R"); //sets this value in an update
// column values are also available as property proxies on the bean objects:
// see https://developer.mozilla.org/En/Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Getters_and_Setters
// for how this works
Myna.println (newEmp.emp_id) // calls get_emp_id() on the bean
newEmp.mname = "R"; // calls set_emp_id("R") on the bean
The DataManager can also manage MPTT organized tree tables. This is a method of storing hierarchical data in flat database tables.
Also check out empManager.columns for metadata about each column in the table, such as name, default value, size, type, nullable, precision and more.
| Myna. DataManager | Creates Objects for reading from and writing to database tables |
| Functions | |
| DataManager | Constructs a Myna.DataManager Object for the supplied datasource |
| getManager | Constructs a ManagerObject for the supplied table. |
| getTreeManager | An extension of getManager that specifically manages Modified Pre-order Tree Traversal (MPTT) organized tables. |
| managerExists | returns true if a manager with a given name can be created form this DataManager |
| Properties | |
| ds | Datasource associated with this Myna.DataManager |
| db | Myna.Database object that represents the database this table resides in |
| ManagerObject | Table data access object generated and returned by Myna.DataManager.getManager |
| Functions | |
| addValidator | adds a validation function to this manager’s validation object |
| addValidators | add multiple validators to this manager’s validation object |
| loadTableData | internal function to load table data into the manager |
| remove | Removes or invalidates a row from the managed table matching the supplied primary key |
| forceDelete | Removes a row from the managed table matching the supplied primary key |
| create | Creates a record in the database, optionally generating a primary key |
| query | returns a Myna.DataSet of information from this table |
| find | returns an array of primaryKey values that match a search |
| findBeans | returns a Myna.DataSet of bean objects that match a search |
| genKey | generates a primary key value |
| genLabel | generates a display label from a column name |
| getById | Returns a BeanObject representing the row identified by the supplied primary key |
| get | returns either an instance of an existing row or the result of getNew |
| getDefault | returns the default value for a column name |
| getDefaults | returns a structure of all the default values for this table |
| getLabel | returns the display label for a column name |
| getNew | Returns a BeanObject representing a new row not yet inserted |
| belongsTo | Sets a “belongsTo” relationship with another table. |
| hasOne | Sets a “hasOne” relationship with another table. |
| hasMany | Sets a “hasMany” relationship with another table. |
| hasBridgeTo | Sets a “many-to-many” relationship with another table. |
| makeTree | Converts this manager into a TreeManagerObject |
| setDefault | sets an explicit default value for a column |
| setDefaults | sets several default values at once |
| setLabel | sets an explicit display label for a column |
| setLabels | sets an explicit display label for multiple columns at once |
| validatorFunctions. unique | A DataManager-specific validator that validates a value is unique in a column |
| Properties | |
| dm | The Myna.DataManager object that created this manager |
| db | The Myna.Database for this manager |
| deferred | default, false Sets the deferred status of beans generated by this manager |
| table | The Myna.Table for this manager |
| ds | The datasource name for this manager |
| columns | The columns array from Myna.Table.columns for this table |
| logQueries | if true, log all queries made by this manager default: false |
| columnNames | The columnNames array from Myna.Table.columnNames for this table |
| softDeleteCol | Date or timestamp column to set to current time instead of deleting rows |
| validation | This manager’s Myna.Validation instance |
| TreeManagerObject | Table data access object generated and returned by Myna.DataManager.getTreeManager for Modified Pre-order Tree Traversal (MPTT) organized tables |
| Functions | |
| create | Inserts a row in the table relative to an existing node, and re-orders affected nodes. |
| remove | removes a row in the table and also deletes any descending nodes |
| hasRootNode | returns true if there is a root node in this table. |
| getRootNode | returns the root node of this table, or throws an exception |
| rebuildTree | recalculates left, right, and depth values based on parent ids |
| BeanObject | Row data access object generated and returned by ManagerObject.getById |
| Functions | |
| get_<columnName> | gets a value for <columnName> |
| set_<columnName> | sets a value for <columnName> |
| setFields | Sets multiple fields at once |
| saveField | Persists a value to its underlying row |
| forceDelete | alias for ManagerObject.forceDelete, which passes this bean’s id |
| getData | returns a structure of this bean’s data |
| getLabel | alias for ManagerObject.getLabel |
| getParent | return a bean representing this bean’s parent record |
| getChildren | return a Myna.DataSet of beans representing this bean’s child records |
| remove | alias for ManagerObject.remove, which passes this bean’s id |
| save | Saves a deferred bean and returns a Myna.ValidationResult object |
| validate | Validates this bean. |
| Properties | |
| exists | true if this bean exists in the database |
| manager | The ManagerObject that created this bean |
| dm | The Myna.DataManager object that created this bean |
| isDirty | true if this bean has unsaved changes, only applies to deferred beans |
| deferred | Default false determines whether “set” operations update the database |
| ds | The datasource name for this bean |
| data | a simple JS object containing this bean’s data |
| id | The value of the primary key of this bean |
| columns | The columns array from Myna.Table.columns for this table |
| columnNames | The columnNames array from Myna.Table.columnNames for this table |
| TreeNodeObject | Sub-class of BeanObject generated and returned by <TreeManagerObject.getById> |
| Functions | |
| moveNode | Moves this node to another location in the tree, only applies to nodes access through <ManagerObject.getTreeManager> |
| getLeft | returns the value of this node’s “left” property. |
| getRight | returns the value of this node’s “right” property. |
| getParentId | returns the value of this node’s “parent” property. |
| getParentNode | returns this node’s parent node |
| isRootNode | returns true if this node is the root node |
| Properties | |
| childIds | an array of the node ids of this node’s direct children |
| childNodes | an array of the TreeNodes of this node’s direct children |
| descendantIds | an array of the node ids of all of this node’s descendants |
| descendantNodes | an array of the TreeNodes of all of this node’s descendants |
| ancestorIds | an array of the node ids of this node’s ancestors |
| ancestorNodes | an array of the TreeNodes of this node’s ancestors |
Constructs a Myna.DataManager Object for the supplied datasource
| dataSource | Datasource Name |
Constructs a ManagerObject for the supplied table.
| tableName | lowercase name of the table, or singular ProperCased name of table, e.g “part_orders” or “PartOrder” |
| options | A JS object representing metadata for this table that can’t be calculated from the table itself See “Options” Below |
| softDeleteCol | Optional, default “deleted” If this column exists in the table, then delete operations will instead set this column to the current time. Find operations will automatically filter rows with this column set |
| createdCol | Optional, default “created” If this column exists in the table, then create operations will set this column to the current time. |
| modifiedCol | Optional, default “modified” If this column exists in the table, then modify operations will set this column to the current time. Detail: Creates a ManagerObject for the supplied table. |
An extension of getManager that specifically manages Modified Pre-order Tree Traversal (MPTT) organized tables.
| tableName | Name of MPTT organized table |
| options | A JS object representing metadata for the MPTT table. See “Options” Below |
| leftCol | *Optional, default “lft” * Column name that contains the “left” values |
| rightCol | *Optional, default “rgt” * Column name that contains the “right” values |
| idCol | *Optional, default primary key col * The column that contains the “id” values |
| parentCol | *Optional, default “parent_id” * The column that contains the “parent” values |
| depthCol | *Optional, default null * The column that contains the “depth” values. If this is null, then this TreeManager will not manage a depth column |
returns true if a manager with a given name can be created form this DataManager
| name | String. Table name or model name to check |
Myna.Database object that represents the database this table resides in
Table data access object generated and returned by Myna.DataManager.getManager
| Functions | |
| addValidator | adds a validation function to this manager’s validation object |
| addValidators | add multiple validators to this manager’s validation object |
| loadTableData | internal function to load table data into the manager |
| remove | Removes or invalidates a row from the managed table matching the supplied primary key |
| forceDelete | Removes a row from the managed table matching the supplied primary key |
| create | Creates a record in the database, optionally generating a primary key |
| query | returns a Myna.DataSet of information from this table |
| find | returns an array of primaryKey values that match a search |
| findBeans | returns a Myna.DataSet of bean objects that match a search |
| genKey | generates a primary key value |
| genLabel | generates a display label from a column name |
| getById | Returns a BeanObject representing the row identified by the supplied primary key |
| get | returns either an instance of an existing row or the result of getNew |
| getDefault | returns the default value for a column name |
| getDefaults | returns a structure of all the default values for this table |
| getLabel | returns the display label for a column name |
| getNew | Returns a BeanObject representing a new row not yet inserted |
| belongsTo | Sets a “belongsTo” relationship with another table. |
| hasOne | Sets a “hasOne” relationship with another table. |
| hasMany | Sets a “hasMany” relationship with another table. |
| hasBridgeTo | Sets a “many-to-many” relationship with another table. |
| makeTree | Converts this manager into a TreeManagerObject |
| setDefault | sets an explicit default value for a column |
| setDefaults | sets several default values at once |
| setLabel | sets an explicit display label for a column |
| setLabels | sets an explicit display label for multiple columns at once |
| validatorFunctions. unique | A DataManager-specific validator that validates a value is unique in a column |
| Properties | |
| dm | The Myna.DataManager object that created this manager |
| db | The Myna.Database for this manager |
| deferred | default, false Sets the deferred status of beans generated by this manager |
| table | The Myna.Table for this manager |
| ds | The datasource name for this manager |
| columns | The columns array from Myna.Table.columns for this table |
| logQueries | if true, log all queries made by this manager default: false |
| columnNames | The columnNames array from Myna.Table.columnNames for this table |
| softDeleteCol | Date or timestamp column to set to current time instead of deleting rows |
| validation | This manager’s Myna.Validation instance |
adds a validation function to this manager’s validation object
| property | property to validate. If this is set to null, then this validator will be called for every property |
| validator | Either 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 manager-specific validator validatorFunctions.unique This function will be called when needed to validate property See Validator Function below |
| options | Optional, default undefined any options needed by the validator |
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 |
| when | A 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 |
this validation instance
manager.addValidator("first_name","length",{
min:3,
max:25
})
//only validate spouse_name when married is true
manager.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;
}
manager.addValidator("first_name",isBob,{
message:"Inferior name entered."
})add multiple validators to this manager’s validation object
| validator_config | JS Object keyed by property name, with sub-objects keyed by validator name (or “custom” for custom validators), with values equal to validator options (or {}, if no options) |
this validation instance
manager.addValidators({
name:{
required:{},
type:"string",
regex:{
pattern:/^[A-Za-z ]+$/,
message:"Names must only contain Letters and spaces"
},
},
dob:{
type:"date",
value:{
min:new Date().add(Date.YEAR,-150),
max:new Date()
}
},
children:{
type:"array",
length:{
max:12
},
custom:function(params){
var vr = new Myna.ValidationResult();
params.value.forEach(function(child,index){
vr.merge(this.validate(child),"child_" + index "_")
})
return vr;
}
}
})Removes or invalidates a row from the managed table matching the supplied primary key
| id | primary key value of the row to remove |
This function checks for the existence of softDeleteCol and will update it to the current time if available. If no softDeleteCol is defined, then forceDelete is called to remove the row form the table.
Removes a row from the managed table matching the supplied primary key
| id | primary key value of the row to remove |
If this manager hasOne or hasMany related managers with cascading deletes, these related rows will be deleted regardless of the existence of softDeleteCol in the related managers
Creates a record in the database, optionally generating a primary key
| requiredFields | An object where the keys are column names and the values are the values to insert. |
requiredFields must contain entries for all non-null columns without default values, except the primary key. If the primary key is not specified, and the column does not have a default value, genKey is called to generate a key. Any extra columns supplied will be inserted as well.
instance of the Bean that represents the new row. See getById
+- - - - - - - - - - - - - - - - - -+
| table employees |
+- - - - - - - - - - - - - - - - - -+
| emp_id int4 primary key |
| fname varchar |
| mname varchar |
| lname varchar |
| manager_id int4 |
| hire_date date |
+- - - - - - - - - - - - - - - - - -+
var dm = new Myna.DataManager("hr_datasource");
var empManager = dm.getManager("employees");
var newEmpBean = empManager.create({
fname:"Bob",
lname:"Dobb",
hire_date:Date.parse("02/21/1992","m/d/Y")
})
returns a Myna.DataSet of information from this table
| pattern | if 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 column name and the value a pattern to search for. In either mode, the SQL wildcard (%) can be used for a “like” search. Special pattern properties are available for advanced queries. See Special Pattern Properties below |
| options | query options, see options below |
| select | *default, “” This is the select expression to use for this query. Any valid SQL will work |
| where | default, false This pattern property works much like the sql property of Myna.Query. Any valid SQL can be used here, and parameter placeholders can be used just as in Myna.Query. Parameters are replaced from the other properties of pattern. See example below |
| orderBy | default, false if defined, this is a valid SQL order by expression |
| ”colname operation” | default, false if defined, will perform operation against colname with the value of this property. e.g : “age <”:12 |
| caseSensitive | default false if true, patterns will be matched in a case-sensitive manner |
| includeSoftDeleted | default false if true, soft deleted columns will be included in query results |
| [queryOptions] | Any other Myna.Query options such as maxRows |
The Myna.DataSet returned has an extra property, “totalRows” that contains the number of items that would be returned if the query was not constrained. This is useful if page, or startRow are passed as options
var employees = new Myna.DataManager("some_ds").getManager("employees");
//Find all employees of a given supervisor
var grunts = man.query({
supervisor_id:"0102236",
"inactive is not":null
})
//more complicated search with wildcards
var assitants = employees.find({
supervisor_id:"0102236"
job_title:"%assistant%"
})
// an even more complicated search with "select",
// "where" and "orderBy" pattern properties
// and including soft deleted records
var bobs_helpers = employees.find({
select:"name",
where:<ejs>
supervisor_id = {supervisor_id}
and (
job_title like {job_title}
or start_date > {start_date:date}
)
</ejs>,
orderBy:"name desc",
supervisor_id:"55652315",
job_title:"%assitant%",
start_date:new Date().add(Date.year,-1)
},{
includeSoftDeleted:true
})returns an array of primaryKey values that match a search
| pattern | if 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 column name and the value a pattern to search for. In either mode, the SQL wildcard (%) can be used for a “like” search. A special property where can be used for complex where clauses, see ”where” pattern property below |
| options | Optional, default false options to pass to the underlying ManagerObject.query call |
This pattern property works much like the sql property of Myna.Query. Any valid SQL that makes sense in a where clause can be used here, and parameter placeholders can be used just as in Myna.Query. Parameters are replaced from the other properties of pattern. See example below
var employees = new Myna.DataManager("some_ds").getManager("employees");
// a primary key search
var bob_exists = employees.find("55652315").length
//one column search for exact match
var bobs_emps = employees.find({
manager_id:"55652315"
})
//Who are Bob's employees?
bobs_emps.forEach(function(employee_id){
Myna.print(employees.getById(employee_id).get_name() +"<br>");
})
//more complicated search with wildcards
var bobs_helpers = employees.find({
manager_id:"55652315",
job_title:"%assitant%"
})
//an even more complicated search with where property
var bobs_helpers = employees.find({
where:<ejs>
manager_id = {manager_id}
and (
job_title like {job_title}
or start_date > {start_date:date}
)
</ejs>,
manager_id:"55652315",
job_title:"%assitant%",
start_date:new Date().add(Date.year,-1)
})
//include deleted "helpers"
var bobs_helpers = employees.find({
manager_id:"55652315",
job_title:"%assitant%",
},{
includeSoftDeleted:true
})returns a Myna.DataSet of bean objects that match a search
| pattern | if this is a string, the primary key will be searched for this value. If this is an object, each key is expected to by a column name and the value a pattern to search for. In either mode, the SQL wildcard (%) can be used for a “like” search. |
| options | Optional, default false options to pass to the underlying ManagerObject.query call |
The Myna.DataSet returned has an extra property, “totalRows” that contains the number of items that would be returned if the query was not constrained. This is useful if page, or startRow are passed as options
var employees = new Myna.DataManager("some_ds").getManager("employees");
// a primary key search
var bob_exists = employees.find("55652315").length
//one column search for exact match
var bobs_emps = employees.findBeans({
manager_id:"55652315"
})
//Who are Bob's employees?
bobs_emps.forEach(function(employee){
Myna.print(employee.get_name() +"<br>");
})
//What are their email addresses?
Myna.printDump(bobs_emps.valueArray("email"),"Bob's Emloyees' Email")
//more complicated search with wildcards
var bobs_helpers = employees.findBeans({
manager_id:"55652315",
job_title:"%assitant%"
})
//Using aggregate math: Bob's employees average salary
//See Myna.DataSet
var bobs_emps_avg_sal = employees.findBeans({
manager_id:"55652315"
}).average("salary")generates a primary key value
By default this function checks the type of the primary key and returns Myna.createUuid for text keys or returns the maximum value of the primary key column + 1 for numeric keys. This is not the ideal algorithm and should be replaced with a database specific means of generating a primary key.
(end)
generates a display label from a column 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
| id | ID |
Returns a BeanObject representing the row identified by the supplied primary key
| id | primary key value of the row to retrieve |
This function loads the data from the indicated row into into a <Myna.DataManager.prototype.BeanBase> object. Each bean is generated with get_<column name> and set_<column name> functions. The set functions will immediately set the value in the underlying row.
If a an object with the specified id cannot be found, an exception is thrown
returns either an instance of an existing row or the result of getNew
| values | Optionsal, default null JS object containing the values for this object |
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, BeanObject.deferred is set to true, and BeanObject.setFields is called with values. Otherwise getNew is called with values. Regardless, the resulting bean will be deferred and BeanObject.save must be called to persist changes
Any defaults set by setDefault will be applied before returning the bean object
//crate or update an order from form data:
var order = new Myna.DataManager(ds).getManager("orders").get($req.rawData)
var result = order.save();
if (result.success) {
...
} else{
...
}
returns the default value for a column name
| colname | lowercase name of column to retrieve a default value for |
If an explicit default for this column has been set via setDefault, or setDefaults, that is returned. Otherwise, null is returned
Returns a BeanObject representing a new row not yet inserted
| initialValues | object representing the initial values of this object. If this does not include a value for the primary key, the primary key will be set to the result from genKey. |
Any defaults set by setDefault will be applied before returning the bean object
Sets a “belongsTo” relationship with another table.
| name | Name of model to associate, or a table name. Model names are the ProperCased singular of the table name |
//these are equivalent
var Person = dm.getManager("Person")
Person.belongsTo("Profile")
Person.belongsTo("profiles")
| name | Name of model or table to associate |
| alias | Optional, default _name_ Name to use when attaching related beans. Using different alias allows you to model multiple belongsTo relationships to the same table |
| conditions | Optional, default null “where” pattern Object to contain this association, see ManagerObject.find. You do NOT need this to constrain by the foreign key |
| foreignKey | *Optional, foreign table’s primary key * Name of column in related table that this table refers to. This is almost always the primary key of that table |
| localKey | *Optional, default modelname +”_id” * The column in this table that contains the foreign key value. |
| cascade | Optional, 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 column in the related table. The string “delete” will delete the related record in the related table |
this.belongsTo({
name:"Profile",
conditions:{
where:"public = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
}
})this.belongsTo([{
name:"Profile",
conditions:{
where:"public = 1 and modified > {oneYearAgo:date}",
oneYearAgo:new Date().add(Date.YEAR,-1).clearTime()
}]
},{
name:"Employee"
}])This maps a one-to-one relationship with the related table 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 table. This is best shown by example
// --- from a FlightPath MVC app ---
//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>
Note that calling Profile() in the above code will cause the “parent” bean to be created if it doesn’t exist and set this bean to BeanObject.deferred. When this bean is saved the parent bean will be inserted, if any changes have been made. To avoid this (and intentionally create an orphan bean) set the related column to an explicit null value, or just don’t make any changes to the returned “parent” bean
Sets a “hasOne” relationship with another table.
| name | Name of model to associate, or a table name. Model names are the ProperCased singular of the table name |
//these are equivalent
var Person = dm.getManager("Person")
Person.hasOne("Profile")
Person.hasOne("profiles")
| name | Name of model or table to associate |
| alias | Optional, default _name_ Name to use when attaching related beans. Using different alias allows you to model multiple hasOne relationships to the same table |
| conditions | Optional, default null “where” pattern Object to contain this association, see ManagerObject.find. You do NOT need this to constrain by the foreign key |
| foreignKey | *Optional, default modelname +”_id” * name of column in related model that refers to this model |
| localKey | *Optional, default model’s primary key * This is the column in this table that contains the foreign key value. This is almost always the primary key of this table |
| cascade | Optional, 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 column in the related table. The string “delete” will delete the related record in the related table |
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()
}
})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"
}])This maps a one-to-one relationship with the related table 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 table. This is best shown by example
// --- from a FlightPath MVC app ---
//Person Model (a DataManager.ManagerObject)
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>
Note that calling Profile() in the above code will cause the bean to be created if it doesn’t exist and set this bean to BeanObject.deferred. If any changes are made to the related bean, it will be inserted when this bean is saved. To force an empty related bean to save, set BeanObject.isDirty to true for the related bean
Sets a “hasMany” relationship with another table.
| name | Plural name of model or exact table name to associate. Plural Model names are the ProperCased table 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")
| name | Plural name of model exact table name to associate. |
| alias | Optional, default _name_ Name to use when attaching related beans. Using different alias allows you to model multiple hasMany relationships to the same table |
| conditions | Optional, default null “where” pattern Object to contain this association, see ManagerObject.find. You do NOT need this to constrain by the foreign key |
| foreignKey | *Optional, default modelname +”_id” * name of column in related model that refers to this model |
| localKey | *Optional, default model’s primary key * This is the column in this table that contains the foreign key value. This is almost always the primary key of this table |
| orderBy | Optional, default null Valid SQL order by expression. if defined, this will be used to order the related beans. |
| cascade | Optional, 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 column in the related table. The string “delete” will delete the related record in the related table |
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"
})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"
}])This maps a one-to-many relationship with the related table 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>
Note that the DataSet result from Posts() above will also contain a getNew() function that is an alias for the related Manager’s getNew() function. Calling this will create a new instance of the related bean and add it to this object’s relatedBean array. The related column will be set to this bean’s localKey value
Sets a “many-to-many” relationship with another table.
| name | Plural name of model or exact table name to associate. Plural Model names are the ProperCased table 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")
| name | Plural name of model exact table name to associate. |
| alias | Optional, default _name_ Name to use when attaching related beans. Using different alias allows you to model multiple hasMany relationships to the same table |
| conditions | Optional, default null “where” pattern Object to contain this association, see ManagerObject.find. You do NOT need this to constrain by the foreign key |
| bridgeTable | Optional, default [relatedModel.tableName,thisModel.tableName].sort().join(“_”) name of bridge table. Defaults to the two tables names in alphabetical order, separated by underbars(_) |
| localBridgeKey | Optional, default primary key the field in the bridge table that stores this table’s ids |
| foreignBridgeKey | Optional, default foreign table primary key the field in the bridge table that stores the foreign table’s ids |
| foreignKey | *Optional, default modelname +”_id” * name of column in related model that refers to this model |
| localKey | *Optional, default model’s primary key * This is the column in this table that contains the foreign key value. This is almost always the primary key of this table |
| orderBy | Optional, default null Valid SQL order by expression. if defined, this will be used to order the related beans. |
| cascade | Optional, 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 column in the related table. The string “delete” will delete the related record in the related table |
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"
})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"
}])This maps a many-to-many relationship with the related table to this one. This requires a “bridge” table i.e a table that maps the primary keys of both tables. 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>
Note that the DataSet result from Tags() above will also contain a getNew() function. Calling this will create a new instance of the related bean and add it to this object’s relatedBean array. The related column will be set to this bean’s localKey value
sets an explicit default value for a column
| colname | column name to set a default value for |
| defaultValue | Default value to set. If this is a function, it will be executed and its return value will be used. This function will be called with the column name, and a reference to this manager |
Defaults are automatically applied by getNew and get to the resulting deferred bean. Direct calls to findBeans, getById and create will not apply defaults.
sets several default values at once
| map | JS object where the keys are column names and the values are default values |
sets an explicit display label for a column
| colname | column name to map |
| label | label so set |
sets an explicit display label for multiple columns at once
| map | JS object where the keys are column names and the values are labels |
A DataManager-specific validator that validates a value is unique in a column
| caseSensitive | Optional, default false Set to true for exact matches. Only applies to character columns |
| includeSoftDeleted | Optional, default false set to true to include soft deleted rows in the search. |
This will perform a query against the current table looking for any instances of this value, NOT associated with this primary key. If any are found this validator will add an error .
The Myna.DataManager object that created this manager
The Myna.Database for this manager
default, false Sets the deferred status of beans generated by this manager
See: BeanObject.deferred
The Myna.Table for this manager
The columns array from Myna.Table.columns for this table
The columnNames array from Myna.Table.columnNames for this table
Date or timestamp column to set to current time instead of deleting rows
If this column exists in the table, then remove operations will instead set this column to the current time. Find operations will automatically filter rows where this column is non-null, unless the includeSoftDeleted option is passed
This manager’s Myna.Validation instance
This Myna.Validation instance is used to validate beans created by this manager.
Table data access object generated and returned by Myna.DataManager.getTreeManager for Modified Pre-order Tree Traversal (MPTT) organized tables
This object contains all of the functions of ManagerObject plus MPTT specific functions.
| Functions | |
| create | Inserts a row in the table relative to an existing node, and re-orders affected nodes. |
| remove | removes a row in the table and also deletes any descending nodes |
| hasRootNode | returns true if there is a root node in this table. |
| getRootNode | returns the root node of this table, or throws an exception |
| rebuildTree | recalculates left, right, and depth values based on parent ids |
Inserts a row in the table relative to an existing node, and re-orders affected nodes.
| data | JS Object containing the non MPTT data |
| location | Optional JS object defining where to insert this node. See “Location” below |
| underNode | Optional, default null The id of the parent node to insert under. This is unused if beforeNode is defined. Will append as the last child of underNode |
| beforeNode | Optional, default null The id of the node before which this node should be inserted |
If both underNode and beforeNode are null, then this node will be inserted as the root node, if the table is empty, or as the last child of the root node. This function calls ManagerObject.create.
removes a row in the table and also deletes any descending nodes
| id | primary key value of node to delete |
When removing the root node of the tree the entire tree will be deleted
recalculates left, right, and depth values based on parent ids
If an MPTT organized table has correct parent ids defined but inaccurate or missing right, left and depth values, this function will rebuild them. This is useful for converting an existing table to an MPTT organized table, or if an non-MPTT aware process modifies the table.
This is a recursive function and may run out of memory for very large trees
Row data access object generated and returned by ManagerObject.getById
| Functions | |
| get_<columnName> | gets a value for <columnName> |
| set_<columnName> | sets a value for <columnName> |
| setFields | Sets multiple fields at once |
| saveField | Persists a value to its underlying row |
| forceDelete | alias for ManagerObject.forceDelete, which passes this bean’s id |
| getData | returns a structure of this bean’s data |
| getLabel | alias for ManagerObject.getLabel |
| getParent | return a bean representing this bean’s parent record |
| getChildren | return a Myna.DataSet of beans representing this bean’s child records |
| remove | alias for ManagerObject.remove, which passes this bean’s id |
| save | Saves a deferred bean and returns a Myna.ValidationResult object |
| validate | Validates this bean. |
| Properties | |
| exists | true if this bean exists in the database |
| manager | The ManagerObject that created this bean |
| dm | The Myna.DataManager object that created this bean |
| isDirty | true if this bean has unsaved changes, only applies to deferred beans |
| deferred | Default false determines whether “set” operations update the database |
| ds | The datasource name for this bean |
| data | a simple JS object containing this bean’s data |
| id | The value of the primary key of this bean |
| columns | The columns array from Myna.Table.columns for this table |
| columnNames | The columnNames array from Myna.Table.columnNames for this table |
gets a value for <columnName>
This function is generated for every column in the associated table.
sets a value for <columnName>
| newval | new value for the column |
Myna.ValidationResult object representing the result of the set.
This function is generated for every column in the associated table, except for the primary key.
Sets multiple fields at once
| fields | an object of column names and their values |
Myna.ValidationResult representing the result of this action.
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
Persists a value to its underlying row
| fieldName | A column name in the row to savee a value to |
| newval | The value to save |
Myna.ValidationResult representing the result of this action.
This function is normally called from the “set” function, but may be useful when overriding the generated “set” function.
alias for ManagerObject.forceDelete, which passes this bean’s id
returns a structure of this bean’s data
| depth | Optional, 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 |
alias for ManagerObject.getLabel
return a bean representing this bean’s parent record
| column | Optional, default: first foreign key column name in this table to dereference. Must be a properly defined foreign key in the database |
var orderBean = new Myna.DataManager("myapp")
.getManager("orders")
.getById(curOrderId);
var customerBean = orderBean.getParent("customer_id");
Myna.print(customerBean.last_name);return a Myna.DataSet of beans representing this bean’s child records
| table | name of child table to check for matching rows |
| column | Optional, default: first exported key to child table column_name to match in child table. This is only necessary if the child table declares more than one foreign key to this table |
var customerBean = new Myna.DataManager("myapp")
.getManager("customers")
.getById(curCustomerId);
var orders = customerBean.getChildren("orders");
Myna.print("Orders Total: " +orders.sumByCol("order_total"));alias for ManagerObject.remove, which passes this bean’s id
Saves a deferred bean and returns a Myna.ValidationResult object
If called against a deferred BeanObject, then validate is called. If successful, then all values in data are persisted to the database. Afterwards, this bean’s deferred status is set to the manager’s deferred status
If this bean is not deferred then a successful Myna.ValidationResult is immediately returned
Validates this bean.
Calls all of the validator functions added via ManagerObject.addValidator against this bean and returns the merged Myna.ValidationResult object
| colname | Optional, default null If defined, limits validation to a single column See: |
The ManagerObject that created this bean
The Myna.DataManager object that created this bean
The columns array from Myna.Table.columns for this table
The columnNames array from Myna.Table.columnNames for this table
Sub-class of BeanObject generated and returned by <TreeManagerObject.getById>
This class has all the properties of BeanObject, plus tree specific functions
| Functions | |
| moveNode | Moves this node to another location in the tree, only applies to nodes access through <ManagerObject.getTreeManager> |
| getLeft | returns the value of this node’s “left” property. |
| getRight | returns the value of this node’s “right” property. |
| getParentId | returns the value of this node’s “parent” property. |
| getParentNode | returns this node’s parent node |
| isRootNode | returns true if this node is the root node |
| Properties | |
| childIds | an array of the node ids of this node’s direct children |
| childNodes | an array of the TreeNodes of this node’s direct children |
| descendantIds | an array of the node ids of all of this node’s descendants |
| descendantNodes | an array of the TreeNodes of all of this node’s descendants |
| ancestorIds | an array of the node ids of this node’s ancestors |
| ancestorNodes | an array of the TreeNodes of this node’s ancestors |
Moves this node to another location in the tree, only applies to nodes access through <ManagerObject.getTreeManager>
| location | Optional JS object defining where to move this node. See “Location” below |
| underNode | Optional, default null The id of the parent node to insert under. This is unused if beforeNode is defined. Will append as the last child of underNode |
| beforeNode | Optional, default null The id of the node before which this node should be inserted Returns: this node |
If both underNode and beforeNode are null, then this node will be moved to the last child of the root node.
Creates a Universally Unique Identifier
Myna.createUuid=function Myna_createUuid()
Capitalizes the first letter of every word in string
String.prototype.titleCap=function()