14

親リソースと子リソースの 2 つのリソースを公開する REST サービスにアクセスしています。

/users
/users/{userId}/account

したがって、リソース「アカウント」はリソース「ユーザー」内にネストされていないため、2 番目のリクエストでアクセスする必要があります。このような REST API の例があります。

これらのモデルを使用して、ユーザーとそのアカウントを Ext Js 4 データ モデルにマッピングします。

ユーザー

Ext.define("MyApp.model.User", {
    extend: "Ext.data.Model",
    fields: [ { name: "id", type: "string" }],
    associations: [{
            model: "MyApp.model.Account",
            name: "account",
            type: "hasOne",
            reader: "json",
            getterName: "getAccount",
            setterName: "setAccount", 
            foreignKey: "accountId"
        }
    ],
    proxy: {
        type: "rest",
        url: "/rest/users",
        reader: {
            type: "json",
            totalProperty: "total",
            root: "users"
        }
    }
});

アカウント

Ext.define("MyApp.model.Account", {
    extend: "Ext.data.Model",
    fields: [ { name: "id", type: "string" }],
    belongsTo: "MyApp.model.User",
    proxy: {
        type: "rest",
        reader: { type: "json"}
    }
});

アカウント プロキシには URL がありません (これが親ユーザー モデルに基づいて作成されることを望んでいました)。user.getAccount() を呼び出すと、プロキシに URL がないため、例外が発生します。

質問: Ext Js が /users/{userId}/account にアクセスするようにモデルをセットアップする方法はありますか?

4

2 に答える 2

26

在庫の Ext クラスからは、必要なものが得られません。少し汚れる必要があります...

私が理解していることから、アカウントレコード自体のIDではなく、アカウントをロードするにはユーザーのIDが必要です。したがって、それを反映するように関連付けを構成します。

associations: [{
    model: "MyApp.model.Account",
    name: "account",
    type: "hasOne",
    reader: "json",
    getterName: "getAccount",
    setterName: "setAccount",
    // foreignKey: "accountId"
    foreignKey: 'id'
}],

ここでの大きな利点は、リクエストの URL を作成するように求められたときに、プロキシがユーザー ID を使用できることです。

buildUrlここで、必要な形式で URL を作成するために、プロキシのメソッドを置き換える必要があります。そして、すでに発見したように、そもそもこのメソッドにアクセスするには URL が必要です。

したがって、アカウント プロキシを構成する方法は次のとおりです。

proxy: {
    type: "rest",
    reader: {type: "json"},

    // Give it an URL to avoid the error
    url: '/rest/users/{}/account',

    // Replace the buildUrl method
    buildUrl: function(request) {
        var me        = this,
            operation = request.operation,
            records   = operation.records || [],
            record    = records[0],
            url       = me.getUrl(request),
            id        = record ? record.getId() : operation.id;

        // Here's the part honoring your URL format
        if (me.isValidId(id)) {
            url = url.replace('{}', id);
        } else {
            throw new Error('A valid id is required');
        }

        // That's enough, but we lose the cache buster param (see bellow)
        return url;

        // If we want the cache buster param (_dc=...) to be added,
        // we must call the superclass, which will read the url from
        // the request.
        request.url = url;
        return Ext.data.proxy.Rest.superclass.buildUrl.apply(this, arguments);
    }
}

この時点で、次の形式の URL に対するプロキシ起動リクエストが作成されます。

rest/users/45/account?id=45

これは表面的なものにすぎませんが、id クエリ パラメータが気になるのでbuildRequest、プロキシのメソッドも次のように置き換えます。

buildRequest: function(operation, callback, scope) {
    var me = this,
        params = operation.params = Ext.apply({}, operation.params, me.extraParams),
        request;

    Ext.applyIf(params, me.getParams(operation));

    // if (operation.id !== undefined && params[me.idParam] === undefined) {
    //     params[me.idParam] = operation.id;
    // }

    request = new Ext.data.Request({
        params   : params,
        action   : operation.action,
        records  : operation.records,
        operation: operation,
        url      : operation.url,
        proxy: me
    });

    request.url = me.buildUrl(request);

    operation.request = request;

    return request;
}

そして、ここにいます...うまくいきますが、プロキシの構成でこの方法でメソッドをオーバーライドすることはお勧めしません。実際には、特にそのようなプロキシを多数構成する必要がある場合は、Rest クラスから独自のプロキシ クラスを拡張する必要があります。

于 2013-07-25T12:17:04.347 に答える
5

私は同じ問題を抱えていました.rixoの答えは間違いなく素晴らしいと思いました. そこで自分用に採用したのですが、その後少し手を加えたので、今使っているコードです。利点は、1 つのパラメーターをさらに連結して、サービス URL を好みどおりに完全にフォーマットできることです。

// Replace the buildUrl method
                buildUrl: function (request) {
                    var me = this,
                        url = me.getUrl(request);
                    var added = [];
                    for(var p in request.params)
                    {
                        if (url.indexOf('{' + p + '}') >= 0) {
                            url = url.replace('{' + p + '}', request.params[p]);
                            added.push(p);
                        }
                    }
                    for(var a in added)
                    {
                        delete request.params[added[a]];
                    }

                    // That's enough, but we lose the cache buster param (see bellow)
                    return url;

                    // If we want the cache buster param (_dc=...) to be added,
                    // we must call the superclass, which will read the url from
                    // the request.
                    request.url = url;
                    return Ext.data.proxy.Rest.superclass.buildUrl.apply(this, arguments);
                }

このようにして、次のような「request.params」オブジェクトを指定して、「/service/{param1}/{param2}/?abc={param3} 」のような URL を使用できます。

{ "param1": "value1", "param2": "value2", "param3": "value3" }

また、ここで使用されるパラメーターはすべて「params」オブジェクトから削除され、後でクエリ文字列に連結されないため、「buildRequest」メソッドをオーバーライドする必要もありません。

これがお役に立てば幸いです。どんなコメントでも大歓迎です!

于 2015-08-28T12:11:11.877 に答える