-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
store.filter doesn't work with promises #1865
Comments
in theory you can use |
Could you tell me more about that? I don't see how I could use that at all in this scenario? Also, is there a better way to do what I am doing? It seems a bit complex |
Aw man I'm having a fairly similar set of cirucmstances recently (last night, actually!). Can't you just do something similar to this? I think store.filter is promise-aware isn't it? // model class is 'ExcitingPerson'
model: function() {
this.store.find('excitingPerson');
return this.store.filter(function(item) {
item.firstName.startsWith("B") && item.isAdmin;
});
} Oh... I undersatnd you now, you're not using find because you can't send query params to the server. Hm... I didn't even know you could do that with filter! I'm a bit confused, though... shouldn't the callback passed to filter actually received the items after they've been resolved? Why are they unresolved? |
@JulianLeviston They are unresolved (as I understand it) because comment.post is an association, and now, in emberdata, associations are all async.
|
@iwarshak gotcha! Thanks very much for that. |
So, something like this, then @stefanpenner ? App.CommentsRoute = Ember.Route.extend({
model: function(params, transition, queryParams) {
var post = this.modelFor('post');
var post_id = post.get('id');
var filterFunction = function(comment) {
return comment.get('id') == post_id;
}
var commentPromises = this.store.filter('comment', {'post_id':post_id});
var comments = Ember.RSVP.filter(commentPromises, filterFunction);
return comments;
}
}); |
@JulianLeviston @stefanpenner I think the nice thing about filter() is that when you add/delete/modify a comment, it will automatically apply that filter to see if that comment belongs in the collection (without refetching it) |
App.CommentsRoute = Ember.Route.extend({
model: function(params, transition, queryParams) {
var post = this.modelFor('post');
var post_id = post.get('id');
var filterFunction = function(comment) {
// promise in the filterFN return
return comment.get('post').then(function(p) {
return p.get('id') == post_id;
});
}
var commentPromises = this.store.filter('comment', {'post_id':post_id});
var comments = Ember.RSVP.filter(commentPromises, filterFunction);
return comments;
}
}); |
@stefanpenner um.... not too sure what point your last comment is making, there? isn't that a bit wrong because filterFunction will receive resolved promises? (bit confuzzled) |
the question from the poster was:
As it turns out This might not be ideal though, but does "work" |
@stefanpenner Apologies! I re-read your code and now understand it properly. Obvious bug in the my code was it was comparing comment id id to outer post_id. Silly me :) Thank you. <3 |
@stefanpenner I get what RSVP.filter can do, but like you said, it doesn't work with ember-data's filter() method. Do you think that the filter() method, when invoked a function should be able to handle promises which resolve to a boolean, and not just true/false? |
@iwarshak doesn't the example he provided work for you? That's using ember-data's filter method... and RSVP.filter, no? |
@iwarshak currently the store's filter method depends on being synchronous. It would be a non-trivial change. I firmly believe a better approach is possible, likely exploring a RX style form of composeability . |
@stefanpenner What is RX? |
@stefanpenner One way this problem can be solved for this particular case is to be able to directly access the post_id attribute. Is that possible as a workaround? |
@stefanpenner @JulianLeviston Tried your code sample using Ember.RSVP.filter fails with:
store.filter() returns a DS.PromiseArray, but RSVP.filter() is looking for an Array. Specifically, it fails here:
|
try App.CommentsRoute = Ember.Route.extend({
model: function(params, transition, queryParams) {
var post = this.modelFor('post');
var post_id = post.get('id');
var filterFunction = function(comment) {
// promise in the filterFN return
return comment.get('post').then(function(p) {
return p.get('id') == post_id;
});
}
return this.store.filter('comment', {'post_id':post_id}).then(function(comments) {
return Ember.RSVP.filter(comments, filterFunction);
});
}
}); |
@stefanpenner Same error, except now the comments passed into Ember.RSVP.filter is a DS.FilteredRecordArray Can I somehow just get the raw post_id value instead of traversing the relationships? |
seems like we may need to explore a baked in solution that isn't insane. |
@stefanpenner What about accessing the post_id attribute? |
@iwarshak this sort of help belongs on stack overflow. Please reopen your question there. |
@stefanpenner FYI - changing to toArray() fixes the error, but now filterFunction is not invoked. |
@iwarshak correct, hence the "shitty solution". It is a non-trivial solution to have both work right now |
I was able to work around this by accessing the foreign key object directly.
Hopefully the filter() method can be reworked in the future to be able to accept promises, or some other solution. I can see situations where accessing it via .data would not work because you are needing to access objects several layers deep. |
Hi, is there any progress on Store.filter accepting promises? |
@xmejkal I don't think we plan to add it any time soon. As this will introduce asynchrony to a currently very sync operation. I would be nervous of introducing it. |
I found a partial solution that may be of use. In my example, an Employee may work a Shift so long as they don't work two shifts on the same day. Employee hasMany Shifts async. route = Ember.Route.extend # route for employee/Fred/shift-signup
model: ->
employee = this.modelFor 'employee'
store = this.store
return store.find('shift').then -> # using emberfire, I found it necessary to find() before filter()
return store.filter 'shift', (shift) ->
# Won't work!!! BOOM!
return shift.get('employee') == null && employee.canWorkShift shift # BOOM, canWorkShift returns a Promise because it uses employee.shifts, an async hasMany relationship
# Instead we do this
return shift.get('employee') == null # defer canWorkShift to an observer, see below Use canWorkShift in an observer: controller = Ember.ArrayController.extend # controller for employee/Fred/shift-signup
needs: 'employee'
availableShifts: []
computeAvailableShifts: (->
_this = this
employee = this.get 'controllers.employee.model'
Ember.RSVP.filter(this.get('model').toArray(), (shift) -> employee.canWorkShift shift).then (availableShifts) ->
_this.set 'availableShifts', availableShifts
).observes('model.@each', 'controllers.employee.model.shifts.@each').on('init') availableShifts is displayed in handlebars and is read-only. I'm able to use Store.filter in conjunction with an observer, simulating filtering with promises. The key limitation is that the final product, availableShifts, is read-only. |
I am using store.filter in my route to load model data. I am using filter and not find so that I can pass query params to the server, and also have the model data be modified/observable.
The problem is that the function you pass in to filter expects a true/false return statement. In my situation, my filter function is dealing with promises and it isn't possible to immediately return true/false.
Here is a relevant sample:
The text was updated successfully, but these errors were encountered: