Force Ember-Data to reload belongsTo/hasMany relationships on find - ember.js

How can I tell ember-data to also reload the related entities?
When I run the the following for the second time it will nicely reload the posts, but will not reload the belongs/hasMany relationships (Which were loaded on the first time).
model: function() {
return this.store.findAll('posts',{reload:true});
},
I know there are many scenarios where this is wanted, but in my scenario the related entities can have changed.
Implement a socket.io service notifiying me of changes isn't an option as I don't have enough control of the server.
Note: I'm on Ember 2.0.0 and Ember-Data Canary

There seems to be no inbuilt solution, only workarounds.
e.g. call
store.unloadAll('typeOfRelationship');
before calling findAll

Related

How to unload a record in Ember 2.3.0?

I am upgrading an Ember 1.13.0 application to Ember 2.3.0 and I'm facing a little issue where I am unable to unload a record from the Data Store without causing Ember to make a HTTP request. I do not want to delete the record in the server. I simply want to remove it from Ember Data Store.
I was using the following Ember DS.Store API: http://emberjs.com/api/data/classes/DS.Store.html#method_unloadRecord in Ember 1.13.0 and it worked fine. Sample:
this.store.find('post', 1).then(function(post) {
this.store.unloadRecord(post);
});
After upgrading to 2.3.0, when I monitor the network tab in Chrome, Ember is making a GET request to find the record and then unload it. Because it fails to find (our server does not have an API to match this call), it doesn't unload the record and the changes don't appear in the UI.
I tried to fix this by instead doing something like:
this.store.peekRecord('posts', 1).then(function(post) {
this.store.unloadRecord(post);
});
but this doesn't seem to work. What is the right way to unload a record from Ember Data without making HTTP calls? Thanks.
Ember data automatically reloads records to keep them in sync with server. So findRecord() resolves immediately, but in background it makes request to the server and update values when it returns. This behavior was changed in ember-data 1.13.0 and is described in toc_new-adapter-hooks-for-better-caching.
The issue with peekRecord is that peek* methods just asks store and thus don't need to return promise. Therefore your code should look like this:
const store = this.get('store');
const post = store.peekRecord('posts', 1);
if (post) {
store.unloadRecord(post);
}

Url not updating when new model is saved

router.js
this.route('claim', function() {
this.route('new');
this.route('edit', { path: '/:claim_id' });
});
claim.new -> redirect to claim.edit with an empty model. this.transitionTo('claim.edit', model);
Initially, because the model is not saved we get: index.html#/claim/null
When we save the model, it continues to display as index.html#/claim/null instead of say index.html#/claim/87
Is there a way to force the url to refresh?
The only way to force the URL to refresh is to force the route/page to refresh. You can use the refresh method in your route to do that.
To understand why it doesn't update automatically, you have to understand how routes work and how Ember is separate from Ember Data (or any data persistence library).
First, you have to remember that Ember has no knowledge of Ember Data and the specifics of its object model. It just sees plain Ember objects. Ember Data models are more important than other models to you, but Ember isn't aware of that distinction.
Second, the routing in Ember is binding/observer aware. It doesn't watch for changes and update URL state accordingly. It calculates the URL once using the serializer hook, then it leaves it as that. It's not going to recalculate if your model changes in any way. It will only recalculate when it's refreshed.
Short story long, the part of your application that changes the ID of your model and the part that calculates the URL to use aren't aware of each other. You'll have to manually sync them up. Using the refresh method is probably easiest way to do that.
UPDATE: As Kitler pointed out, you can also transition to your route using the new model. It won't fire the model hook so it won't have to do any asynchronous work, but it will still update the URL.

How to unload ALL models in Ember-Data

Ember-Data Store has unloadAll method for unloading records for given type. How to unload records for all types?
Great question #jaaksarv. According to the Ember Core team, one would use the App.reset() method to:
Clear all the data in the Ember container.
Rebuild the container anew and then route back to the URL.
See
Ember Discussion on the matter and for a more complex options see the how-to on the API Docs.

How to communicate data between controllers in Ember.js?

