Document directory
- I. Prerequisites
- Iii. Ext. Data. belongstoassociation
- Iv. Ext. Data. hasmanyassociation
- V. Ext. Data. polymorphicassociation
- Vi. Summary
Reprinted please indicate the sourceEXTHttp://ajaxjs.com ).
One of the most powerful functions of ext JS 4 is to link the relationship ing of the model. In the ext 4 Data Model, this link is achieved through association operations. It is natural to define the relationship between different objects in an application. For example, in a recipe database, a recipe may have multiple comments. Multiple comments may be written by the same author, and the author can create multiple recipes. By defining this link, you can manipulate data in a more intuitive and powerful way.
I. Prerequisites
The first is belongto pipe Association. What is "belongto"? Let's say this ("belonging" indicates a specific link ):
- In the company database, the bill accout belongs to the company;
- In the Forum program, the post thread belongs to the forum Forum and also belongs to the category cateory;
- In an album, the thumbnail belongs to picture.
If bar belongs to Foo, that is to say, the relationship between them is belongto, then in general, in the physical table of relational database, bar table will have a field called foo_id, as the foreign key (foreign_key.
Comparatively, the association with belongs_to corresponds to the hasmany association, that is, the difference between "many-to-one" v. s "one-to-many;
Maybe we can use the concept of "Parent-Child" to understand it. For example, a parent can have multiple children, and a child has only one parent. A bill is equivalent to a company with a sub-level, and a company with a bill with a parent level ".
Currently, ext. data supports belongto (many-to-one), hasmany (one-to-many), and many-to-many. The hasone relationship is actually included in the belongto relationship.
Ii. Model instance MANAGER: modelmgr
For example, assume that a blog administrator has three business objects: users, posts, and comments. We can use the following syntax to express the relationship between them:
The sample code for edit may be different from the EXT model of the latest version, but it does not affect the main meaning-thanks to Qiuqiu/Sun reminder.
Ext. regmodel ('post', {<br/> fields: ['id', 'user _ id'], <br/> belonsto: 'user ', <br/> haswon: {model: 'comment', name: 'comments'} <br/>}); <br/> Ext. regmodel ('comment', {<br/> fields: ['id', 'user _ id', 'Post _ id'], <br/> belonsto: 'post' <br/>}); <br/> Ext. regmodel ('user', {<br/> fields: ['id'], <br/> hasmany: [<br/> 'post ', <br/> {model: 'comment', name: 'comments '} <br/>] <br/> });
You can also define attributes associations:
Ext. regmodel ('user', {<br/> fields: ['id'], <br/> associations: [<br/> {type: 'hasance', model: 'post', name: 'posts'}, <br/> {type: 'hasance', model: 'comment', Name: 'comments'} <br/>] <br/> });
During model registration, the main program is as follows (for details, see the Notes ):
/** <Br/> * register the definition of a model. The plug-ins of all models will be started immediately, and the plug-in parameters will come from the configuration items of the model. <Br/> */<br/> registertype: function (name, config) {<br/> ...... ...... </P> <p> // If We're extending another model, inject its fields, associations and validations <br/> If (extendname) {<br/> // inherit the existing business class <br/> extendmodel = This. types [extendname]; <br/> extendmodelproto = extendmodel. prototype; <br/> extendvalidations = extendmodelproto. validations; </P> <p> proxy = extendmodel. proxy; <br/> fields = extendmodelproto. fields. items. concat (fields); <br/> associations = E Xtendmodelproto. Associations. Items. Concat (associations); <br/> config. validations = extendvalidations? Extendvalidations. Concat (config. validations): config. validations; <br/>}else {<br/> // inherits from Ext. Data. Model to create a new business class. <Br/> extendmodel = ext. data. model; <br/> proxy = config. proxy; <br/>}< br/> // create a new business class/<br/> model = ext. extend (extendmodel, config); <br/> // initialize the plug-in <br/> for (I = 0, length = modelplugins. length; I <length; I ++) {<br/> plugins. push (pluginmgr. create (modelplugins [I]); <br/>}< br/> // Save the model to modelmgr <br/> This. types [name] = model; <br/> // modify prototype using the override method <br/> Ext. override (model, {<B R/> plugins: plugins, <br/> fields: This. createfields (fields), <br/> associations: This. createassociations (associations, name) <br/>}); </P> <p> model. modelname = Name; <br/> // note the clever use of call! <Br/> Ext. data. model. setproxy. call (model, proxy | this. defaultproxytype); <br/> model. getproxy = model. prototype. getproxy; <br/> // static method <br/> model. load = function () {<br/> Ext. data. model. load. apply (this, arguments); <br/>}; <br/> // start the plug-in <br/> for (I = 0, length = plugins. length; I <length; I ++) {<br/> plugins [I]. bootstrap (model, config); <br/>}</P> <p> model. defined = true; <br/> This. onmodeldefined (model); </P> <p> return model; <br/> },
Iii. Ext. Data. belongstoassociation
Ext. Data. Association indicates a one-to-one relational model. The owner model should have a foreign key (a foreign key) setting, that is, the primary key associated with the model ).
VaR Category = ext. regmodel ('category ', {<br/> fields: [<br/> {Name: 'id', type: 'int'}, <br/> {Name: 'name', type: 'string'} <br/>] <br/>}); <br/> var Product = ext. regmodel ('product', {<br/> fields: [<br/> {Name: 'id', type: 'int'}, <br/> {Name: 'category _ id', type: 'int'}, <br/> {Name: 'name', type: 'string'} <br/>], <br/> associations: [<br/> {type: 'belonsito', model: 'category '} <br/>] <br/> });
In the above example, we created the products and cattegory models respectively, and then associated them. In this process, we can say that the product is of the "belonging" category. By default, product has a category_id field. With this field, each product entity can be associated with category and generate new functions on the product model.
The new function is obtained through reflection. The first function added to the main model is the getter function.
VaR Product = new product ({<br/> ID: 100, <br/> category_id: 20, <br/> name: 'sneakers' <br/> }); <br/> product. getcategory (function (category, Operation) {<br/> // you can perform some tasks based on the cateory object. Do something with the category object <br/> alert (category. Get ('id'); // alerts 20 <br/>}, this );
When defining the association relationship, the getcategory function is created for the product model. Another getcategory function is used to send an object containing success, failure, and callback, which are of the function type. Among them, callback must be called, and success is the success function that will be called only after the associated model is successfully loaded. Otherwise, the failure function will be executed if the associated model is not loaded.
Product. getcategory ({<br/> callback: function (category, operation), // the function that will be called. A function that will always be called <br/> success: function (category, operation), // The function called when the call is successful. A function that will only be called if the load succeeded <br/> failure: function (category, operation), // The function called when a failure occurs. A function that will only be called if the load did not succeed <br/> scope: This // The scope object is an optional parameter, which determines the scope of the callback function. Optionally pass in a scope object to execute the callbacks in <br/> });
The preceding callback function has two parameters: 1. the instance of the associated model; 2. the Ext. Data. Operation object of the model instance. The operation object is useful when loading instances.
The second generated function sets the associated model instance. If only one parameter is input to setter, the following two calls are consistent:
// This call <br/> product. setcategory (10); <br/> // is equivalent to this call: <br/> product. set ('category _ id', 10 );
If the second parameter is input, the model is automatically saved and the second parameter is passed to the Ext. Data. model. Save method of the main model:
Product. setcategory (10, function (product, Operation) {<br/> // The product is retained. The product has been saved <br/> alert (product. get ('category _ id'); // now alerts 10 <br/>}); <br/> // another Syntax: Alternative Syntax: <br/> product. setcategory (10, {<br/> callback: function (product, operation), // the function that will be called. A function that will always be called <br/> success: function (product, operation), // The function called when the call is successful. A function that will only be called if the load succeeded <br/> failure: function (product, operation), // The function called when a failure occurs. A function that will only be called if the load did not succeed <br/> scope: This // The scope object is an optional parameter, which determines the scope of the callback function. Optionally pass in a scope object to execute the callbacks in <br/> })
Model allows us to customize field parameters. If this parameter is not set, the model is automatically set based on the primarykey and foreignkey attributes. Here we replace the default primary key (default: 'id') and foreign key (default: 'category _ id '). Generally, this is not required.
VaR Product = ext. regmodel ('product', {<br/> fields: [...], <br/> associations: [<br/> {type: 'belonsito', model: 'category ', primarykey: 'unique _ id', foreignkey: 'cat _ id'} <br/>] <br/> });
Iv. Ext. Data. hasmanyassociation
Hasmanyassociation indicates a one-to-many relational model. For example:
Ext. regmodel ('product', {<br/> fields: [<br/> {Name: 'id', type: 'int'}, <br/> {Name: 'User _ id', type: 'int'}, <br/> {Name: 'name', type: 'string'} <br/>] <br/>}); <br/> Ext. regmodel ('user', {<br/> fields: [<br/> {Name: 'id', type: 'int'}, <br/> {Name: 'name', type: 'string'} <br/>], <br/> associations: [<br/> {type: 'hasance', model: 'product ', name: 'products'} <br/>] <br/>}); <br/>
We have created the products and model models. We can say that users have many products. Every user instance has a new function. At this moment, this function is "product", which is the name specified in the name configuration item. The new function returns a special Ext. Data. Store that automatically creates a product based on the model instance.
// First, create a new record 1 for the user. <Br/> var user = ext. modelmgr. create ({ID: 1, name: 'ed'}, 'user'); <br/> // create a user based on the established relationship. products method, which returns the store object. <Br/> // The scope of the created store is automatically defined as a product whose user ID is equal to 1. <Br/> var products = user. products (); <br/> // products is a common store that can be added to easily add () records <br/> products. add ({<br/> name: 'Another product' <br/>}); <br/> // execute the Save command of store. It is automatically saved before. You set the user_id of the product to 1. <Br/> products. Sync (); <br/>
The store is instantiated only when the product () is executed for the first time. Persistence is not created repeatedly in the memory.
Because the store API has the filter function, the filter by default tells store to only return the primary key of the primary model that matches the foreign key of the associated model. For example, if the user is the products product owned by ID = 100, the filter will only return the products that match user_id = 100.
However, if any field must be specified for filtering at some time, for example, for a Twitter search application, we need the search and tweet models:
VaR search = ext. regmodel ('search', {<br/> fields: [<br/> 'id', 'query' <br/>], <br/> hasmany: {<br/> model: 'Tweet ', <br/> name: 'tweets', <br/> filterproperty: 'query' <br/>}< br/>}); <br/> Ext. regmodel ('Tweet ', {<br/> fields: [<br/> 'id', 'text ', 'From _ user' <br/>] <br/>}); <br/> // return the process field specified by filterproperty. Returns a store filtered by the filterproperty <br/> var store = new search ({query: 'sencha touch'}). Tweets (); <br/>
The Tweets relationship in this example is equivalent to the following code, that is, defining a filter through Ext. Data. hasmanyassociation. filterproperty.
VaR store = new Ext. data. store ({<br/> model: 'Tweet ', <br/> filters: [<br/> {<br/> property: 'query ', <br/> value: 'sencha touch' <br/>}< br/>] <br/>}); <br/>
Data may come from various places, but a common approach for us is relational databases. Most of the content in this section is based on relational databases.
V. Ext. Data. polymorphicassociation
Many-to-many relationship (due to insufficient document information ...... ......)
Vi. Summary
Compared with the server-side activerecord solution, ext only inherits and naturally does not have many advanced features. Maybe the client is enough ...... But does anyone want to run Ext. Data in the background?Oh, my God ~ Not for the purpose ......
From the perspective of technical evaluation, dynamic languages are more suitable for implementing the so-called activerecord. 4.0 adopts the activerecord concept and is also in the client. Instead of generating SQL statements, it uses Ajax requests and other requests, this idea enriches the meaning of activerecord and enhances the value of dynamic language.
Orm is a standard for almost all enterprise development projects, but there are a variety of solutions and ideas for implementing Orm. Although it cannot be said that the flowers are blooming, it can also be said that prosperity can be said that competition.
(...... Several words about ORM ...... ...... See the link below)
Since activerecord is selected for implementation, there must be some reason. Javascript is a dynamic language, and it is indeed easy to make activerecrod. This is undoubtedly better than static languages. But must I only select acitverecord? I don't know. For example, Microsoft's jslinq is also a kind of idea. I have seen JavaScript solutions (although they are all for JSON queries, they lack js2sql ), it shows that the advantage of Dynamic Language is obvious, and the language burden is not that heavy. Well, it's easy to get started with "language competition ".
In fact, the model activerecord has long been well-known. This may be one of the considerations of the extjs development team. Activerecord on Ruby on Rails and Gails is already very popular. It's not long before JS or ext is implemented ...... I have also written activerecord JS, but of course it is far behind, but it is not the actual project's "paper discussion" related concepts, theoretical instructions ...... For more information, see enterprise development instructor Uncle Ma: http://www.martinfowler.com/eaacatalog/activerecord.html ...... The preceding permission is used as a draft note.