So thank you for coming. This is leveling up with Ecto. When I first started thinking about this talk a long time ago, I sort of imagined it being a lot more workshoppy and live codey, and as I started preparing it, I started to feel like the stuff that was going to be the most useful was a little more conceptual. So it's going to be a little less workshoppy than I imagined, but I didn't want to drop that component completely. So up on the screen there is a link to a GitHub repo that I set up, and it's just a simple Elixir app that sets up Ecto and sets up some sample data that I'll be working with in the talk. So if you do want to try some stuff out as we go, go ahead and give it a shot. The slides might be going by kind of fast, so there's a link on the readme to the slides so you could pull that up too and copy and paste if you need to, or refer to it later or whatever you like. So what do I mean by leveling up? Well, when we first start out with a new platform or a technology or a tool, we're a little bit awkward at first. We tend to stumble around a little bit. We lose our balance. We're not sure where we're going. Things don't often go very well, and in our desperation to get something, anything working, we become practitioners of SODD. That's Stack Overflow Driven Development. You probably know how this goes. You have a problem. You Google it. Something comes up on Stack Overflow, copy, paste, tweak a little bit. It works.  And that's kind of how it goes for a while, but over time, you start to get a sense of how things work. You get some experience trying the tool in different contexts. You learn from other people, and pretty soon you're having to Google a lot less, and it's not so much that you have the whole API memorized. It's just that you kind of understand the lay of the land, and you know where you're going, and you get a lot less of this and a lot more of this. So my goal for this talk is try to accelerate that process for you with Ecto. I'm relatively new. I started working with Elixir and Ecto around the beginning of the year, and I was stumbling around quite a bit, but I really wanted to get my head around it. So I took more of a deep dive, and what I'm hoping to do is share some of the things that I learned, and hoping that it'll make things go a little bit faster for you.  If you are a complete newcomer to Ecto, you've never seen a line of Ecto in your life, I'll be honest with you, you probably won't understand every single line of code you'll see in the presentation, but hopefully you'll get the gist, and certainly the foundational stuff that we're going to talk about will serve you as you keep going. Now if you're an Ecto expert, if you're the sort of person that provides the examples that practitioners of SODD copy and paste into their code base, there may not be too much in here that will surprise you, I'll be honest again, but if you're not familiar with the changes in Ecto 2, if you're a diehard Ecto 1 person, then there probably will be a few surprises. So that's the context. So let's talk about what is Ecto. So this is my very biased and completely unofficial definition of Ecto, but I think of it as a tool set for interacting with external data sources. And I chose these words kind of carefully. It's a tool set because there isn't just one way to use Ecto. It's got lots of different pieces to it. They harmonize beautifully and work together beautifully, but you don't necessarily have to use all of them. You can use pieces depending on what you need to do. And I say external data sources because although Ecto is best known as a tool for interfacing with relational and in some cases no-SQL databases, it can do much more. And anytime you're interfacing with external data in any way, might be files on your local file system. It might be an external API or anything like that. There's things in Ecto that can help you. It's not just for databases anymore. Ecto's a pretty big library. There's lots of pieces to it. So if you've tried to wade into the code of the documentation, it can be a little disorienting at first. But to my mind, there are kind of four main pillars that are the foundation of the whole thing. And these are good entry points. And these are repo, query, schema, and change set. Technically, there's a fifth, which is migrations. But migrations are covered pretty well in the docs, and there's not too much more subtlety around them. So I'm going to just pretend they don't exist for today. But migrations are the means of getting data into your database, and they're used in other systems as well. So let's start with repo. So repo is the part of Ecto that actually talks to the data source. And in fact, it's the only part that talks to the data source. And this is good to know, because if you're trying to manage where in your code side effects happen, it's pretty clear. You can mess around with schemas, change sets, and queries all you want. Nothing is going over the wire until you actually use one of the functions in repo. And so repo has functions that you'd expect to see. Get, insert, update, delete, transaction, the usual suspects. This isn't an exhaustive list, of course, but this is the kind of thing you find. Typically, you don't call the functions in Ecto repo directly. Instead, you create your own module in your app. That's namespace to your app. Typically, by convention, we call it repo. You could call it something else if you really wanted to, but I don't recommend it. Repo's going to be easier. And then there's a call to use Ecto repo, which pulls in the functions, but it is your own local module. Then somewhere in your configuration, you tell Ecto how to take this module and connect it to some data source. In this case, it's Postgres, and we provide all the information that needs to connect. And then from there in your code, you usually alias it. And then at that point, you just start calling repo. And as though you're talking to Ecto repo directly, but it's your module. Now, this is kind of important to keep in mind, because there are two nice consequences with this arrangement. One is that it's super easy to connect to another data source if you need to in your app. For example, if you had some legacy database that you needed to talk to, you'd simply create another module, give it a different name, legacy repo in this case, and then configure it with whatever information you needed to hook up to it. And at any point in your code, if you need to talk to the new database, you just talk to repo. If you need to talk to the old database, you just talk to legacy repo. Easy to do. Another consequence is that it's super easy to add your own custom repo functions. So let's say we were making an application that helped us manage a music collection. And we wanted to do a lot of counts. So we'd want to find out how many artists we have, how many albums we have, how many tracks. If we're doing this sort of thing a lot, we can create a little shortcut for ourselves. We can just add a function into our repo called count that takes a table name. And then we forward that on to repo's aggregate function. And then in our code anywhere we need to count, we just have to do that nice and easy. So if you find things you're doing things sort of repetitiously that interface with repo, you might think about putting your own function. Now there's some functions in repo that allow you to work pretty directly with the data in a low level way without even having to get into schemas. And they're easy to spot because they all end with all.  So for example, if you just want to throw some data into your database, you can just do a simple insert all. This call here will talk to the artist table. It will insert one record, and the record just has one field called name, and it'll set it to John Coltrane. And the thing you get back, we didn't ask for it to send us anything back, so we get a tuple with the number of records affected, and then nil, because we didn't ask for anything. If we wanted to update all those records, we could do it that way. Again, we're just using the table name as a string, and then we have a set keyword. We tell it which column we want to update, and if we want to delete them all, we can do it just like that. But what about queries, you might ask? Well, if you want to go super low level and just use SQL, you can. There's ectoadaptors.sql query, and you can throw a SQL query directly into it. I don't recommend it. The response is not super friendly, and if you don't enjoy filtering through all those tuples to create timestamps, this might not be the way for you to go. The recommended way is to use the query module. So, ecto implements a DSL for generating queries, relies on macros pretty heavily, and this DSL feels a lot like SQL, and I do mean that in a good way. What I mean is that if you're familiar with SQL, you're gonna find ecto's query syntax pretty easy to pick up, and if you don't know SQL, you're gonna learn it without knowing it, and pretty soon when you have to go spelunking through your app logs to figure what went wrong, those SQL statements that are flying by aren't gonna look like gibberish to you. You're gonna have a good sense of what they mean. So here's an example SQL query. This goes to our tracks table, and it does a join on the albums table, and it pulls back the track ID, the track title, and the album title, and we're filtering just on those tracks that have a duration longer than 600 seconds. So we're looking for the long self-indulgent longer than 10 minute tracks in our collection. This is what the query looks like in SQL. This is what the query looks like in ecto. It's pretty close. All of the SQL keywords kind of become keywords in the ecto syntax. The only thing that's unusual is the query start with from, that's almost always how the queries begin.  Now you may at some point have to deal with pesky user data, data coming from somewhere else. So if you have to interpolate into the query, you need to use that little carrot symbol. So if you see our where clause now, that min duration has a little carrot in front of it, which is us telling ecto, please evaluate this variable and stuff it in there for us. If you didn't have that carrot, ecto would get confused and think min duration was part of the keyword syntax. Now if you do that, and we're not at schemas yet, you have to think a little bit about types. So if that value might be coming in as a string, rather than an int, you're gonna need to let ecto know. So here we've modified the where clause to put a type macro around it to make sure it's forced down to integer. Now that's not very much fun, but there are ways around that and we'll get to that later. Now a really useful thing about queries is that they are composable, which means you can create fragments of queries that can be chained one onto the other so you can further refine the query down the line. So if you have some particular part of a query that's tricky, if you're drawing a lot of tables and you need to reuse it, you can. You just have to store it and then work with it again later. This allows you to do what some people in other ORMs would call scopes. You know who you are. So here's an example query. We'll talk to the Albums table and we're gonna do a join on artists, mapping the artist ID back to, sorry, the album ID back to the artist ID. And we're specifically looking for Miles Davis. So effectively this query gives us all the albums by Miles Davis. So let's call it that, albums by Miles. Now this is actually not a valid query at this point. If you tried to pass this off to ecto, you'd get a big error. And the reason is, because we haven't told it what to select. And if you don't have schemas, ecto won't know. There's no such thing as select star. And certainly if there were, you'd have to be explicit about it because that's elixir and that's what we do. But you can build on this query somewhere else. So now we're creating a new query and we're saying from A in, instead of giving a table name, we give the query that we created above. And now we can kind of interact with it in exactly the same way. Here we're just gonna get the title. So if we ran it, we would get the album titles. Now we could do something fancier. Take the same query and now we're gonna add a join onto it, which takes us into our tracks table and now we're gonna pull back the album tracks. And this would just give us all the tracks that we have in our dataset. So this ability to put queries together and slice and dice them and refine them is pretty handy. If you find yourself repeating parts of queries, it's a good idea just to stuff them all in a function and then you can call it back later when you need to somewhere else. So now that we have this query syntax, we can go back to these all functions that we were looking at earlier and do some fancier stuff. So here's a query that pulls back all the artists whose name is Art Tatum, but it looks like it's misspelled. So we're gonna do an update and correct the spelling. Here's another one that goes back to get our self-indulgent tracks and we're going to delete them because who has time for that? So the story so far, we're only a few minutes in and we can already do a lot. With repo, we can talk to the database. With query, we can construct just about any query we want to and we can insert, we can update, we can delete and we can read. So we've got the full crud spectrum. It's all good. There are a couple little hitches. First of all is that we always have to be explicit about our selects. And if you were doing something with very large tables where you're getting back lots and lots of columns at a time, this would get tedious in our hurry. The other thing is that we have to be careful about making sure we're correctly casting the types of data that we're forcing down. Like when we saw that min duration coming in as a string. It'd be nice if we had a shortcut to help us deal with these things we might have to do over and over again. And that's where schemas come into play. So again, my highly biased unofficial definition, schemas define a reusable shape that we can use to move data in and out of our data source. So if you find you're selecting the same kinds of thing over and over again, it's a good chance that you're gonna want a schema. So schemas again use a DSL. This is a typical setup. We're gonna create a track module and we're gonna pull in schema by using the use statement. And this gives us the macros that you see below. We call schema, give the name of the database table that we're mapping to and then define the fields one by one and their types. And timestamps gives us this nice little shortcut of two columns called inserted at and updated at which depending on which repo call you go through will update automatically for you. Now this saves us some typing. So here's, we go back to that query we did earlier where we're looking for the long tracks. Here's what it'll look like without schemas. You see we have to do that nasty cast on min duration and we've gotta manually select out all the fields that we want. With schemas, it looks like this. We simply have to say from T and track and because we're referring to a module that has a schema, we don't have to provide the select statement. Ecto's just gonna grab all of those fields that we've defined. And we don't have to manually cast it because Ecto's gonna do it for us. It knows that duration is an integer so it's gonna do its best with whatever comes in as min duration. String, atom number will probably work fine. If it's a list it'll blow up of course but it's gonna do its best. Now, here's the thing about schemas. Wonderful time saver here but you don't always have to use them. Just because they're defined in your project, in some situations it might be more work than you need. For example, let's say we just wanted to get all the names of the artists and the number of albums for each person. That type of query doesn't fit neatly on top of a schema. An album count is not something we've defined anywhere and it's not like we want the whole artist record or the whole album record. We really just want a simple map, name and account. And so in that case you can construct the query so we do a join, we do a group by but you can still manually supply the select if you want to.  So schemas are great but you don't need to go overboard with them. Especially when you're in reporting types of situations where you're grabbing data from lots of different fields. Let them go and do your own selects and there'll be a lot less data to come through. Now schemas are a huge help when it comes to dealing with associations. So associations you may know are what allows us to create relationships between tables. So we've modified our artist schema to say that it has many albums. And we refer to the name of the association we're gonna call it albums and the struct that has the schema that we need which is musicdv.album. And this assumes of course that we've set up our migration so that there is an album or sorry an artist ID on the album table. There's four different kinds of associations you can have. Has many, has one, belongs to, belongs to is what sits on the other side of a has many or has one. And as a Vecto2 you can do many to many which is pretty nice. The album schema uses a bunch of these. It belongs to artist. It has many tracks. And it's got a many, many to relationship with genres. Genres being the type of music. Jazz, funk, rock, speed polka, whatever you want. Now if you wanna see the association records now that we've got our schema set in place for album we can use repo.get. We pass in the struct name which is album and an ID. This is gonna give us album number ID. And then we simply use dot notation to get album dot tracks. And when we do this we get the dreaded Ecto association not loaded. Who's seen this one? Yeah, kinda gives you this feeling. Okay, why did this happen? So here's the elixir thing at work. Ecto will not go on a fetch associated records unless you specifically ask it to.  You really don't want your database interface running around and grabbing whole bunches of records without your knowledge. And if you don't believe me after the talk go and Google N plus one queries. I won't take the time to get into it now but there's probably people in this room that can tell you some painful stories. There's guy nodding right there. Can tell you some painful stories about what can happen. So the takeaway is when you're dealing with associations and you're running your queries you gotta be super specific about which ones you want. So here's how you fix it. One way to do it is to add preload keyword to your query. So you just set up your query like normal but then you say preload and specify the association that you want. In this particular case it's albums. We're gonna load the artist named Bobby Hutcherson and we're gonna get the albums back as well. And you can nest these if you've got associations on top of associations. So in this case we're not only gonna get the albums by Bobby Hutcherson but we're gonna get the tracks. And these are groups together because tracks are not directly related to artist but albums have a has many relationship to tracks. So we do nesting that way. If tracks had a has many to something else we do another keyword list and you can just go turtles all the way down. Another way to fix it is you can use preload after the fact. This will save you when you're typing around in IEX and you hit that association not loaded. You can fetch the record and then once you have the record you can pass it to repo preload and then that'll get the associations for you. So if you're in IEX you don't need to redo the whole query over again. You can just slap yourself on the forehead like you normally do and pass the record into preload and you're good to go. Now another great thing about this scheme and the association support in Ecto is that inserting new records when they have complex nesting is now a total breeze. So imagine we wanted to insert an artist one of his albums and all of the tracks all in one shot. You can do it like this. So we call repo.insert and then we set up the artist struct we set the name and now we have the albums association. And so we set that up since it has money as a list and we create an album struct within that list create an title for that album then set up a tracks association within there and then four more structs underneath that and this will absolutely do the right thing in terms of figuring out which foreign keys go where. Now please just take a moment and bask in the beauty of that and think about how, yes it does deserve a pause. Jose and Eric and Mio, thank you and think about how easy it's gonna be to set up your development database next time. By contrast, here's what that data structure looks like in JSON. This is just pure JSON and that's executable elixir code. You wanna talk about clean syntax. It doesn't get any lighter than that. So this is a fantastic way to dump a whole bunch of data into your database at once. Provided that data is valid. Now it's okay to do that in development with data that you know about.  If you're throwing user input into the database you wanna make sure that it's the data you expect. You wanna make sure it's in the format you expect and that it's all valid and that's where change sets can help you out. So change sets allow you to filter, cast and validate the values that you wanna send to your data source. Also helps you track errors. So here's a typical usage. Somewhere in your code base you import change set and then we've got these params that came from somewhere. We don't know where but we've got a map of title and index. And then we set up the change set by using an empty struct that's mapped to one of our models. Oh, I said model, I'm not supposed to say model. To one of our modules, it's so close to model that we set up as a schema. And then we call the cast function and cast is provided by change set. And this is gonna do two things. First of all, it's gonna filter the params. That second argument to cast defines, it lets us specify which fields we want. So we're saying we just want title and index. If those params had anything else in there they would just get thrown on the floor and ignored. The second thing that's gonna happen is that they're gonna be cast into the correct type. So if you see that index value up there as a string this cast call is gonna convert it into an integer. And what we get at the end of cast is another change set. And change set can be passed into the validate functions that the change set module provides. And so that first one we can make sure that title and index were provided. That's what validate required gives us. And we can make sure that we got a number greater than zero for index. Now once we have this change set we can just kinda see if it works. So we'll pass it into repo insert and see what we get back. If we get a tuple with okay and the track we know it worked. And if we get error and the change set given back to us then we know it didn't work. But at this point change set has been populated with an error struct that tells us exactly what the errors were. So if for example we had left off title that's what we would see in change set errors. It would tell us what the field is and what the problem is. Change set ships with a whole bunch of validations that are pretty useful. You can look at strings, verify format of strings, check on numbers, check booleans, all kinds of things. But as you're searching through the documentation looking for the validations that you need make sure you're also looking for the constraints. And these are functions that end in the word constraint. Constraints work exactly like validations in that you can pass them through just as we did with the validates and they will populate change set errors if there are problems. But constraints are special because they actually verify it at the database level, not necessarily on this side of the wire. So take an example, the unique constraint. So sometimes in your data you need to have columns that are guaranteed to have unique values. Like in a user table the username you wanna absolutely be unique. Now you can sort of try to enforce that on your side but really the only way to be sure is to set up a unique index on that column when you first set up the database. So that way the database will absolutely enforce it and make sure you don't get duplicates. So if you do something like this where you take the change set and you apply the unique constraint to it, provided everything else is okay with the change set Ecto will actually try to execute this query. But it will check the error that will come back from the database if the uniqueness was violated. Catch that and then put it into your errors as if it was a regular validation error. So validation errors and constraint errors are gonna look exactly the same in that error structs. It's just that anything that's constrained you know came from the database and you know is for real.  Yeah, it's available. Okay, let's give it a try. You shove it off to the database but you know the index is there so you might get an exception. So an exception comes back and that either means that the server blew up and the database is completely offline or the username is simply not available. So you had to figure out looking at the exception which was which. Ecto does all this for you behind the scenes. So you get the guarantees that the constraint is good without having to muck around through a bunch of exceptions. That's pretty nice. So validations on their own are pretty handy. You could imagine how they might be useful outside of a database. Let's say you were talking to some sort of third party API and you were collecting some data. You might want to make sure the data is good before you send it off. Validations are handy for that. Can we use them? Yes, you can. Because you can have schema-less change sets in Ecto. Yes, you heard me correct. You can define a change set without a schema it just kind of looks like this. Probably not correct to say schema-less. It's more like schema on the fly. You can create a map that defines the parameter names and the types that you want to enforce. So in this case, we're gonna say that our API is expecting a band name and an album name and they're both strings. Here's the input we're gonna use. The band name is modern jazz quartet and we're gonna drop off the album name because the user was feeling obtuse that day. And then you set up a change set just as you normally would. But instead of that empty module, I said it right this time, that we used before, we pass in a tuple. First is just an empty map and then the second are the types that we defined earlier. So we're telling Ecto, this is the structure we wanna enforce. From there, we can just treat it the same way. We call cast on the params and we can run our validations. And at the end of it, we can ask change set if it's valid. In this case, it's gonna say false. And if it's false, we can look at the errors and it looks exactly the same as if we were using a schema. So if you can think of a place where you'd like to use those validation functions and it's not in the context of database, you can. You can just use change set on its own. Let's talk for a little bit about Phoenix integration. So if you've done any work with Phoenix, you've probably discovered that Ecto and Phoenix play pretty well together. That's because if you look in your dependencies, you'll see that there's another package called Phoenix Ecto, which kind of provides the glue. Phoenix Ecto just adds some definitions for behaviors that Phoenix is expecting and puts those onto some of the modules from Ecto. And this is why, for example, when you're setting up a form in Phoenix and you have form for, you can pass in a change set and you can use these nice shortcuts for setting up the form fields. And you don't have to do all that mucking around with names and values yourself. It's pretty handy. So this works very, very nicely, but there's one drawback, which is that it implies that there's kind of a one-to-one correspondence between our schemas and therefore our database tables and our user interface. So this works great if our form looks exactly like our database, but, and that works some of the time, but that may not always be what you wanna do. Let's take the track example. Now let's say we wanted to create a form for user to input tracks. The duration is kind of tricky because in the database we're storing it as an integer of the number of seconds. That's not a very friendly interface for the user to do. Normally when a user sees duration it's expressed as a string, minutes and seconds. If we want to get that as seconds, we have to ask the user to do some math. Now we could create a separate form that would do this, but then we lose all that nice convenience of just passing a change set directly to form for and being able to construct all the fields. Well, change sets and schemas have a couple other tricks up their sleeve to get around this. One of them is virtual fields. So one way we could solve this is add another field to our schema called duration string.  And you'll notice we've added a keyword called virtual true on the end. So this is our little cue to Ecto saying we're not gonna try to persist this. This is just something we're using for our own purpose. Ignore this, move on. Having done that, over in Phoenix land when we pass the change set to form for we can use duration string as a first class citizen when we're setting up our forms. It'll work just the same as all the others. Now back in our controller or the module that the controller uses according to what's coming in 1.3. I'll be agnostic about that. We set up our change that is normal. We set up the track. We cast it. We do the validations. But now we're gonna do another step, which is we're gonna convert the duration string over to an integer. And we'll do a separate function for this. I didn't pass the change set there, that's all right. So we'll take the change set in the separate function and we'll call get field, which is a change set function to get the duration string out of the change set. This is the string that the user provided. And then we'll do some sort of magic conversion to take that string and turn it into an integer representing the number of seconds. So how you take something that says four colon 33 and turn it into a number of seconds, that's an exercise left to the reader. Now once we have that integer, we can put it back into the change set by calling put change. And now we're using our real duration field, the one the database actually knows about, and supplying the integer. And that's been back from there. We can go ahead and validate it to make sure that we got a number that's graded from zero. So this is a subtle shift, but it points to something kind of important, which is that we now have a way to decouple our UX from our database tables without sacrificing the convenience that comes from passing change sets around. If the form that you wanna present the user looks exactly like the database table, no problem, you're good to go. But if you don't want it to for whatever reason, in this particular case, there's a way around it. And you can go even further. And here's another big secret, schemas don't actually have to have a database table associated with them. There is a feature in schema where you can define what's called an embedded schema. And this is sort of like an entire schema full of virtual fields, that you could then pass into a form, collect the input, validate it, and then convert to the real schema that you wanna use. It sounds insane, but it's true. I don't have time to walk through an example right now. So I would refer you to this blog post that Jose wrote called Ectos Insert All in Schemeless Queries. He's got a really nice example in there where he demonstrates how a form you might use to sign up a user would be different than a form you'd use to edit the user content, but how you can map that back to the same schema in the back end. It's super handy and I strongly recommend reading that blog post because it'll just open up your mind a little bit about what is possible with keeping the convenience of the Phoenix Ecto integration, but providing a more flexible and more dynamic UI. Okay, that was a lot of stuff. We've gone through a lot of things. It's been a little random. You can do this, you can do this, you can do this, you can do this. What does it all mean? So if I could give you one big idea to take away with you as you go into lunch and contemplate, it's this flexibility. There is no one right way to use Ecto. It's got a lot of different pieces to it. It's a lot of different tools and you can use them in any combination that you want. You wanna do some validations without having to have a database behind you? Go ahead, you can use it.  Fine, you can. It's kind of up to you and so you can think about what your use case is and then look around in the Ecto tool set to find the things that can help you. So to keep leveling up, I recommend you check out the GitHub repo. The source code is surprisingly readable and the documentation is very, very good. In particular, the top level modules have a very nice preamble to them, like the big four that I talked about that walk you through a lot of the nuances. So it's definitely worth checking out. So that's about all I have. My name is Darren Wilson. I work for a company called Infinite Red. We do web and mobile development using Elixir and React Native. So if you need help with either of those things, feel free to talk to me. I'm at Darren Wilson on Twitter and in most places on the internet. I also tend to lurk in the Ecto channel of Slack, of the Elixir Slack, I mean, and I troll the Elixir Forum too. So if you ever wanna talk about this stuff, if you have any questions, feel free to contact me anytime. Thank you for coming. I appreciate it.


