Using store.all adds items to controller - ember.js

I'm using store.all to find all the current instances of an model in my store and then setting it as the model for the route in my controller like this:
model: function() {
this.store.all('activeShip');
}
That works fine, but I'm having some odd behavoir when I create a new model instance for that type. When I do, it's automatically added to the controllers model even though I never addObject. I've created a little demo here to see what I mean. As soon as you create a record, it's included in the model and updated in the view. I figured store.all would just run once, gather all the records and be done; not continue to update as new records are created.
Is this the desired behavior, a bug or am I doing something wrong? Thanks.
EDIT: Think these two issues my be related: #2375, #2542.

This is expected behavior, but maybe not desired in your situation. It's actually one common criticism of Ember Data--the inability to "fork" a model or RecordArray until the changes are persisted.
Secondly, a call to this.store.all returns a DS.RecordArray, which actually updates when new records are added to the store. If you don't want to show new records, consider using something like return this.store.all('post').filterProperty('isNew', false); to keep it from showing new records. Once they're persisted on the server, it will show in the array, but not before.
P.S. You're not actually "setting it as the model" unless you return this.store.all('activeShip'); (note return).

Related

Is it possible to observe a model property after it was loaded?

In my use case I want to invalidate a model when some of its properties change so that the user needs to revalidate before publishing his changes
invalidate: function () {
this.set('model.valid', false);
}.observes('model.solution', 'model.setup', 'model.tests')
the problem (I think) is the observer fires whenever the model changes, including when it is loaded, which may be a time where the model is valid and all attributes didn't change, but since it fires valid is set to false.
using isDirty was not helpful as the model is then always dirty
Incase my intent isn't obvious, what I have is a model that I want to be invalidated whenever some properties change, saving changes while invalid causes to model to be unpublished, it also required that the model be valid in order to publish it (however not to save it).
currently my workaround is to just validate when publishing but I would prefer if I can do the former.
I'm having the same issue, but I've found some workaround that works in my case.
Please see the link below. There is an example of using "observesBefore" function instead of "observes"
How can an observer find out the before and after values of the observed property in Ember.js?
I use observesBefore with arguments to check previous state of the model and the new attribute value being set to find out whether this is the first time the model loaded or changes made by the user.
Yes, tricky situation. Any time a model switches all of those properties have changed. In that case, I'd define invalidate on the model itself, that way the only time they change is when that particular model changes.
App.Foo = DS.Model.extend({
...
valid: true,
invalidate: function () {
this.set('valid', false);
}.observes('solution', 'setup', 'tests')
});

What is the different between Ember-data Store's currentTransaction and defaultTransaction?

General question:
I would like to get an overview of current transaction (currentTransaction) and default transaction (defaultTransaction).
Specific question:
I've been comparing in the Ember controller this.get('model').save() and this.get('store').commit().
this.get('model').save() will eventually call Ember-data Store's get(this, 'currentTransaction').commit()., see github.
this.get('store').commit() will eventually call Ember-data Store's get(this, 'defaultTransaction').commit(), see github.
In the cases of updating a single edited record, they seem to be exactly the same. How should they be used differently?
I would like to get an overview of current transaction (currentTransaction) and default transaction (defaultTransaction)
currentTransaction is for records that were scheduled to be persisted, typically via model.save()
defaultTransaction is for persisting records that were not explicitly added to another transaction
In the cases of updating a single edited record, they seem to be exactly the same. How should they be used differently?
In that case they are going to do the same thing.
In general model.save() is probably a better choice, since 1) it wont have unexpected side-effects if there are other unsaved records and 2) calling save() on multiple models will result in just one commit(), making batch save possible.
Somewhat related:
Difference between model.save() versus model.get('store').commit()

Update/Remove items in Ember Array

I'm doing prototype small app on emberjs for my project.
It's here - jsbin
I have a list of transactions, which are displayed to the user. User may update or delete some of it.
For example, after update - transaction general status must be change on "Done" if both user status is "Done" (see properties of App.Transaction model).
After "Remove" user action is simply remove from array :)
How it is correctly implemented in ember.js methodology with Ember Arrays?
P.S. Pay no attention to that transaction list is static, in the future I would use ajax-request on load of app for fill transaction list. Currently, statics is made for simplicity.
Thanks.
Here is your working jsbin.
I've changed a few things, instead of passing the id when updating a transaction we pass now the transaction itself, so you can call setProperties on it and set the general_status to Done. I've also changed this behavior when deleting a transaction. And when adding a transaction you where using always the same id which is not optimal, I've used Ember.uuid to get always on creation a new id for your new record.
Have a look at the changed code to see the changes.
As a side note I should mention that you overall approach is not quite following ember's conventions, but ember is flexible enough to make it work anyway :)
Let me know if this is what you where looking for.

EmberJS Model find not up-to-date with underlying store

