 Well, hello nice people of Ember London. I came from Planet Thoughtbot to talk a bit about building crowd interfaces with Ember, which is something I have done a little bit of research on lately And I thought I will share with you. At first I'm going to do that compulsory definition slide where I remind everyone that crowd stands for create, read, update and destroy. It's just a fancy term for all these interfaces we have seen many times, both as user and developers. They revolve around a list of records where you can just create a new record or read an existing one, update it, destroy it. Well, at the end of the day most, if not all the applications we build are crowd at heart. Hopefully with a layer of UX on top so that users don't have to be, so that users can think about their own objectives and not about these pesky records that we developers like to think about. And something about crowds is that being so important and being so present in all our applications they are also a very good way to approach a new framework and start learning the ropes because you will find primitives and common idioms and you will learn to put them together to build applications. So recently I ran a workshop at my office at Thoughtbot London because I happened to be the resident Ember advocate there and I wanted to introduce my colleagues to the framework. So I created this simple code application because they are all Ruby and Rails developers or at least they are very familiar with it. So I thought it would be easy to translate their skills to Ember by using a similar kind of application that I used to build with Rails. And I built preparing this framework, I built a very simple app very much like the one I just showed with a list of records and then you can click on new or edit and find a form very much like this one where you can just create a new record and you can save it or you can discard what you were doing and cancel and go back to the place when you came. And also for completeness I added a bit of a service side validation because if you do it correctly and your API supports it Ember can deal with it for free, Ember data can deal with it for free and it's very simple to show validation errors on your app. And it was using this feature, they realized something was amiss. I came to create a new record, I entered an invalid value, I saved, it gave me a validation error so far so good but then I click cancel and I came back to the list and the value was still there, it hadn't been dropped from the store. I had code in place to drop it from the store when transitioning away in that case but for some reason it hadn't kicked in, the value hadn't been persisted so therefore it didn't have an ID and when refreshing the browser the value was gone because it was just on the store. So I was scratching my head thinking what could possibly go wrong, the code I had at that moment for dealing with that case when transitioning away and not having saved the record was this and for some reason the lead record wasn't working. I read the documentation many times and I couldn't see what was wrong. Eventually I saw I could just do an unload record instead and it worked and I thought it was probably something I was doing wrong or some gotch I wasn't aware of but it annoyed me a bit and I did make a point of making a note of that I actually put together a gist on github where I explained this and I uploaded all the files all the important files that my application was using which were basically the router, the roots and the templates just to have as material for the workshop and well I didn't think this was going to go very far I didn't think I was going to find much to make notes about except that between that and 50 versions later I realized that maybe I have enough material to come here and talk to all of you about all the interesting things I have found while building the simplest of the applications with Ember Incidentally by the way the problem I was having with the lead record turned out to be a bug that I took the time to isolate and create an issue for Ember data as issue tracker and it was eventually fixed on Ember data 2.5 but this has been there since Ember data 2 beta 1 which covers more or less the space of 8 months so if you have an application affected by this bug you do the lead record on something that may have a validation error bear in mind that that may not be doing what you think it is doing anyway I'm not going to go through everything in the application and by the way before I forget I'm going to give a link to the gist at the end I'm not going to explain everything in the application because I don't have time for that but I'm going to explain a few other gotchas I found the application by the way is as I said as simple as possible so it only has one model and this model only has one attribute that is a simple string and I'm doing server-side validation so I expect that the API will handle this for me and will return things like this JSON API error when I'm sending bad data in some way so starting with actually building the app one of the first things you have to think when building a new app or a new feature in the app is what paths what URLs is going to use and coming as I am coming from a Ruby and Rails background I settle for a series of URLs that Ruby and Rails developers will be familiar with you go to slash lines by the way line is the name of the model you go to slash lines and you see a list of the records you go to slash lines slash new and you see the form to create new records and well I was deciding on this and I created these paths well I declared these paths on the router very much like this so I had a pattern root called lines and within it nested within it I had all the possible rules that I could find the application and after some experimentation I realized that I didn't really need to declare the index root because in Ember as soon as you start nesting it will create an index root for you so if you declare a root it will give you that root but if you declare that root and you start nesting if that nesting is empty you will get also root.index so root which makes perfect sense because in this second case lines is not actually a root you can land on so in fact if you try to transition to it you will land on lines.index which is a much more sensible place to land when you are trying to reach the space so that is the interesting thing I found root I'm going to move on to the templates and specifically to the form which is the most interesting template in this extremely simple app if you are a beginner who has just read the guides just the tutorial and a few pages on the guides you will probably implement this form with a template very much like this one which will have an input for each attribute and will have a button that clicking on it you will trigger the save action and save the record and well you will have a link to take you back to the list of records and presumably you will run some code behind the scenes as I was doing earlier to make sure that the data there is correctly discarded when you are cancelling but there is something here that is a bit annoying and it is that if a user lands here goes to name enter something and presses enter nothing is going to happen because the user probably expects that the record will be saved but we are saving and pressing the button not on submitting the form and what we should be doing is wrapping this on a form and saving the record on submission of the form instead, instead of clicking the button something else that can be done to improve this template is actually render the validation errors as I showed earlier, this app supports them and as long as the API supports them too and responds with validation errors in a way that your adapter and your serializer can understand them Ember data will give them to you for free just by looking into model.errors. the name of the attribute for each one of the attributes and something interesting by the way about validation errors is that normally we think about them as link to specific attributes but they can be also linked to the object as a whole what I think they call object level validation errors so you may want to also check if you are having any of those by checking model.errors.base which is a save the attribute where Ember data will put these errors that don't actually belong to any attribute again assuming that your API is communicating them back in a way that your serializer understands that's enough with the templates, I'm moving now on to the routes well the first thing you normally do when creating a route is implementing the model hook and it's super simple but it's still fine since I started doing Ember back in 110 or something like that I still find myself sometimes doing this.store.find instead of find record because even though the old finders like all or get by ID have been removed find still exists and still works pretty much in the same way that find record does so it's very easy to use that one instead of find record there are reasons why find is there and not going to go into those but it's useful to remember that we really should be using find record instead as well as all the new finders that have been there since Ember 1.13 on with the route let's go back to the form for an instant this form is super simple if you save, the save action only needs to get the record it has probably been sent along with the action save it and then on resolution of the promise, the transition away and you're done the cancel action is the one that gave me trouble when I started all this and it's one that deserves looking a bit more in detail how it should be implemented so when we are canceling a creation or an update of a record when we transition away or before we do we should first grab the working record then we should discard all the changes on it and if it is a newly created record we should also remove it from the start which my code was failing to do earlier and then we can finally leave but making sure that we are clean after ourselves and I will explain in a moment what this means first, I have seen code out there in the wild that uses deactivate here and we should be using the wheel transition hook instead the activate doesn't fire if you move from a root to the same root with a different model which will happen if for example you're showing the edit form along with a list of records and then while editing one you click on editing the other you will be moving from the edit root to the edit root changing the model but the activate wouldn't fire wheel transition will fire there and will ensure that you clean after yourself properly now that we know which hook to use we need to grab the existing record or the current record and this seems to be the two accepted ways of doing this after my asking around a bit you either go through the controller and get the model and by the way here I'm assuming that I'm not doing this on the controller which I could be doing but since I wanted to simplify the application as much as possible I did all this in the router instead and the second way to do this is using model 4 and feeding it the current root name the way I started doing this when I first started doing ember was like this because I didn't know better and first apart from the difference with this here by the way is that I am feeding a string literal instead of a string literal that will have to update if I move things around my chain names and also if I misspell something like I actually did here the first time I wrote it which where I said line instead of lines misspelling strings tends to be the kind of error that's a bit more difficult to track down if I misspell model 4 I said for example model 4 JavaScript will be quick to tell me that such a function doesn't exist and when I feed strings to places you never know where that is going to end up something else I have seen the while for retrieving the current model is using this dot current model which is a private API and we shouldn't be using so now that we have the current model the next thing we have to do is discard the changes can somebody tell me what's the correct way to discard the changes that will work both if we are discarding a newly created record and an existing record that's correct rollback attributes which is something I really didn't know when I first started with all this in fact all this information didn't come into the documentation until ember 2 where the behavior when the record is near was properly documented it hadn't been documented before and in fact something that annoys me as lightly about rollback attributes is the name because if you are rolling back attributes on an existing record then the name works well but if you are rolling back attributes on a newly created record that is also going to be dropped from the store then rollback attributes in my personal opinion doesn't quite convey the same significance and that's probably one of the reasons why I missed it for so long and instead I was running code like the one I was running earlier but what, it's on the guides, it's on the API reference now and it seems to be the acceptable way to do that so this is what we should be doing instead so now we have grabbed the record and now we are undoing the changes and that includes dropping the record if it was new and now another question for the audience can somebody tell me one last thing we should be doing here and... well done! exactly we really really should be calling Super because we are using a framework hook and if you don't believe me believe Robert Jackson aka RWJ what in him, you should always call Super whenever you implement any framework hook period, end of story even if you know it doesn't need to be done you should do it and this is because you could be using a mixing that implements the same framework hook and if you don't call Super on your code the framework hook won't be called in the mixing and that has already happened to me and things won't work and you won't know why it is not working so bear it in mind this is the correct way I think to implement this feature and if you think differently please let me know because I really want to know these things and that's really as far as I'm going to go if you want to see other details and other little things I found on my research as well as the full source code of my little crowd app you can go to this URL which is basically the short link to the gist and apart from that if there's anything you disagree I would be I am all ears thank you very much