findByAttribute inside ObjectController


#1

Im using Ember v1.0.0, Ember-Data v1.0.0-beta.3 and building using Ember-tools.

Inside my order_controller, I’ve got an action called: delivered. Once triggered, I want to make some changes to the current object (no problems here) – but I also want to query an object from this same model and make some changes to it.

Heres my ObjectController:

var OrderController = Ember.ObjectController.extend({
actions: {
	edit: function(){
		this.transitionToRoute('order.edit');
	},
	delivered: function(){
		// orders are sorted by "sequence" attr.
		var current_sequence = this.get('sequence');

		// find the next order in pipeline
		var next_sequence = current_sequence+=1;

		// HERE is the challenge!
		var next_order = App.Order.find({sequence: next_sequence});

		this.set('up_next', false);

		next_order.set('up_next', true);

		this.transitionToRoute('order', next_order.id)

	}
}

});

module.exports = OrderController;

Im using FIXTURES:

Order.FIXTURES = [
	{
		id: 1,
		name: "John Doe",
		email: "john@doe.com",
		telephone: "263663636",
		address: "123 Example Rd.",
            ......
		sequence: 4,
		done: false,
		up_next: false
	},

Basically Im looking for a way to query records from inside the ObjectController with more specific attributes than just ID.

Thanks!


#2

The API of the find methods has changed. Instead of the above, you should write

this.get('store').find('order', { sequence: next_sequence })

All calls to find return a promise, so you should add a then call to work with the result, when it is resolved:

this.get('store').find('order', { sequence: next_sequence }).then(function(order) {
  // Do something with the result
}, function(error) {
  // Handle the error
});

For other API changes, see the TRANSITION doc.


#3

Awesome, thank you!

I’ll add a couple gotcha’s I faced, in case someone else experiencing the same issue is reading this:

  1. The results come as an array, even though I know there is only one result, to retrieve it i do:

    this.get(‘store’).find(‘order’, { sequence: next_sequence }).then(function(order) { // to get the first object var next_order = order.get(“firstObject”);

    // then I can directly manipulate it like so:
    next_order.set("up_next", true);
    

    }

  2. The rest of my delivered action runs before the function inside the .then() block does so if I need to do anything with info retrieved from this query, it better be inside the then() block!

  3. I now had to run the this.transitionToRoute() inside .then(), the scope of this is no longer accurate. To solve it i simply declared

    //outside of the .then() block var that = this

and then:

//from inside the .then() block
that.transitionToRoute("order", next_id);

#4

A couple of quibbles.

  1. I would use orders as the name of the variable with the response data: order.get("firstObject") is weird to read. Expanding on that, if sequence numbers serve as ids in your app, I think there is a way to set that up as primary key with ember-data. That would make more clearer.

I would probably put everything inside the resolved branch (so inside the then(function(order) { ... }), otherwise some changes that the code outside it cause might happen before what’s inside and that’s probably not what you want.

Quoting the Ember Doctor proposal:


#5

Small question regarding point #3.

Do you mean to move it to a Route as an actions:{} like I would inside an ObjectController ?

Or with something like a afterModel: hook?

In either case, how would I trigger this transition to occur only after my delivered action is fired?


#6

Within an actions object on the route. The semantics are the same whether you define your action handler on the controller or on the route.

I’m not sure I understand. If you just move the whole delivered handler to the route, it is going to be triggered there, no extra setup is needed.