Uncommitted record still present after rollback() - ember.js

I have the following in an ObjectController and have verified that both actions are called correctly:
setup: ->
transaction = #get('store').transaction()
post = transaction.createRecord(App.Post, {postedAt: new Date()})
#set('content', post)
cancel: ->
#get('content.transaction').rollback()
However, despite the transaction being rolled back the uncommitted record is still present in the data store.
Should I be handling created records differently in transactions?
Edit: I'm also seeing errors such as this after rolling back the transaction:
Error: Attempted to handle event `didSetProperty` on <App.Post:ember926:null> while in state rootState.deleted.saved. Called with {name: title}

Related

No template update after createRecord with findQuery fetching

I'm wonder why my template doesn't get updated after createRecord when using findQuery to fetch data.
When changing this return this.store.findQuery('timetracking', {year: year, month: month, user_id: user_id}); to return this.store.find('timetracking'); the template gets updated with my new records.
I don't want to fetch all records to save bandwith, but when using only find/findQuery with query params, my newly created records doesn't show up in my template.
Do I have to do a "force" reload? And how to do this?
Update
The Ember inspector shows the new records.
findQuery puts the job of filtering on the server's back. Ember Data assumes that the results that were returned are the only results that are associated with that collection. find with no query or id (findAll) will always return all records found in the store, because it realizes you weren't looking for any filtered set, if you create a new record it gladly knows to include it in all of the available records. You can manually push a record into a collection of records using pushObject.
// assuming you're in the context of your `findQuery` results, and they are the model
var model = this.get('model'),
record = this.store.createRecord('timetracking', {...});
model.pushObject(record);

Force ember data store.find to load from server

Is there a nice way to force Ember Data to load the resource from server eaven if it has it already in store ?
I have a simple show user action that do store.find('users',id) the model is loaded only once at first attempt to display a page the second time i go my model is loaded from the store which is normal ember data behaviour i know. However i need to load it each time.
edit:
the only way i found is to do this :
#store.find('user',{id: params.user_id}).then (users)->
users.get('firstObject')
however it forces me to implement a "fake" show action on my index action ...
I think this... http://emberjs.com/api/data/classes/DS.Model.html#method_reload
model.reload()
Good luck
Additionally you can call getById which will return any instance of that record that exists, or null, then call unloadRecord to remove it from the cache. I like Edu's response as well though, then I wouldn't have to worry about the record existing somewhere else. Maybe I'd use getById then reload that way any references that had a reference to the user got updated. (pardon my errant coffeescript, if it's wrong).
user = #store.find('user', params.user_id)
if (user)
#store.unloadRecord(user)
Hot off the presses, thanks to machty:
There's a new method getting added as part of the query params feature going into beta this weekend called Route.refresh()...
/**
Refresh the model on this route and any child routes, firing the
`beforeModel`, `model`, and `afterModel` hooks in a similar fashion
to how routes are entered when transitioning in from other route.
The current route params (e.g. `article_id`) will be passed in
to the respective model hooks, and if a different model is returned,
`setupController` and associated route hooks will re-fire as well.
An example usage of this method is re-querying the server for the
latest information using the same parameters as when the route
was first entered.
Note that this will cause `model` hooks to fire even on routes
that were provided a model object when the route was initially
entered.
#method refresh
#return {Transition} the transition object associated with this
attempted transition
#since 1.4.0
*/
You can do this in the setupController hook, using a promise, and the reload method mentioned by Edu.
setupController: ->
#store.find('myModel', 1).then (myModel) ->
myModel.reload()
If you are sure that records to display will change after a certain action then you can call this.refresh() method in your Route. For example:
ProductsRoute = Ember.Route.extend
model: ->
#store.find 'product',
activated: true
actions:
accept: (product) ->
if not product.get('activated')
product.set 'activated', true
product.save()
.catch (err) ->
console.log err
product.rollback()
.then =>
#refresh()
ignore: (product) ->
if not product.get('ignored')
product.set 'ignored', true
product.save()
.catch (err) ->
console.log err
product.rollback()
.then =>
#refresh()
If actions are called from child route - e.g. products/proposed - models will be reloaded for parent route and also child routes.
I think that what you are looking for is DS.Store#fetchById

Ember Data - rollback if navigating away from a form

My application has new / edit forms for a set of entities read from a backend.
When I open such a form, and fill out / edit some fields, then navigate away, the records appear changed in the entity lists, even though I did not commit those changes. Reloading the app (which reloads the data from the backend) fixes the issue, but is not an option.
I've tried doing some transaction rollbacks in the form view's willDestroyElement, but this seems fundamentally wrong since it gets called even after successful form submits (and actually crashes with Attempted to handle event rollback on X while in state rootState.loaded.updated.inFlight).
How would I go about ignoring all unsubmitted form changes (similar to pressing the Cancel button, which performs a transaction rollback), for any use case that involves navigating away from the forms?
Using Ember rc5, Ember Data 0.13.
When exiting the form route, check the state of the record. If its (isNew OR isDirty) and its NOT isSaving, rollback:
App.FormRoute = Ember.Route.extend({
deactivate: function() {
var model = this.controllerFor('form');
if ( (model.get('isNew') || model.get('isDirty')) && (!model.get('isSaving')) ) {
model.rollback();
}
}
});

What is Ember data's defaultTransaction?

What exactly is the 'defaultTransaction' in get(this, 'defaultTransaction').commit(); of ember-data's store?
Taken from the source code inline documentation:
This method delegates saving to the store's implicit
transaction. Calling this method is essentially a request to persist
any changes to records that were not explicitly added to
a transaction.
Since you can create a new transaction to control how your records are persisted, imagine you don't - this is the case where the defaultTransaction comes in. In other words, a transaction is needed every-time you do some CRUD with your records, but if you don't specify one then the store's defaultTransaction is used.
To make even more clear, see the method createRecord taken from here:
createRecord: function(type, properties, transaction) {
properties = properties || {};
// Create a new instance of the model `type` and put it
// into the specified `transaction`. If no transaction is
// specified, the default transaction will be used.
var record = type._create({
store: this
});
transaction = transaction || get(this, 'defaultTransaction');
...
The code line transaction = transaction || get(this, 'defaultTransaction'); reveals it all, as you can see, if no transaction is specified for the record just created the defaultTransaction will be used.
Hope it helps.

Ember Data: Delete a record without removing it from view before commit

Take the following:
FooController = Ember.ObjectController.extend
# Model is set, view is rendered, button is clicked
someDeleteAction: ->
# Object is destroyed & removed from view
#get('content').deleteRecord();
# Uh-oh... error happens here, but object
# remains 'deleted' according to ember
#get('content.transaction').commit();
Is there a way to prevent an object from being destroyed and removed from the view?
Bonus points: On a scale of 1 to Chinese Water Torture... how much fun is ember-data?
My solution:
Override DS.Model.deleteRecord so it contacts the server first, then commit the transaction.