For a simple overview screen I have a developed a route that sets up a controller that does an App.Location.find().
App.LocationsIndexRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('content', App.Location.find());
},
renderTemplate: function() {
this.render('locations.index',{into:'application'});
}
});
I naively assumed that this would simply go to the store and fetch me all the records, giving me an up-to-date view of the records.
Apparently not....
When an external process starts removing records from the database,
the App.Location.find() keeps on returning these deleted records.
(although the REST call doesn't show them anymore)
If an external
process starts adding records to the database, the
App.Location.find() picks them up.
If I delete the records form
within the Ember app itself the model is correctly updated.
How should I deal with this in my Ember app ? I'd like to have an up-to-date view on whatever is in my database. Right now I need to refresh the page (F5) to get an up to date view. Using the linkTo helpers shows me the stale data.
This seems to be yet another trivial thing that I completely missed in EmberJS. Is it somewhere mentioned in the docs why it behaves like that ? I guess there is a valid philosophy behind this behavior.
My overview screens is simply interested in showing the most up-to-date data. If a record is no longer in the DB the model should not return it anymore.
I've added a sample project in Github that is having this issues.
Try unloading all of the data from the store before you call find():
this.store.unloadAll('widget');
this.store.find('widget');
That will fully refresh your store to reflect what's on your server.
Have you tried App.Location.query() instead of App.Location.find()?

What can you do with Ember Data Models when in the error state?

I'm struggling to understand the workflow that would be used in the following scenario:
A user creates a model, let's call it Product. We present them with a form to fill in. The save errors for some reason other than validations (timeout, access denied etc...) In Ember, this puts the model into an error state. From a UI perspective, all I want to do is put a message on the screen (easy) and allow the user to try again (apparently not so easy).
I've seen it written many times not to reuse a transaction. I understand the logic of that. In the case of a new Product, I simple create another new Product, merge in the data from the original product (attributes, relationships) and replace the content of my controller with the new Product. This wasn't hard and appears to work nicely, although there may be (hopefully) a better way.
However, when I'm editing a Product, I have run into a serious issue and the above solution does not work. The Product model is now in the error state and I can not find any way to get a copy of this Product that isn't also in the same state.
What I cant' figure out is what I can do with this model once it hits the error state. I have tried the following:
Rollback: This doesn't work. You can't rollback a transaction in the error state.
Reload: Same as above. Not allowed to reload a record in the error state.
Grab a new copy of the record: So I try App.Product.find(id) with the same id as the existing record. It just gives me a copy of the existing record, in the error state.
I'm hoping I'm missing something fairly basic here. Is it possible to roll a record nicely out of an error state (or invalid state for that matter)?
If there is a simple way to change the state of these models, should we still be creating a new transaction for further attempts to commit?
So after a few days of reading source and experimenting, I have come to the conclusion that this is functionality that is not yet implemented. To move a record into another state you are supposed to send an event to it which passes it on the statemanager. There appears to be no events registered on the error state that allows us to recover the record.
There is an ugly workaround - I can call transitionTo on the statemanager of the record and force it into the state we want. I did not decide to do this lightly, but at this point I must continue on with the project while I wait for ember-data to evolve. So if the record is so far unsaved, we can rescue it from an invalid or error state by calling:
model.get('stateManager').transitionTo('loaded.created.uncommitted')
or for an existing record:
model.get('stateManager').transitionTo('loaded.updated')
Once this has been called, you can attempt to call commit again on the transaction that the model resides in. This will be the default transaction as the behaviour of ember-data is to move a model into the default transaction once commit has been called on it's original transaction. You can always retrieve the current transaction for a model by calling model.get('transaction')
So at the end of this, I have a way to create the typical CRUD scenario that we might see in Ruby on Rails, but I don't believe this is the ideal way to do it. I do believe however that at this point in time, neither does the ember-data team.
For those of you interested in having CRUD functionality as controller and route mixins for Ember, I have a Gist that contains the code I cam currently using. This is working fine, recovers from save errors as well as validation errors. Hopefully I can continue to refine this as ember-data evolves.
With the addition of DS.Errors in 1.0.0-beta5 (see https://github.com/emberjs/data/commit/994f3b234ef899b79138ddece60d8b214c5449e3) you should be able to call...
record.get("errors").clear();
This will clear out the previous errors and triggers becameValid.
You can trigger a becameValid event on it:
record.send("becameValid");
This should transition the model to uncommitted state.
You could try creating a parallel representation of the model as an Ember.Object that is not persisted but has the same properties as your persisted model. If your ajax bounces back in an error state you can use the error callback provided by the ajax method to do something.
In this case, the "something" might be to delete the record, and then clone the properties from your dummy object into a new record and re-save the record. On a success callback simply destroy your temp object and if all records are clean then clear your temp objects (to prevent lingering temp objects).
This could also be insane... but it strikes me as an option.