See, we got in the box, man. I feel like it's going to be fire, so let's check it out, man. Ooh, yes, sir. Both of them got a little splash of white, you know? Perfect for the uniforms. I'm Kevin Byer here, and these are my cleats for the Byer Family Legacy Fund. Me and my wife, since we've been here in Nashville in Tennessee period, we do a lot of great things in the community, doing all type of different stuff as far as Thanksgiving meals. Christmas, holidays, all type of stuff. But we want to be able to put that into a whole entire thing so we can have our own foundation, do our own events. We're actually going to be starting, actually, a scholarship called the Grace Grant. We feel like God's grace has been in our life so much and took it so far that we want to be kind of be able to do the same thing, a $10,000 grant that we're going to help out, deserving a kid going to college. As long as I'm here in Nashville, I'm going to be doing things to touch the community and touch everybody as much as I can. So it's a great thing to me and my wife are doing it.


Imagine a community of service providers who are good at what they do, are generous of heart and are collaborative, wishing the best for one another, wishing for one another to express their unique genius, their greatest strengths in order to serve and uplift the world, that help one another. We've begun building that community. It's called Our Highest Work. It's free. It's online, so you can join from anywhere. And you can find it at ourhighestwork.com slash community. Now, today, I want to encourage those of us who are part of that community, or those who wish to join, to be more intentional about referring business to each other. That's one. And even before that, even before referring business to each other, is to be clear how, where our strengths are, what kind of people we serve the best, so that we make it easy for others to refer business to us. Two videos ago, I think the video is called Focus to Service Equals Fewer Competition. In that video, I shared, I think, seven questions to answer in order to focus your service more, so that you can be giving your greatest gifts, using your greatest strengths, so that you can be making the biggest impact you possibly can on your clients. So I invite you now to experiment and share, either underneath that video or underneath this video, what that is for you. Whom do you best serve at this time? Now that may change, of course, as you evolve, as your business evolves, as the world evolves, that may change. But right now, what appears to be the population, the group of people that you best serve, and for which issues? It can be one of two things. It can be one is the population you feel you're most excellent at serving, the issues you're best at serving, or the other possibility is the thing you do that you don't mind doing that is most popular, that's the easiest sort of gateway for people into your work. One of the things I didn't say in that video is that even though you focus your service on a particular issue or a particular type of person, it doesn't mean that you can't serve those people in other issues or other types of people. It's simply a doorway, a gateway into your service that you become known for because people don't remember a lot about you. It's true for all of us. People just remember a few things about us when they think of us. So what do you want those few things to be? The more focused it is, the easier it is for them to remember you in the right circumstances when they're talking to the right people. So I invite you to start a dialogue in our community to start referring business to each other. So I just imagine this community where everybody is really good at what they do specifically and so that we can refer business to each other because we know that if we refer this type of person it'll really best be taken care of by someone like you and if you meet someone who is best taken care of by someone else in the community, you refer that to them. And everybody wins. The client is most taken care of. If you're referring someone to someone else you know that you're doing good in the world and that you're creating a better relationship with that person you're referring them to. That person gets a new client. And vice versa, someone referring clients to you as well. So I invite you to start a dialogue and let's see if we can realize this dream of this community together. I'm looking forward to seeing your comments. Be well.


