Rails バックエンドに永続化するために Ember Data (Rev 12) を使用する Ember.js アプリ (1.0.0-rc.3) があります。クライアント側には、1 対多の関係を持つ 2 つのモデルがあります。
App.Child = DS.Model.extend(
name: DS.attr('string')
parent: DS.belongsTo('App.Parent')
App.Parent = DS.Model.extend(
name: DS.attr('string')
children: DS.hasMany('App.Child')
)
関係をサイドロードするのではなく、埋め込んだ Rails からの JSON を期待するようにストアを構成しました。
App.Store = DS.Store.extend(
revision: 12
adapter: DS.RESTAdapter.extend(serializer: DS.RESTSerializer.extend(init: ->
@_super()
@map "App.Child",
parents:
embedded: "always"
))
)
そして、新しいApp.Child
レコードを作成するためのフォームがあります。App.Child
新しいフォーム ビューの childNewController で、次のように newApp.Child
とnew を作成App.Parent
します。
@transaction = @get('store').transaction()
@set('content', @transaction.createRecord(App.Child, {}))
@set('content.parent', @transaction.createRecord(App.Parent, {}))
子と親の両方のさまざまな属性にバインドされたテキストフィールドがあります。フォームの保存ボタンをクリックすると、childNewController のアクションが変更をコミットします@transaction.commit()
。
問題
トランザクションがコミットされると、Rails は 2 つの JSON POST リクエストを受け取ります。1 つは次のような JSON を含む ParentController へのリクエストです。
{"parent"=>{"name"=>"William"}}
...そして、次のような JSON を含む ChildController への 2 番目の POST:
{"child"=>{"name"=>"Henry", "parent"=>{"name"=>"William"}}}
Rails ChildController と ParentController の両方が新しい親を保存しようとしています。
理想的には、ParentController への要求は不要であり、子との関係を確立するための十分な情報が不足しているため、なくなります。私は単純に ParentController へのリクエストを無視しますが、Ember Data はサーバーからの応答を期待しています。
もう 1 つのオプションは、ParentController に新しい親を保存させ、ChildController が新しく保存された親レコードを検索して、新しい子レコードへのリンケージを作成することです。問題は、2 つの要求の順序が予測できないことです。
Parent.find_or_create_by_name(parent_name)
この順序付けの問題のため、一方のコントローラーが新しい親を既に作成している場合、もう一方のコントローラーはその新しい親レコードのルックアップのみを実行するという理論に基づいて、両方の Rails コントローラーを入れてみました。ただし、これにより親レコードが重複しました。
Ember Data が親の重複した JSON 表現をバックエンドにプッシュすることを主張する理由を理解するのに本当に途方に暮れています。それは私の側の単純な構成エラーだと確信しています。
アップデート
コミットを連鎖させることで、今のところ許容できる回避策を見つけました。
newParent = @transaction.createRecord(App.Parent, {name: parentName})
currentChild = @get('content') # we assigned a new App.Child to the childNewController in the new child route's controller setup
currentStore = @get('store')
newParent.one('didCreate', this, ->
now = new Date()
transaction = currentStore.transaction()
transaction.add currentChild
transaction.commit()
transaction = null
)
newParent.get('transaction').commit()
@transaction = null
これを行うより良い方法はありますか?