 OK, how many people were here last month? OK, a few. So Matt last month talked a bit about Firebase and Ember. So I'll try not to cross over too many things. So basically, Firebase is a scalable real-time backend they call it. So it's basically a JSON blob in the cloud, where each node in this JSON blob has a URL attached to it. And you can attach event handlers to these things. You can say, right, when foobar changes or has a child added or is removed, do something. And then it's got a JavaScript client. It's got an Android client. It's got iOS client. So you can have all these things meant to be talking to each other if you've got Wi-Fi. We'll see what happens here. And basically, you can listen to child added events, child change events, child removed events, and do stuff. This doesn't fit in with Ember particularly well, just because everything here is using callbacks and first promises. So basically, when things happen, we want things to happen within a run loop. So there's kind of naive ways of doing this by basically every time a child is added, stick Ember run around it, create a new thing, do various things. The problem here you run into quite quickly is, if you do every single event in its own run loop, things get very slow, which is quite interesting. You can actually watch a page build as every single node added event is happening in its own run loop. Looks quite interesting, but not great for a production system. So Firebase have got their own library called Ember Fire, which was released a couple of months ago. This is what Matt talked about last month. And this is basically a really, really thin wrapper around the Firebase library. I think it's about 120, 140 lines of code. And it means you can create an array, point it towards a Firebase reference, and it'll update in real time. Or you can create a reference to an object. And as things happen out in the cloud, it'll update. Any changes you make locally, they'll get synced to the cloud. And it's meant to sync all your devices. So again, the problem here is with it being a really, really shallow wrapper, again, this does nothing with the run loop. It does nothing with promises. So you find yourself building lots of things on top of this, at which point you might as well not be using this library in the first place. And Matt talked a lot of the issues last month. We've been using Firebase on a yet-to-be-launched system coming out in a couple of months. So before Ember Fire was released and before any of the Ember data adapters were released, we'd been writing our own library, which we called Fireplace. So basically, it does what you'd expect from a kind of JavaScript ORM. You can define models. You can set attributes. You can say what type these attributes are so that they're synchronized. Again, not something the Ember Fire library does. It just gives you back strings. If they're stored as strings in the database, you actually want those dates, all this kind of stuff. Gives you associations, all these kind of things that you would expect. So yeah, you've got attributes. You can set specific keys for these attributes. So they're stored as different things in Firebase. You can give them types. So this is a number, and it makes sure it's coerced to that, to and from Firebase. Give things defaults. Defaults can be functions, various things like that. Everything you'd kind of expect. So how do you use it? You start off, again, very similar to Ember data in that everything happens through a store. In this store, you give a Firebase root, and that is where the data is being stored. That's where it's going to fetch all the data from. So you create records. Again, pretty much identical to Ember data at the moment that you say, OK, this store, create record. Store is injected into all your controllers, routes to your components. So you've got access to this in most places that you would need to. And if you need it somewhere else, you're probably doing things wrong. So here we can create a record, save it, create an address, push that into that record, then save that again. Now one of the main differences here between this and a lot of the other Firebase libraries is that until you save, this isn't synced. We found there were 50% of the times you wanted things to happen immediately, and the other 50% of the times you want to wait because maybe you want to validate a form, you're filling in half the thing and you want to save it at the end. So it's a lot easier to say explicitly, I want this thing to go to the server now versus, oh crap, it's gone to the server, how do I stop it? And this is where we'll see if any of this stuff works. Right, OK, so we've created a person. The right bit here is basically what's in Firebase at the moment. So we've created a person. I can add an address to that. There we go, cool. So we've created something. It's in Firebase. It's been synced to various machines that are on the internet. And then we can find them by basically this store fetch person returns a promise, and that gets resolved when all those things have been loaded or what it can initially get is loaded. And then that's a live collection. So whenever anyone from any device then adds something to that list, it's added to the database, which is then immediately synced to the front end. We can then limit that by just saying limit some number. And that'll take the bottom part of the list. Basically, Firebase assumes that the last things you put in there are normally what you want to get out. So if you've got a chat application, it's normally like the last X records that you want to display. And then if we add a bunch more people, you'll see that that list is capped to five there, and it just removes the top one, adds one in the bottom. Again, Firebase takes care of all that. So updating again is exactly what you'd expect from ember data style kind of thing. You just set some properties. You save. And then you can see the bit on the right is changing as the thing in the database has changed. All you've had to do is set your properties, set save. Things are all synced. Everyone's seeing the same thing. So Firebase is just a big list of JSON. But there's a few properties behind it that you can't see that aren't returned in the default JSON response, which is a property field. So you can set a property on each one of these nodes called priority. And that determines how this thing is sorted in the database. So if we add a few records to the company, this is sorted by name just because we've aliased property, the priority property, to name Firebase on five places handling. Whenever you save that, update the priority field. And it keeps all that kind of stuff in sync. OK, cool. So you can filter records by basically saying, I want to start at this point, end at this point. And that will go off the priorities you've set. If you don't have a priority, that'll go off the ID of the node. So here, we're basically saying, starting at A, ending at J, get me all the companies back that's got a name in between those. In this case, it's just the one, because everything else is after that. Cool, so that's all pretty simple. So we showed before where a person can have many addresses and that's stored just as an embedded bit of JSON underneath each person, much like, where are we? This guy. So this guy has got this one. He's got the address embedded within the document, which isn't what you always want. Sometimes you want that to be connected to somewhere else. So we've got our companies here. We're going to say, each company has many employees and that's not embedded. So this is basically just going to be a list of IDs for each company. So we can move these into the cross. And then, again, back up here, we can see that this company has a list of employees, which is person ID, true, which is basically saying, this node exists. Go look up the person referenced to this. And Fireplace knows that it's the person object you want, because it has many people. So it has to figure out things by the name. So you've got a has many relationship with things stored somewhere else. You can then also store some metadata on there. So if you want to say, we've got these five people working here. What's their job title? What department do they work at? And that wants to be stored on the relationship, not the actual person object, because that person could work at many different places if they're moonlighting. So you have a notion of a meta model, which is basically, this company has employees, which are many people not embedded as an employee. And that employee is basically an ember object proxy that wraps whatever comes back from the person. And then you can attach further information to it. So here, we can say, over here on the right, instead of it just being employee ID, person ID, true, you then attach some extra information to it. And then that's specific to that relation. So the other kind of association you've got is, so you've got embedded, you've got non-embedded, where you've just got a list of IDs. And then you've got detached, which is basically, this thing has some other things, but the data is not stored with me. It's stored in some other index. So because of the structure, go back. Because of the structure of Firebase being one big JSON tree, sometimes you want to store things in different orders based on some kind of property. You want to store multiple indexes maybe for an individual association. So here, you can basically say, we're going the other direction here from a person to a company to say, these are the companies that I work at. We could just model this as, again, has many embedded false, but in this case, we want to store this somewhere else in the tree. So we can just give this a path to say, OK, store this index at slash employments ID being this object's ID. And this path can be any kind of level of complexity. So here, we can say, this person works at these four companies, busy guy. And this is just stored at slash employment's person ID. So quite a lot of things if you're doing different kinds of ordering. So if you've got a task manager, and each person has a bunch of tasks, and those tasks can be sorted by created date, last updated dates, various other things, you could do that locally by just getting all that data back and then sorting it. But if you have a ton of data, you want to leave that down to Firebase. You end up having a few of these indexes per record. So same with permission-based stuff. So this person has access to these things. And it's kind of down to you as the client to manage those indexes. You're taking on some of these kind of database complexity of managing your indexes locally. Or you can have a server updating these things for you. So yeah, we've seen there that you can customize the path for a relationship. You can also customize where you're storing this data. So in this case, app.person would normally be stored at slash people using Ember inflector to figure out a pluralized version of that. And you can just say, OK, in this case, this model is stored at this path in your data in Firebase. And like the path for the detached associations, you can also have that as any kind of complexity. So in this case, a person is stored at members slash for slash some project. And then that have an index of, in this case, the actual models there in Firebase. In that case, whenever you create a person or go look for a person, you have to give it that project and say, I want to find the people for this specific project. So in this case, you've set up a model and you say, it's always got a project. When we fetch it from the database, it's this project. And when you've got any association, you say, OK, this is the query that fulfills the path of this item. So we've got Ember Inspector support with this. So if I bring up the Inspector, so here we can see all the data that has been loaded. And then you can inspect, OK, these are all the people that we've either created or found, all the data associated that, and the path on Firebase, which is really handy when you think you've stored something in one place and actually it's somewhere else or various things. Makes it a hell of a lot easier to debug, especially because this isn't going over Ajax. You've got no way of saying, OK, I've saved this. Where's it gone? So you can open up the network inspector and look at your Ajax request and see what's happened. It's really quite handy to be able to say, this object thinks it's meant to be stored here. It's not. And you can do all kind of filtering. So that's really quite cool. And the promises plug-in to Ember Inspector will be quite handy as well, so you can say, OK, this has been saved. What stage is it at? And we got there. Questions? Never doing a live demo again. This looks very, very close to an actual Ember data adapter. Yeah. But deliberately, it's not. No, when we started working on this, Ember data was kind of prior to the JJ Abrams regroup kind of stuff. And similar times, because you had the kind of trying to fit all these kind of things into Ember data when it's kind of a moving target, is a bit of a nightmare. And just kind of a lot of parts of Ember data, kind of assume a rest kind of API, where here you've got a different structure. And by building something specific, we can assume things like everything has a reference. Everything knows its tree. So we know that a person that has an address that has something else is at this path by the nature of its structure. So it's a lot easier to do something separate. Likewise, with the Ember models, got a Firebase adapter as well. But again, it's kind of the same kind of level of Ember fire. It's really simple. And when Ember fire came out, it was a case of, well, can we contribute to this? But Ember fire is about 120 lines of code. This is about one and a half, 2,000 lines. It felt a bit rude to open up a pull request, which is all this new stuff. So we'll keep it separate for now. But yeah, if we can load some of this stuff in with Ember data or other things, that would be great. When building this, there's a lot of bits here that are either carbon copy or very, very similar to things that Ember data do and Ember model do, especially things like attributes and serializing. So you've got a date, turn it into an ISO 8601 string when you serialize. Half of this stuff is just basically lifted across. It'd be quite nice if that was extracted out into a separate library. So various different ORM kind of things can benefit from that. More of a Firebase question, so I know a huge fan of that. But it doesn't do any logic server, does it? No, it's kind of just a DOM data store. Yeah. DOM a few JSON into there. Yeah, this thing belongs to this node. You've got some kind of security things you can say. Only these kind of people, people who are logged in can see this node. So you can restrict your data quite nicely. Other than that, it's not a business logic. Now I know nothing like that now. So do you do all that in the client then? At the moment, we're doing everything in the client just because it's a lot easier. But in the future, some of this stuff will farm off to the server. So there's node bindings as well. So you can have a few node servers running that just, you could put something in one place. No one looks at that and shuffles data around. We're doing similar things so that we can synchronize Watson Firebase with our other databases. Because obviously you can't do things like full tech search. So we have a node server that basically anything that happens in Firebase adds an event to a queue. Node server goes, OK, something's changed. Stick it in. Elastic search. Just so you can keep all these various things in sync. And anything that does require business logic. You can scroll away on the server there. Yeah. How does Firebase compare to something like that in Pusher? Yeah, well, we start off in Pusher. And we had a nice Gressed API using Ember model and things like that. And that was do something on the server. And that would send off a Pusher notification. I was just spending my entire life handling, right, OK, on this page, what Pusher notifications happen? How does the client react to that? And I was spending all my time dealing with just the logic of sync. What happens if you reorder a list? What kind of age response do we send for that? And what kind of Pusher notification do we get back? And in the end, I just spent so much time micromanaging. It was quite nice just to say, Firebase, does it all? Let me just get on with actually building the application itself. So it depends on what kind of things you're doing. Pusher is fantastic. But when your entire app is sync, it's quite nice to have something that just takes care of the whole sync side of things for you. When storing and taking user data, is there any way of setting the IDs or set up so you can sync it up on the fourth side? Yeah, so by default, when you create a record, it just pushes it on and push, just creates a generated ID, which is a reasonable guarantee to be at the bottom of a list. So it keeps everything in order. But you can set the ID yourself and it'll just. It's a little hard to do that. Yeah, as long as it's just a string, it doesn't have two or three different special characters in there. Can't start off with a dot. You're pretty much free to do whatever you want with the IDs. Yeah, so yeah, quite a lot of places, we have the IDs being Mongol IDs just because that's what we were originally using, things like that. But yeah, you've got complete control over that. I was wondering how hard it would be to switch to the fireplace by like in your model in applications, what would you like to do to use it? Most things are kind of pretty much the same. So it wouldn't be too much work. I wouldn't select. Incense but no. Yeah, so I'm kind of stuck to most of them. Emma model doesn't use a store. But other than that, the kind of notion of fetch returning a promise versus find returning the actual object, same with collections. If you do a fetch, it returns a promise. That's all kind of pretty much the same as the model. So I kind of tried to take inspiration or wholesale steal things from Emma model and Emma data just to kind of try and keep things in sync. Emma data is either currently moving to or has moved to fetch being a promise, find being returning the actual thing. When I look today, it hadn't done yet. Moving to it. Moving to it, yeah. So she's trying to, basically, if you've got something in Emma data, it's not going to work out about it. But it shouldn't be too much problem to move across. Cool, OK. Again, I'll be at the post.