PDA

View Full Version : Using belongsTo / hasMany with a nesting-enabled restful store.



hickscorp
1 Aug 2012, 7:18 PM
Hello,

i'm fairly new to Ext 4.1 framework. My question might have an answer already, but i've been unable to find anything specifically related to it, so here i am.

Basically, i'm making a small application for which the backend is rails 3.2.6 based. Right now, i'm trying to add an Ext-based client to the application, and i'm proceeding with only two simple server-backed models:
- Person that belongsTo Company,
- Company that hasMany People (Plural Person).
Those two models are accessible via restfull URLs (/companies and /users). When outputing json from the server, i am not nesting any resource within the output (Eg. /companies json will not contain users, and /users will not list nested companies).

Also, those two models have their client-side counterparts defined with Ext,
The basic functionality of those models are done in Ext, and it's working pretty much as i like (i'm able to Person.load(...), Company.load(...), etc). Also, i'm able to do person.getCompany().
However, i'm unable to go with company.people, the server request being sent with a "filter" array parameter. Instead, i would like to have an nested-resource based URL to be built like /companies/1/users.

As far as i can understand, i would have to subclass Ext's Rest proxy (So i would for instance create a proxy named RailsRest) that would dynamically build URLs based on the hasMany association description (Eg. /companies/1/people instead of people?filter=[company_id=1]....).

My problem is that i really have no idea where to start... Nor if my idea would be the right approach.

Is there anyone here who knows a bit about this matter please?

Thank you very much for your help!
Pierre.

Below is what i'm doing right now. This is coffee-script, but i'm pretty sure you guys will easily deduce the javascript equivalent of this code :)



Ext.define(
'Person',
extend: 'Ext.data.Model'
fields: [{
name: 'id'
type: 'int'
useNull: true
}, {
name: 'company_id'
type: 'int'
}, {
name: 'email'
type: 'string'
}, {
name: 'first_name'
type: 'string'
}, {
name: 'last_name'
type: 'string'
}
],
associations: [{
type: 'belongsTo'
model: 'Company'
foreignKey: 'company_id'
name: 'company'
getterName: 'getCompany'
setterName: 'setCompany'
}]
)

Ext.define(
'Company',
extend: 'Ext.data.Model'
fields: [{
name: 'id'
type: 'int'
useNull: true
}, {
name: 'name'
type: 'string'
}
],
associations: [{
type: 'hasMany'
model: 'Person'
name: 'people'
}]
)

Ext.application(
name: 'PQRTesting'
launch: ->
opts =
headers: accept:'application/json'
listeners: exception:(me, res, ope, opts)-> console.log 'The proxy failed to retrieve data from the server:', res
reader: type:'json'


Person.setProxy new Ext.data.proxy.Rest(Ext.apply(opts, url: 'people'))
Company.setProxy new Ext.data.proxy.Rest(Ext.apply(opts, url: 'companies'))


Person.load 1,
success: (rec) ->
console.log 'Loaded person:', rec.data.email
rec.getCompany (rec) ->
console.log 'Loaded company:', rec.data.name
rec.people().load()
)

hickscorp
1 Aug 2012, 9:59 PM
As an complementary element to my question, consider the following declaration:


Ext.define(
'Company',
extend: 'Ext.data.Model'
fields: [{
name: 'id'
type: 'int'
useNull: true
}, {
name: 'name'
type: 'string'
}
],
associations: [{
type: 'hasMany'
model: 'Person'
name: 'people'
storeConfig:
listeners:
beforeload: (store, ope, opts) ->
console.log this, ope, opts
[ @proxy.url, @proxy.oldUrl ] = [ '/companies/1/people' , @proxy.url ]
ope.filters = []
load: (store, records, success, opts) ->
[ @proxy.url, @proxy.oldUrl ] = [ @proxy.oldUrl, null ]
@listeners = {}
}]
)

This configures the hasMany association of the Company model to switch URL (Hardcoded as '/companies/1/people') prior to sending the request. My problem is that i'm unable to retrieve the "caller" model instance that originated the load (In this very specific case, the model instance is the Company object loading people, eg. 'company.people().load()' ). i would like to be able to have the URL, or a whole different store instance configured to be able to retrieve the people linked to the company.

Of course, i'm not just trying to reach a solution for this very specific example, but a general solution that would determine the URL to be built, and the ID to be used based on the 'called' load object.