Hell yeah what's up guys this is Chris Pike my friends call me Bigsy back in action today we're talking broken pieces that's right guys we got a new game in the freedom pipeline and yeah it looks pretty damn good I'm not gonna lie if you've ever wondered what Dreamscaper combined with you know some Silent Hill and a little life is strange Mike if you put it in a bowl and you mixed it around you got a game this kind of looks like that that's the vibe it's giving me at least guys it looks pretty darn good in a nutshell you play as Elise you move to a small village in France and well what can I say you know one night some armed troopers show up at your joint they try and capture you escape and now you're in this village all alone and you gotta deal with a little bit of paranoia you gotta live with the paranormal if I throw that in there there's puzzles there's mysteries a little bit of gun shooting going on there's a whole bag of things going in there throwing some found footage type style and Walkman with some mixtapes hey how good is that yeah guys it's all in there on this game it looks pretty damn good it's set to come out in the third quarter of this year so that could be anytime before the end of September well hopefully we'll get a solid release date in the next few days or maybe the next few weeks but it should be pretty soon so maybe put this on your radar if you like this type of game add it to your wishlist and yeah hit me up on discord if you want to talk about maybe making some content for it if let's plays or or strategy guides and stuff like that I always want to talk about this kind of thing guys that's that's what we do here I'll publish your content here you know let's just get it going anyways my information is in description below enjoy the demo let me know what you think in the comments below add me on discord and I'll be back soon if you find this tape I beg you listen to it carefully my name is Elise I recently settled in the village of St. Exel a quiet and isolated place near the sea but during the animal fair something happened armed troops attacked the village and tried to kidnap us all I barely escaped only to wake up completely alone stuck inside this place that doesn't feel like home anymore I I am starting to lose all sense of reality while I was investigating the village I discovered a deeply rooted sickness when I started to sink into its abyss I was finally able to see more clearly because even if this place is constantly challenging me it also keeps pushing me to question everything if by chance anybody is listening please come help me I'm not going to last much longer it's now or never


