Note that there are some explanatory texts on larger screens.

plurals
  1. POProper Handling of hasMany/belongsTo in Ember Data with Rails Persistence
    primarykey
    data
    text
    <p>I have an Ember.js app (1.0.0-rc.3) using Ember Data (Rev 12) to persist to a Rails backend. On the client side, I have two models that have a one-to-many relationship:</p> <pre><code>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') ) </code></pre> <p>I have configured my store to expect JSON from Rails that embeds relationships rather than side-loading them:</p> <pre><code>App.Store = DS.Store.extend( revision: 12 adapter: DS.RESTAdapter.extend(serializer: DS.RESTSerializer.extend(init: -&gt; @_super() @map "App.Child", parents: embedded: "always" )) ) </code></pre> <p>And then I have a form for creating a new <code>App.Child</code> record. In the childNewController for the new <code>App.Child</code> form view, I create a new <code>App.Child</code> and a new <code>App.Parent</code> as follows:</p> <pre><code>@transaction = @get('store').transaction() @set('content', @transaction.createRecord(App.Child, {})) @set('content.parent', @transaction.createRecord(App.Parent, {})) </code></pre> <p>I have textfields bound to the various attributes of both child and parent. When I click the save button on the form, an action in the childNewController commits the changes with <code>@transaction.commit()</code>.</p> <p>THE PROBLEM</p> <p>When the transaction is committed, Rails receives two JSON POST requests—one to the ParentController with JSON that looks like:</p> <pre><code>{"parent"=&gt;{"name"=&gt;"William"}} </code></pre> <p>...and a second POST to the ChildController with JSON that looks like: </p> <pre><code>{"child"=&gt;{"name"=&gt;"Henry", "parent"=&gt;{"name"=&gt;"William"}}} </code></pre> <p>Now the Rails ChildController and ParentController are both trying to save the new parent. </p> <p>Ideally, the request to the ParentController would go away, since I don't want it, and it lacks sufficient information to establish a relationship with the child. I would simply ignore the request to ParentController, but Ember Data is expecting a response from the server. </p> <p>Another option would be to let ParentController save the new parent, and then ChildController could look up the newly-saved parent record and create the linkage to the new child record. The problem is that the sequence of the two requests is unpredictable. </p> <p>Because of this sequencing issue, I tried putting <code>Parent.find_or_create_by_name(parent_name)</code> in both Rails controllers, on the theory that if one controller has already created the new parent, the other would only execute a lookup of that new parent record. However, this resulted in duplicate parent records!</p> <p>I'm really at a loss to understand why Ember Data insists on pushing duplicate JSON representations of the parent to the backend. I'm sure it's a simple configuration error on my part.</p> <p><strong>Update</strong></p> <p>I found an acceptable workaround for now by chaining the commits:</p> <pre><code>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, -&gt; now = new Date() transaction = currentStore.transaction() transaction.add currentChild transaction.commit() transaction = null ) newParent.get('transaction').commit() @transaction = null </code></pre> <p>Is there a better way to do this?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload