rutile
Version:
Factory automation for Mobile Enterprise.
275 lines (184 loc) • 10.4 kB
Markdown
# Schema definition
Schema definition file is imported from Config.txt by @FILE.
It should be in the same directory as Config.txt.
Schema definition file is composed of segment, entity and collection.
Segment is a unit of database made by *createdb* command.
Entity is your business entity definition represented by *table*.
And collection is an aggregation represented by *junction table*.
The segment is actually the database made by *createdb* command.
But the entity and collection is not always a representation of physical table.
You can assume this entity to be a logical definition as long as being with your stored procedure.
## Sample
```
=== Product (Product) ===
# Product (Product)
aggregate:Product/ProductProductImage
sequence:productSeq(1000)
field* type* name* search* valid* tags
---------------+-----------+---------------+-------------------+---------------+-------------------------
productID int4 ProductID key notNull
productName(*) text Product Name key,like,orderby notNull
price int2 Price num,orderby positiveValue
depositoryID int DepositoryID key - helper:Product/Depository
registerDate timestamp Registered Date timestamp,orderby timestampString
data:
1 Apple 200 1 2013-01-01
2 Orange 300 1 2013-02-01
3 Banana 400 1 2013-03-01
4 Strawberry 150 2 2013-04-01
* ProductProductImage (Product-ProductImage)
collector/collected* type*
---------------------------------------+------
Product/Product.productID int4
Product/ProductImage.productImageID int4
# ProductImage (Product Image)
featuringImage:true
sequence:productImageSeq(1000)
field* type* name* search* valid* tags
---------------+-----------+---------------+-----------+---------------+-------------------------
productImageID int4 ProductImageID key notNull
productImage(i) image ProductImage - notNull
width int2 Width num positiveValue autoset:imageSelected
height int2 Height num positiveValue autoset:imageSelected
name(*) text Image Name like notNull editor:textField
caption text Caption like - editor:textArea
```
## Term
| word | explanation |
|:---------------------|:------------------------------------------------------------------------|
| Segment | database segment, or its representation of segment definition |
| Entity | table, or its representation of entity definition, almost same as Model |
| Segment/Entity | an Entity defined in a Segment |
| Segment/Entity.field | a field defined in an Entity defined in a Segment |
| Collection | entity relation represented by junction table |
## Segment definition
The line starting with **===** represents database segment name.
This segment name should be your database name starting with an upper case character.
Trailing word noted in brackets is its human-readable name used in UI.
Whitespace character is allowed around the word.
In above sample, === at the end of the line is just a decoration.
## Entity definition
The line starting with **#** represents the start of entity definition.
Entity may have some tags defined below.
* sequence
Option for entity defining.
Defines sequence generator for this entity.
The value, just after **:** is your sequence defined in this database.
Begin number can be defined in brackets.
* aggregate
Option for entity defining.
Represents this entity has many-to-many relationship.
The value, just after **:** is the collected entity defined as Segment/Entity.
This can be an external(foreing) entity, defined in another database segment.
In this case, search query will be generated by using dblink.
(Therefore, in this case, the query will not be parameterized in auto generated implementation.)
* featuringImage
Represent this entity has image field.
The value, just after **:** is *true* if you define this keyword.
If this keyword is defined, UI will be generated as with thumbnail in List and Editor for the field.
### Field definition
The line starting with TAB, and being in an entity definition, the line represents field definition.
The first two lines will be assumed to be a comment.
(so you can define field header in there)
Field definition contains six elements.
**field**, **type**, **name**, **search**, **valid** and **tags**.
The first four elements are must items.
Each element should be separated by TAB.
White space character will be allowed around the value.
#### field
A field of this entity.
* primary key
The first line is for primary key.
Rutile requires primary key for each entity and its name should be *lowercase started entity name* with *trailing ID*,
and its value should be generated by sequence defined by *sequence tag*. (This primary key is aka surrogate key or pseudo key.)
For example, Product entity should have productID definition at the first element of field definition.
And its value should be a number from starting from 1000, generated by sequence:productSeq(1000).
* normal field
Other lines define normal field name.
#### type
Data type of this field.
| type | in db | UI |
|:----------|:----------|:------------------------|
| int | int | numeric input field |
| int2 | int2 | numeric input field |
| int4 | int4 | numeric input field |
| text | text | text field or text area |
| date | date | date picker |
| timestamp | timestamp | timestamp picker |
| image | text | image picker |
| geography | point | Ti.Map |
* **image**
If you define image type, the field will be represented by image in generated UI.
In database, that is stored as MIME encoded text.
* **geography**
This value should be a text representing postgis geography type defined by point, POINT(lon lat).
#### name
Human-readable name for this field. Used in generated UI.
#### search
Defines how to generate server and client function to search this field.
| search | generated search constraint |
|:----------|:--------------------------------------------------|
| key | match full |
| num | range, less than, greater than |
| like | match partial |
| date | range, less than, greater than |
| timestamp | range, less than, greater than |
| nearby | geo point within a distance from a point |
| area | geo point included in a area |
| orderby | orderby for this field, desc and asc |
| join | for foreign key, search by foreign entity's field |
**join** should be with **helper** tag.
According to this definition, Rutile generates server side search module and client side UI search form.
You can define multiple search properties separated by ','.
#### valid
Defines how to generate server side data check for this field.
This is optional definition, you can skip this definition but have to set **-**.
| valid | required value |
|:----------------|:---------------------------------------|
| - | don't generate validation |
| notNull | don't allow null |
| positiveValue | positive value |
| negativeValue | negative value |
| timestampString | string representing timestamp |
| dateString | string representing date |
| emailString | string represent email address |
| escapedHtmlTag | escaped html tag in the source value |
| geographyPoint | string representing geographical point |
The *valid* property does not affect on client side.
So you can input any invalid value into your generated form.
When the server receives invalid value for a field, it returns exception message for your request.
#### tags
Optional generator controls.
You can define multiple tags separated by ','.
* **helper**
Defines foreign entity.
Its value after the trailing **:** is formatted as Segment/Entity.
This tag should be with **join** keyword in search section.
If you define this tag, search logic, both server side and client side, will be generated to search its joined field.
For example, defining helper for the field of Product/Product.productClassID makes it possible to search Product/Product.productID by Product/ProductClass.productClassName.
Additionally, with helper tag, field editor will be generated as a selector for the foreign entity.
* **editor**
Whether to use TextField or TextArea for this text editor.
**textField** and **textArea** can be defined.
* **autoset**
Injecting cross edit form interaction.
Generated form UI emits an event when some value has been selected.
Field type *image* will generate image picker for the UI.
After selecting a image for the field, **imageSelected** event will be emitted.
Injected code should be defined in Inject/Autosetter.js.
And it should be an CommonJS module returns a hash object to get injecting code for appropriate event.
To set a field, Product/ProductImage.width, by an event *imageSelected* that is fired by selecting an image of Product/ProductImage.image,
Autosetter.js should have { imageSelected:{'Product/ProductImage.width':CODE} }.
The CODE should be some text value defining your injection.
*entitySelected* event also can be used.
## Collection definition
The line starting * represent the start of collection definition.
After the line, also should be appear lines starting TAB.
Collection should have two field style definitions, collector and collected.
It means the former owns the latter.
Both lines should be a primary key expression represented by Segment/Entity.primaryKey.
## Predefined data
You can append predefined data entry for yor Entity and Collection.
Data definition should be after your field definition, starting with **data:**.
Each value should be separated by tab.
See the Sample and [rutile_kickstart/README.md](https://github.com/RayKitajima/rutile_kickstart/tree/master/1st_step/en)