Now for the third exercise get into the same position and Then we're gonna do tootsal, which means stripping hand so go like this and Then two things are happening at the same time one hand is slicing and stripping like you're stripping off a Sanding a piece of wood and the other one is pulling this way. So you have two rotating Opposite rotations


Russian forces advanced attacks on Ukrainian troops, foreign mercenaries and weaponry on the front lines and places including Kupinsk and Donetsk during the past 24 hours, the Russian Defense Ministry said on Saturday local time. Russian air defense units down 32 Ukrainian drones in multiple areas during the period, the Defense Ministry said. Also on Saturday, the general staff of the Ukrainian armed forces said Russian troops continued offensive in the direction of Bakhmut, where the battle was still going on. In the past 24 hours, the Ukrainian Air Force, as well as the missile and artillery units implemented attacks on targets including areas with dense deployments of Russian weapons and command points, said the Ukrainian general staff.


okay here's a bit of soil chemistry so I'm holding this piece of mud that I just took off from the surface of the soil and it's interesting because you see a brownish layer on top here a thin one it's about maybe extends about two three millimeters deep into the soil on top of that is actually a bit more greenish yeah and then underneath of that we have this dark gray blackish soil and that's basically what's happened happening in a flooded soil it's what we call a chemical reaction which is actually driven by microbial processes reducing the iron compounds from iron II iron III oxides and hydroxides which have a reddish color into iron II compounds which have a grayish color so what we have up here is basically a layer where the oxygen jet still comes in from the water that we put on and though that always stays oxidized and underneath of that we have this highly anaerobic reduced soil in which the roots are but this is also up here very biologically active layer which is why it's greenish on top so you've got algae living on top doing nitrogen fixation and all kind of things


The National Broadcasting Company and its affiliated stations present the Pacific Story. This is the story of the Pacific and the millions of people who live around this greatest sea. The drama of the people's whose destiny is at stake in the Pacific War. This is the background of the war in the Pacific and its meaning to us and to the generations to come. Tonight's Pacific Story, Mongolia, Strife in Asia's Interior comes to you from Baltimore, Maryland and Hollywood as another public service with drama of the past and present and commentary by Owen Latimore, authority on Mongolia and director of the School of International Relations, Johns Hopkins University. Strife in Asia's Interior. A Chinese commander and I were sitting in his quarters playing cards when it happened. Aaron Ungern Sternberg with a horse whip in his hands burst in. His eyes were blazing. Behind him were two Russian soldiers with rifles. There he is. The commander lay dead in a pool of blood. I'm an American. Your name? Barlow. Samuel Barlow. Why are you here in Urga? I'm a traveler. What's the meaning of this? You will learn. You are to stay here. You're there. You will stand guard outside the door and wash off. You'll come with me. There a long time looking at the body of the Chinese commander on the floor. The Russian Revolution had come to Mongolia. The man with the horse whip was a czarist. Until the outbreak of World War I, the czar had had a strong garrison here. But most of the Cossacks had been taken to fight the Germans. And thousands of political prisoners and peasants freed by the Revolution had come down into Mongolia. I heard someone raising a window. Good Russian was coming in through the window. It's not the czarist. I thought the Chinese would resist. Who is he? He's Baron Ungern Sternberg. This is the only safe place in Urga. One of the Baron's soldiers burst in carrying a lantern and a pistol. I saw him crawling in through the back window. You will never take me. That Russian lay crumbled in death beside the Chinese commander. The czarist soldier holstered his pistol and walked out. I lighted the lamp. I sat down and looked at the two bodies in the blood on the floor. The silence was broken every now and then by the firing squads. At dawn the door opened and three men were thrust in with me. Get him there. One of them was a Lama priest. His wife and child were killed by the Bolchiviks. And all his property was destroyed by his peasants. But why has he come here to Urga? A way out here in Mongolia. He hopes to raise an army here to fight the Bolchiviks. He has already broken the power of the Chinese. He must have attacked with a strong force. No. Only 35 men. Have their parking! Island! Baron Ungern Sternberg walked in. The two riflemen behind him. You people are my prisoners. No harm will come to you as long as you obey. I am raising an army of Mongols and loyal Tsarists. I am marching in Moscow. I am taking you along. Island! I will march straight to the Kremlin. I will ring the necks of those infected with the leprosy of communism. A who have seized power. The horse whip quivered in his hand as he spoke. His eyes blazed. You will prepare to move with us at once. He will have to move fast. For all Mongolia will be ablaze with the news of his massacre. Word of the slaughter spread among the Mongols and the Buryats. And word spread to the Bolshevik forces. As we started to march off the steps of Mongolia, they rallied in the desert and the hills. The Kremlin was 3,000 miles away. Baron Ungern Sternberg! What is it? The Bolshevik regiment is closing in on us. We will attack. Almost before we knew it, the Red Forces were upon us. Sternberg was taken. We looked down as he was led through the mud of a Russian prison yard and stood against a wall. Fire! Mongolia had fallen under the influence of the Soviets. In 1915, Tsarist Russia and China and Outer Mongolia had signed a treaty in which China recognized the autonomy of Outer Mongolia with some strings attached, but under the protectorate of Tsarist Russia. But after the Tsarist Cossacks moved out to fight the Germans, the Chinese swept in and occupied Mongolia. But now the Chinese hold was at an end. From this time on, Red Russia was to be a big factor in the affairs of Mongolia. I proclaimed the Mongolian people's government. From the hills and the deserts of Mongolia, one-third the size of the United States, tribesmen came to Urga the capital to hear this proclamation. Mongolia is still bound by the treaty of 1915 to China and Tsarist Russia. There is no Tsarist Russia. This was 1921. Soviet ministers came to Urga to enter into direct negotiations with the leaders of the Mongolian people's government. As of this day, Soviet Russia repudiates the treaties of Tsarist Russia and recognizes the Mongolian people's government. For years before this, the Lamas had had great power in Mongolia. They had virtually ruled the land. This power is now at an end. The local lords will have no governing rights. The crushing taxes against the lower classes are abolished. But those who had held power joined forces against the people's government. I speak for the landowners, the businessmen and the priests. Are we to fall into the chaos that now engulfs Russia? No, let us re-establish the time-honored rule that has endured down through the years. Down with the people! The movement failed. Mongolia swung to the left. But at this time, China and Russia were drawing closer together. Soviet Russia recognizes outer Mongolia as an integral part of the Republic of China. All Soviet troops will be withdrawn from outer Mongolia. The Red Forces started to move out at once. Within a month, Mongolia declared itself a republic. Mongolia is an independent nation. The supreme power will be in the people's assembly. The landlords, the exploiters, the priests and the moneylenders will have no political rights. Only the people who work will have political rights. And every man may worship as he pleases. For the first time in centuries, the Mongol people were drawing together. I listened to an old Mongol. Once we were conquerors. The old Mongol looked at the many different Asiatic peoples passing in the streets of Orga. Once, the Mongol Empire was the greatest in the world. And Genghis Khan's name was on the lips of every man. He was born with a clot of blood in the palm of his hand. And the wise one said he was sent to be a leader. He welded the scattered tribes into an invincible horde that swept across Asia and conquered Turkestan and Bahara and Armenia and South Russia. So great was the power of Genghis Khan that when he died the fierceness of his fighters went on under his son, Ogdai Khan.  Here was the heart of this great empire. Once we were a great nation and now we are drawing together once more. The Russian troops had withdrawn but the Soviets had recognized Mongolia as an integral part of China. We are not part of China. We are an independent nation. The Mongolians determined to make their position clear to the world. We have our own history, our own traditions, our own language and our own territory. We are an independent nation. Mongolia was swinging farther to the left but by 1932 this policy had come to an end. The collectives were dissolved and private enterprise came back. But now something else had happened that Japanese had invaded Manchuria next door to Mongolia. We watched the Japanese developments. They occupied all of Manchuria, changed its name to Manchoko and set up a bogus government. Then from Manchuria they moved westward and overran the 100,000 square miles of Rihou. From Rihou they extended their influence into Inner Mongolia but the Russians and the Mongolians knew what the Japanese were up to. They are trying to create a buffer state between outer Mongolia and North China. They are trying to outflank us. The biggest border clash of the thousands that would come broke out near Lake Bornoir on the frontier between Manchuria and outer Mongolia. An aftermath of the border incident in the vicinity of Lake Bornoir between Manchuria and outer Mongolia. A conference to settle the dispute has been called to be held in Manchuria, northwestern Manchuria. Delegates from outer Mongolia are now en route to Manchuria to meet with Japanese military observers in an effort to... For months efforts have been made to penetrate outer Mongolia from Manchuria. This incident was the result of the Manchurian troops crossing the border into outer Mongolia. Japan has no interest in outer Mongolia. The incident was the result of the chaotic conditions that exist along the frontier. To keep order, we demand the right to place military personnel in outer Mongolia and the right to run telegraph lines into Mongolia to facilitate Japanese communications. The Mongol delegates failed to come to terms with the Japanese and the Japanese continued their penetration of inner Mongolia. And outer Mongolia drew closer to Soviet Russia. I accompanied the 67 Mongols who visited the Kremlin in January 1936. We welcome you as the workers who are building the new outer Mongolia. Many of the Mongols made speeches. We are grateful to the party, to the government, This was the chairman of a Mongol collective farm. Today in this happy, joyous atmosphere we can recall our difficult and wretched past. Now we have prosperity and a rise in our cultural life. We have a school, welded homes, a bathhouse and a radio. Many of us collective farmers even ride bicycles. But in inner Mongolia the Japanese were telling the people other things. The Russians have ruined outer Mongolia. Here in inner Mongolia it is Japan's purpose to help you set up our sound government which you yourselves will run with our help. Inner Mongolia was taken from China and put under a Japanese puppet government. Its leaders spoke of the day when they would reach out and by force if necessary take in outer Mongolia even though it was three times its size. But the establishment of inner Mongolia as a new nation was much more important to Japan than to inner Mongolia. For now Japan was at war with China. In Japan a minister made a report to his government. The new inner Mongolia nation has now been established and henceforth we will be known as Mengqiang. The head of the government is Prince Tai Wang who understands the value of relations with Japan. In this new nation we now have a buffer state between communist controlled outer Mongolia and the Japanese occupied areas of China. By the creation of this buffer state we are now in a position to prevent communism from spreading into Manchukuo and North China as it has into outer Mongolia and Turkestan which are completely Bolshevik. Inner Mongolia had become the Japanese puppet state of Mengqiang but outer Mongolia had joined hands with Soviet Russia and after Nazi Germany had attacked Russia in the summer of 1941 the Mongolian people's republic rallied behind the Soviets. We are faithful to our alliance with the Soviet Union. This was Marshal Choi Baosan speaking before 80,000 people at Ulan-Bator which means Red Hero and is the new name for Urga, the capital of outer Mongolia. We pledge all possible help to the Soviet Union in the great struggle against the wild fascist force. The Japanese across the border in Inner Mongolia looked on. They looked at the Mongolian force charged with keeping the peace in Inner Mongolia. General Pai Feng Xiang and his 18,000 cavalrymen. Are you satisfied we can depend on him? He is a difficult man to penetrate. He is silly. We must be certain we can trust him. A friendy or reader would be safer. We will have the banquet. See that the general is invited. We will take care of all details. The night of the banquet, the general died. Oh, it is unfortunate. He was such an able general. For days there was an ominous gloom. The word leaked out that the general had been poisoned and on the black of night Japanese heard an unaccountable sound. 18,000 of General Pai's cavalrymen are gone. Days later news came back of where they had gone. They have joined the Chinese forces in Sui An province and they are armed with all the guns and ammunition we gave them. Across the border to the north, there was no question where the people of outer Mongolia stood. It is our sacred duty to increase the aid to the nations of the Soviet Union in order to speed victory over our common enemy, German fasciners. Although closely allied with Russia, the Mongolian People's Republic kept its independence, its system of private property, and its strong Mongol nationalism. How do they impress you, Mr. Barlau? They look almost like Soviet troops in those uniforms. Are they good soldiers? Most of them have been marksmen since boyhood and they are completely fearless. The organization of the Mongolian army seems to be almost the same as that of the Russian army. It is. And like us, they have developed into skilled artillerymen and tank drivers and air flame pilots. I realized as I stood there with the Russian officer that Mongolia was preparing for coming events. The troops were equipped with tanks, artillery, armored units, even flamethrowers. They were friendly to the Chinese and friendly to the Russians. When the Japanese pushed into Manchuria, they had been anti-Japanese. Mongolia gave all possible aid to the Russians in their war against Germany. But Russia took pains to see that Mongolia never weakened itself. Today, Mongolia is stronger than perhaps at any time in its history. For today, she has not only a strong, well-equipped army, but she has good communications. Highways have been built to link supply bases to take the movement of troops and their modern war equipment. Today, Mongolia is ready to play her role in the war against Japan. Japan knows the strategic value of Mongolia. She would have to strike across Mongolia to invade the Lake Baikal region. If the Japanese struck through Mongolia, they could cut the trans-Siberian railroad and then drive deep into Soviet Asia. But we also know our strategic value. On the Mongolian-Mangyokan border, the Russians fought their most important frontier engagements with the Japanese. They know the terrain and they know the enemy. Observers are coming in from faraway lands. They see Mongolia not only as a buffer state, valuable in the defense of Soviet Asia, but as a possible base for attack. From this point, the Soviets could drive eastward into Manchuria. He pointed at the northeast corner of outer Mongolia. Another force, starting from here... He pointed to the air of Khabarovsk, 200 miles from the sea. Could drive westward to form a giant pinches to cut off the northern part of Manchuria. In this operation, Mongolia would be a springboard for attack straight eastward. Or, from this point here... He pointed to the southeast corner of Mongolia. The Soviets could drive southeast, cutting between Manchuria and north China to the sea. This would outflank all of Manchuria, where the Japanese are so strongly entrenched. And also outflank the Japanese in occupied China. In effect, it would cut off the Japanese in Manchuria from the Japanese in China. Mongolia, so long forgotten, so long off the beaten paths of the world, has become one of the strategic centers of Asia. Those are Russian tanks, aren't they? They were made in Russia. Russia's playing a big part here in Mongolia. What about when the war is over? Mongolia is an independent nation. But Mongolia is still under the suzerainty of China, isn't it? We are an independent people. And an independent nation. The tanks rumbled by. And the Mongols and their land may again be known around the world as they were in the days when Cengiz Khan swept two continents with his invincible force. Never since the days of the great Mongol conquerors has Mongolia been so important as today. To tell the significance of the Mongols in the light of present-day events, the national broadcasting company presents Owen Latimore, authority on Mongolia and director of the School of International Relations, Johns Hopkins University. The next voice you hear will be that of Mr. Latimore. We take you now to Baltimore. While great nations are sparring with each other at San Francisco, there is a natural tendency to overlook some of the smaller nations. Yet it is a mistake to overlook a group of nations in Asia and the Pacific, which, taken as a group, have a key importance. Although taken individually, they do not measure up to much compared with the giants of the Earth, like America, the Soviet Union, or the British Empire. This group I am talking about includes outer Mongolia, Korea, the Philippines, and Thailand, which we used to call Siam. They are important for four reasons. First, they represent freedom. Second, because they represent freedom, they represent change, and that means we can no longer talk about the unchanging East. Third, they are all grouped around China. If China should become a stable, prosperous, united country, they would all form part of the same field of industrialization and trade. But if China should break up in civil war, they would all become bases and beach heads for countries competing for spheres of influence and control in China. Fourth, and most important of all, outer Mongolia, Korea, the Philippines, and Thailand can all within limits make their own choice politically, whether they want to move over closer to Russia, or China, or America, or even, as far as Thailand is concerned, the British Empire. It is not 100% a question of which of their big neighbors may want to reach out and grab them or control them. Therefore, each big country will do well to think whether it has a policy which makes the smaller countries want to move over closer, or a policy that makes them feel like backing off and getting closer to somebody else. Outer Mongolia illustrates all these problems. Outer Mongolia is also a test case of Russia's ability and willingness to take part in the lives of other peoples and countries without riding rough shard over them. It is a great pity that so few people here in America know anything about outer Mongolia. It is a pity because the history of Mongolia over the last quarter of a century offers encouraging evidence for the hope that we can get along with Russia in the post-war world. Russia treats Outer Mongolia as an independent country. There is a Soviet minister at Ulan-Bator, or Urga, and a Mongol minister at Moscow. And yet, in repeated diplomatic notes exchanged with China, the Russians have always recognized China's claim to sovereignty over outer Mongolia. What does all this add up to? In the simplest possible words, this is the story. Up to 1911, Outer Mongolia and China were part of the same empire. But the Mongols and Chinese are entirely different peoples. Upon the frontier, when you leave the last Chinese farm and ride to the first Mongol camp, maybe 50 miles away, you make in that short 50 miles a jump from the language family of China, Indochina and Burma to the language family of Tashkent and Samarkand and Istanbul. In 1911, the Chinese and the Mongols both rebelled against the Manchu emperor. Ever since then, the Chinese claim has been, we are the people who actually deposed the emperor and founded a republic. Therefore, everything that used to belong to the emperor now belongs to us. Outer Mongolia is Chinese territory. The Mongol claim, on the other hand, is this. We Mongols were never Chinese, and you Chinese were never Mongols. The emperor, who ruled us both, is overthrown. Now, the time has come for each of us to go his own way. Neither of us has any reason to fight the other, but as for admitting that one of us belongs to the other, nothing doing. Here the Russians come in. Today, the people who live right on our frontier are Mongols. They claim they are independent, and there are no Chinese on the spot for us to deal with. It is not our business to force the Mongols to submit to Chinese rule, but neither is it our business to force the Chinese to recognize Mongol independence. If the Chinese claim sovereignty, that is perfectly all right as a claim. But in the meantime, we have to deal with the people on the spot who happen to be Mongols. It is encouraging for the rest of us that the Russians have not simply annexed outer Mongolia. They have helped and strengthened the Mongols a great deal, and this has enabled both Russians and Mongols to put up an unyielding front against the Japanese, but they have not forced the Russian system on Mongolia. In Mongolia, you can be a rich man with thousands of sheep and hundreds of cattle, horses and camels. You can buy and sell and keep the profit. Eventually, there will have to be some kind of settlement between the Mongols and the Chinese, perhaps they will negotiate with each other and form a federation of republics. The important point for us is that the decision, whatever it turns out to be, is likely to take the form of free negotiation between free and self-respecting people. And after the kind of war we have been fighting, in Asia as in Europe, the more negotiations we can have between free and self-respecting peoples, the brighter the hope for the future of the world. You have been listening to the Pacific story presented by the National Broadcasting Company and its affiliated independent stations as a public service to clarify events in the Pacific and to make understandable across currents of light in the Pacific Basin. For a reprint of this Pacific story program, send 10 cents in stamps or coin to University of California Press, Berkeley, California. The story is written and directed by Arnold Marquess. The original musical score was composed and conducted by Thomas Paluso. The principal voice was that of Jack Moyles. This program came to you from Hollywood and Baltimore, Maryland. This is the National Broadcasting Company.