3

私はドキュメントを何度も読んできましたが、この側面はまだ明確ではありません。backbone-relational がしないことを行うと私が考えている可能性は十分にあります。

キーに基づいてリレーションシップを定義する方法を探して、定型的なフェッチのナンセンスをすべて回避します。

標準的なアーティストとアルバムの例を見てみましょう: アーティストには、album.artist_id で定義された多くのアルバムがあります。

/api/artist/62351 が返される場合があります

{
  id: 62351,
  name:"Jimi Hendrix"
}

同様に /api/album?artist_id=62351 が返される可能性があります

[
 {
   id:5678,
   name: "Are You Experienced?"
   artist_id: 62351
 },
 {
   id: 4321,
   name: "Axis: Bold as love",
   artist_id: 62351
 }
]

アーティストとアルバムの関係をどのように定義すればよいでしょうか。

var hendrixInstance = new Artist({id:62351});
hendrixInstance.get('albums');

アルバムのforeign_key artist_idに基づいてアルバムのコレクションを取得して返しますか? まだ試していないキー/キーソース/キーデスティネーションの順列であるか、バックボーンリレーショナルが解決しようとしていない問題であるに違いありませんが、私のドキュメントの理解は失敗し、これに対する簡潔な答えだと思いますSO は将来の Google 社員に役立つかもしれません。

var Artist = Backbone.RelationalModel.extend({
  urlRoot: '/api/artist',
  relations:[{
    key: 'albums', //Docs say this is the foreign key name, but in practice it doesn't appear that way. Need keySource/Destination?
    type: Backbone.HasMany,
    reverseRelation: {
      key: 'artist',
      type: Backbone.HasOne
    }
  }]
});
var Album = Backbone.RelationalModel.extend({
  urlRoot: '/api/album'
});

ボーナスは、parent_id で自己隣接リスト スタイルを参照するサンプル モデルを指します。

4

2 に答える 2

3

したがって、上記の@xzhangの方法により、この問題を繰り返し処理できました。まず、これが間違っていることを証明したいと思いますが、カスタム コードを追加せずにバックボーン リレーショナルがこの問題を処理する方法を見つけられませんでした。私の考えでは、これは OneToMany 関係の信じられないほど基本的な例であるため、何か明白なことがわからないことを願っています。

これが、状況を処理するために私が最終的に行ったことです。残念ながら、 someobject.fetch('somerelationship') が呼び出されたときにサーバーから自動的にフェッチされません。これは私が本当に望んでいることです。ほとんどの人にとって解析関数は必要ありませんが、呼び出している API には必要です。

最初に、拡張するベース コレクションをセットアップします。

  var BaseCollection = Backbone.Collection.extend({
    initialize: function(models, options) {
      if (_.isObject(options.relation)) {
      this.url = '/api/'
        + options.relation.keySource
        + '?search.'+options.relation.reverseRelation.keySource
        + '=' + options.foreignId;
      }
    },
    parse: function(res) { return res.success ? res.list : res },
  });

次に、リレーションシップの作成を支援する再利用可能なヘルパー関数 (おそらく BaseCollection にロールバックされる可能性があります)

  function collectionOptions(instance) {
    return {"relation":this, "foreignId":instance.get('id') };
  };

そして最後に、これらの関係は CollectionType として BaseCollection を使用するように指示され、collectionOptions() ヘルパーが set collectionOptions に割り当てられます。

 var Form = BaseModel.extend({
    urlRoot: '/api/form',
    relations:[
      {
        key: 'fills',
        keySource: 'fill',
        relatedModel: Fill,
        type: Backbone.HasMany,
        collectionOptions: collectionOptions,
        collectionType: BaseCollection,
        reverseRelation: {
          key: 'form',
          keySource: 'form_id',
          type: Backbone.HasOne
        }
      },{
        key: 'children',
        keySource: 'form',
        relatedModel: 'Form',
        type: Backbone.HasMany,
        collectionOptions: collectionOptions,
        collectionType: BaseCollection,
        reverseRelation: {
          key: 'parent',
          keySource: 'parent_id',
          type: Backbone.HasOne
        }
      }
    ]
  });

これにより、サーバー側 API を変更して ID のリストを返し、それらの ID を個別にフェッチする必要がなくなります。代わりに、次のことができます。

var form = new Form({id:1});
form.get('children').fetch();
form.toJSON(); //now has {id:1, ..., ..., children:[child,child,child,...]}

.get('children') への最初の呼び出しでの autoFetch children の拡張は単なるチケットですが、バックボーンリレーショナル自体を変更せずにそれを行う方法を発見していません。

于 2013-04-16T14:24:15.450 に答える
0

私はまさに問題に直面しています (バックボーンリレーショナルには多くのベストプラクティスがあります)。2 日間の調査とソースコードの調査の後、key/keySource/keyDestination が機能するとは思いません (間違っている場合は修正してください)。

そのため、独自の関係タイプを作成することになりますが、これまでのところ問題なく動作しています。これは良い解決策ではないかもしれませんが、希望はあなたを助けることができます.

var LazyMany = Backbone.HasMany.extend({
  setRelated: function (related) {
    var relation = this.options
      , instance = this.instance
    ;

    if (related && !_.result(related, 'url')) {
      related.url = relation.relatedModel.prototype.urlRoot + 
        '?' + relation.reverseRelation.key + '=' + instance.id;
    }
    return LazyMany.__super__.setRelated.apply(this, arguments);
  }
});

次に、モデルで:

var Album = Backbone.RelationalModel.extend({
  urlRoot: '/api/album/'
});

var Artist = Backbone.RelationalModel.extend({
  urlRoot: '/api/artist/',
  relations:[{
    key: 'albums',
    type: LazyMany,
    includeInJSON: false,
    relatedModel: Album,
    reverseRelation: {
      key: 'artist',
      // I didn't test this, I don't have artist_id, artist is "id" in my app
  keySource: 'artist_id',
  keyDestination: 'artist_id',
      includeInJSON: 'id'
    }
  }]
});

したがって、collectionType を定義しないか、コレクションに url フィールドがない場合、LazyMany は url: でコレクションを作成します/api/album/?artist=62351。次に、コレクションをフェッチするだけです: artist.get('albums').fetch().

これが役立つことを願っています。私はまだより良い解決策を探しています。

于 2013-04-12T19:40:37.327 に答える