I am in the painfully slow process of learning Ember and find the guides and documentation severely limited when it comes to non-trivial examples.
To my question now.
Given the following router definition:
App.Router.map(function () {
this.resource('home', function() {
this.resource('weather', function() {
this.route('site', {path: '/:weather_site'});
});
});
When the user enters the home.weather.index route the model hook executes and fetches all weather information from the server. When the user then enters home.weather.some_site the model hook of the new route would bring weather data for that particular site from the server. How can this redundancy be prevented? In other words, how can controllers communicate data to each other? Should I use the setupController hook in each Route to achieve this or are there better ways?
Are there any good resources to help me understand the data flow in and out of Ember? Are there any good resources to help me learn Ember faster than digging into the source?
How can this redundancy be prevented?
It's not clear if/how/why the model hook for home/weather/index would fetch all weather information from the server. If that's desired behavior, then totally agreed there is no reason to fetch the same data when user enters home/weather/site.
If you are using ember-data there should be no redundancy since:
when user visits home/weather/index App.Site.find() fetches all weather data
when they visit home/weather/site App.Site.find(weather_site) returns site from cache and does not make a new request to the server
if user visits home/weather/site directly (or refreshes browser) then App.Site.find(weather_site) will call server and fetch just data for that site.
So unless there is something I'm missing there is no redundancy to prevent.
In other words, how can controllers communicate data to each other?
Seems unnecessary, but since you ask: Controllers communicate with one another via bindings. You declare a dependency from one controller to another via the controller's needs property, then Ember inject's a that dependency automatically. See the ember guide dependencies-between-controllers for more on how this works.
Should I use the setupController hook in each Route to achieve this or are there better ways?
That shouldn't be necessary in this case.
Are there any good resources to help me understand the data flow in and out of Ember?
Not clear what you mean by data flow. Best guess is that you'd learn a lot from Luke Melia's gothamjs presentation
Are there any good resources to help me learn Ember faster than digging into the source?
Reading the source is always a good option, but there are many other resources. I recommend checking out embercasts and ember weekly

Ember Data RESTAdapter is not Submitting Requests to the Server when I run Model#find()

I am developing an Ember app. I am serving the API and the ember app from the same server on localhost.
I am pretty sure my API conforms to Ember specifications (although I'm not sure, because conflicting information is given here and here. The second site is linked to from this Ember blog post, and is supposed to be a formalization of Ember's conventions). My API follows the style of the second link, so requesting host/api/users/1, for instance, returns:
{
"users": [{
"username": "jojo"
etc..
}]
}
I know my API is working because I can test it with curl. My problem is that Ember data doesn't seem to be making requests. The Chrome developer tools network tab shows that no request to load the data is being sent when I run App.User.find(). I do however get back this:
Here is the coffeescript code where I define the store:
App.Store = DS.Store.extend
revision: 13
url: 'http://localhost:9292/'
adapter: DS.RESTAdapter
DS.RESTAdapter.reopen
namespace: 'api'
And here is where I define the model, controller, and route for 'User':
App.UsersRoute = Ember.Route.extend
model: ->
App.User.find()
App.UsersController = Ember.ArrayController.extend()
App.User = DS.Model.extend
username: DS.attr 'string'
url: DS.attr 'string'
projects: DS.hasMany 'App.Project'
query_instances: DS.hasMany 'App.QueryInstance'
Am I missing something important here? I am new to Ember and client-side development in general-- perhaps there are obvious solutions here but I'm not aware of them. I'd appreciate if anyone could give a few tips on debugging Ember in general.
Since the framework is very jung there are still not so much tools besides the browser console and a debugging affiniti to debug ember applications, but some stuff exists that can help out with this task.
1. Not nearly ready for prime time but very usefull to inspect ember.js app's is the ember extension for chrome.
2. Since this PR it exists the possibility to set the flag LOG_ACTIVE_GENERATION to get information about what get's generated by ember under the hood. The active generation logging can be simply enabled with:
App = Ember.Application.create({
LOG_ACTIVE_GENERATION: true
});
3. For debugging only but very usefull is the __container__, one can inspect everything ember-data knows about it's models with ease like this:
App.__container__.lookup('store:main').recordCache
This will give you access to the store's recordCache, e.g. all the loaded records.
To inspect more in detail you can access specific records like this:
App.__container__.lookup('store:main').recordCache[7].get('data.attributes')
4. One more thing might be also usefull is to define/override the global error handler to catch all errors happening inside an ember app:
Ember.onerror = function(error) {
console.log(error);
}
5. There is also the possibility to log records directly in your templates by using the log handlebars helper
{{log post}}
or simply set a debugger breakpoint to inspect further
{{debugger}}
Hope this information helps you debug successfully your app.
I was able to solve this problem by upgrading to more recent versions of Ember and Ember data. I think that I was using incompatible versions. I initially generated my project using the Yeoman ember generator. I seriously doubt that this generator would actually give you incompatible versions, so I'm not quite sure what the problem was. It may have been:
An issue with my bower cache
An incorrect statement of the revision number in the DS.Store declaration, which I may have changed because I was unclear as to whether this needed to be included. It is not needed in the latest version, but that's not what the Yeoman generator was providing. So I may have deleted it, then added it back with the wrong version number.
In any case, for anyone else having similar problems I advise you to upgrade your versions of Ember and Ember Data and ensure that they are compatible.