 This is unblocked, this is a talk about Ruby's blocks or something like that, or that's what it was supposed to be, I don't know. For those who don't know me, I'm James Evergrey, the second. I've been in the Ruby community quite a while now, not as long as some, but one of the most. I've written several things you may have seen, including the faster CSV library that became the standard CSV library in Ruby 1.9. I built Rails applications for a living, one you may have seen recently was Go vs. Go, which I built with Ryan Bates during the Rails rumble, and that was fun. I've also sometimes been caught impersonating Jim Wyrick, I have no idea why. I'm going to be nice and leave him alone today. The other thing you really need to know about me though is this. If you've seen any of my talks before, you know, I love these pop culture references, heroes, Ballastar, Galactica. I used to video game ones, Living Planet. I've even used my vacation photos from Japan, how cool was that? By the way, this tree, I believe Rich Kilmer once showed a tree in a talk at Lone Star RubyConf. This is from my own photos and I believe it is the exact same tree Rich Kilmer showed in Japan. So we both traveled all the way to Japan and got obsessed over the same tree, right? How was that? Okay, but I'm not cool anymore because I'm a dad now. That's right. This is my daughter, James, I work for the third. Yes. I'm just kidding. Her name is Sar. As my wife's doctor is fond of telling me, dads are not cool, they're weird. Okay, so I'm not cool anymore. She always says that because her dad once dropped his watch in that the taper pond at the zoo and went in after it. Yes. Okay, so the reason dads aren't cool is we can really only think about two things. Okay, the first one is where is our next state of caffeine coming from? And I just drank an entire Dr. Pepper before I had this speech, so that's why I'm wired. The other thing we can think about is playing, okay? That's what we're programmed to do. By the way, if you guys don't notice, this is why you have kids. You know it's socially acceptable for me to play with Legos again. That's awesome. Go out and get a kid right now. Don't wait on that birthday. It's too long. Just steal one or something. It's way too long. Okay, so Summer has all these great toys, right? And I want to show you one. These are some blocks, some alphabet blocks, ABCs, teacher ABCs. But they're from the point of view of everything a young mad scientist would need to know. So, like, F is for freeze-breaking, right? You might need to know that. Or U is for underground layer. Everybody needs to know about that, right? It goes all the way down to Z is for zombies. And why do you need to know about zombies? If you're a young mad scientist, well, because of this. Obviously. Okay. Oh, yeah. I'm supposed to be talking about Ruby's blocks. In case you haven't noticed, I'm not doing that. Actually, there's been some doubt about my ability to talk about Ruby's blocks. You can almost hear Jeremy's question here when I tell him they took my blog time and he goes, like, you're going to talk about blocks for 30 minutes? No, the talks are 45. But he's right. I'm not going to talk about boring old blocks. It's not the usual boring stuff you're used to. These are experiments with blocks, right? And the words of Dave Thomas are meant to inspire. And I'm so glad he said it was okay to do it worse, because we're definitely going to. These blocks might be, or examples, might be described as maniacal. That's definitely true. And I've already given you the reason for that is because I'm on caffeine, right? Okay. So this is the evil blocks talk. Okay? So let's start off with a quiz. Why is for you the mad scientist of tomorrow? So let's see how you do mad scientist. I'm going to pose a problem. Let's say we have this Ruby construct. We have a table, right? And we're storing it by rows and columns. So we have rows and then columns ADC. We wanted to find a simple indexing method, pair brackets, and then we want to try to get the three inside, right? And there's a lot of ways we can do this. I'll show you a couple. The most easy way is we could delegate to the underlying array, right? So we just write here when the first value gets passed in, we pass that on to the underlying array, then we return the array to the row, and do that. The weird thing about that is then we have to pass it in kind of backwards for us humans, right? Y then X, right? But usually we think in terms of X then Y. So that's a little bit backwards. To fix that, there's several ways we can fix that. This is probably the best idea. If we just take both of those values at once, the X and the Y, we can swap them right here and pass them both in there, and then that lets us call it with X, Y, which is very natural and it's a good idea, right? This talk is not about good ideas, right? Not at all. So we're throwing this slide away. Okay, so I actually want to do a bad idea. I want to do it the way I did it in the first slide, with brackets, brackets, but I want to pass X, Y. So I want to come up with a line of code that goes right here and allows us to do X, Y, like this. Pop quiz. Any suggestions? Shout it out. Return of lambda. Return of lambda. That is so cool. Alright. I'll show you a more pedestrian way first. How about transpose? Anybody know this method? Array, you can have an array of arrays flipped around in Ruby, right? So that it'll change it to go by columns instead of by rows. And usually it's easier to store it by row because when we're printing it out or things like that, it makes it easier. But if we want to access it the other way, we can transpose it first. This could get expensive though, right? If we have a lot of data in there and we're constantly having to flip it around just to get at the data or maybe having to save two copies of it, even worse. So this could get really expensive. So that's transpose. The other answer that was offered is let's return a lambda which is an awesome answer and it's right, it works. The reasons that it works is kind of interesting though. So let's look into these a little bit. First you have to know what a lambda is. So we kind of got it into some black drama just a little bit. And a lambda, this is a simplification, but I'm sure you've seen a method like this before in Ruby, where you put the ampersand in there and it will bundle the block up into an object for you. And then we can do something with that block inside the method, right? So lambda could almost be defined like this. It's not really, this is a simplification, but it basically just bundles it up into an object and immediately returns that object. So it allows you to invoke a block anywhere when you wouldn't otherwise have a block. It's like a stand-in method to generate blocks. This is the way to think of it. Well, why would you want to create a block where you can't create a block? To get the answer, we'll go to Java, obviously. So this is from Java code and it just sums up five numbers. Simple stuff, right? But in Java, this is common sense here. You would want to be able to access this variable in this loop, right? If you couldn't, Java would make you even more mad than it already makes you, right? Okay, so here's the equivalent program in Ruby. And like usual as Ruby, we drop all the loops here in place of iterators, right? So they're blocks. And in order to get that same thing, in order to be able to access that outside variable, blocks have to be closures, which is the scary computer science word we throw around, but it really just means that they can access the surrounding environment so that they don't make you mad in simple situations like this, right? Okay, so that's the quality of blocks that we care about. The last point that you really need to understand how that example I showed works is duck typing. And here's the pretty canonical example that we tend to see, which is with this append method right here, right? And the idea is that everything supports this append method. We can append to arrays, we can append to strings, we can append to file objects, et cetera, right? But my favorite duck typing method is not append. It's the indexing method, the brackets. Everything supports this sucker too. Look at these examples, string, array, hash, and lambda supports the indexing method as well. It's an alias for call, right? So anywhere you could use a hash to look something up, you could use a lambda instead to calculate something instead, right? So let's go back and look at that example I made one more time. You can see all the tricks here. So we're using a lambda so that we can grab a block here when we couldn't otherwise do it, wrap up the context, and the reason we want to do that is so we can gain access to this private instance variable and the x that was passed in. And then down here, when the y gets passed in through that duck typing method, we'll have all the pieces we need and we can sort it all out, right? So I love this example because it reminds me of all the reason blocks are cool in Ruby, okay? As example number one, how are we doing so far? You guys feeling like superheroes or are you feeling more like this? All right, let's see if we can bite off more than we can chew. All right, so the awesome thing about Ruby is that there's blocks everywhere, right? You already know about iterators. We've got talks about that here. Everybody knows about the iterators. But a lot of weird Ruby methods take blocks, like exit takes a lot, right? And this allows you to do something when the Ruby interpreter is shutting down, okay? So in this case, I'm just checking to see if we have an error and printing out a message when we do it. It's time to shut down. That's cool stuff, right? And another thing that can take blocks, and this is one of my personal favorites, is class new. You can actually define a class programmatically in Ruby. And the block is the class block, okay? So this allows you to make up things on the fly. So in this case, I've added a method to all classes to bring in an audit long version of Ruby. It does that by calling class new. If you pass anything to class new, that's your superclass. So in here, we inherit from whatever class it's called on. Then we run through all the public methods and we read a final to do the exact same thing they did before, but first, print out a message about what happened. So now I can create an array with an audit log and then I'll call some methods on it and you can see it's printing out what I'm doing to these methods. That's pretty cool, right? So what can we do with this dynamically describing methods? So I thought I would go, this came up at OKRP recently. And people were talking about how this data, by the way it exists, actually confers some structure about the data. Just by looking at it, we can see that it's a collection of names and these names have these various attributes. We can already see that from the data itself. All right, so artists for a robot, which kind of disappointed me a little bit, really felt like that should be for Ruby. So we'll just turn it into a Ruby robot, right? We want to parse that XML with no pre-existing knowledge and determine the structure from it. Let's see how we would do that. So here's a simple parse. Regular expressions are my weapon of choice for those who know me or won't be surprised by that at all. So I didn't use anything cool like Nukagiri, but I'll get back to Nukagiri in a minute. This is a simple parse right here that just runs through. It's not really important to understand how it works, but I do want to show you a couple of things. It works tag to tag, and I do that in Ruby by changing the line ending character when you call each or gets or something like that. You can tell it when you want to use this line ending character. So here if we use greater than as the line ending character, I think Jeremy actually calls it Waka. Then we can move tag to tag. And then I parse those tags with two regular expressions. I am using a cool Ruby 1.9 feature here, though. If you don't know about it, I'm using named captures. I'm naming them and having Ruby set local variables of the exact same name so that I can access everything by name instead of $1, $2, etc. Okay, so that parser relies on some escaping. This is a little more code to kind of round it out. Here's the escaping function. And the IO we're going to leave from. Also, I've got this storage prepared for where we're going to stick the classes when we make them, but we haven't got that for yet, so just don't worry about that for now. And here's the parser. You can use it just by opening a file, wrap it around it, call the parse method. I'm using some Ruby 1.9 tricks here again for variables in the block and have defaults now, awesome. And below you can see that prettier hash syntax. And we get these events, right, these parsing events. So here's the start of a tag. Another tag that has these attributes. Another tag here's content, etc. Okay, so it's an event-based parser. Okay, now we've really got into getting into the icky stuff, okay, into the designing of the classes around the data and the parsing and end objects. So here's a code for that. If you're going to parse a tree structure like XML, the easiest way in the world to do it is with a stack, okay? And we just start with a root context. Every time we go into a new tag, we push that onto the stack, and every time we leave a tag, we pop that back off of the stack. That means whatever's on the bottom of the stack right now, that's the context we're currently in, okay? And we can use that to figure out where we're going. Given that, as I read new tags and stuff, I just keep track of the attributes on them in hash by their class. This is the parsing part where it's doing the pushing and popping that I talked about with the stack. And then we do one dirty trick here, and we don't really want to have a names object that contains a bunch of names. Really, we just want to simplify that to a Ruby array. So I'm going to go ahead and collapse a couple of levels. And this isn't perfect. It doesn't work in all cases. But we'll see how far we can make it go. And then I just run through those and turn them into classes, which the code for turning them into classes is almost the same thing. Here's class here. The whole point I showed you this example. And I'm dynamically defining the classes here, right? I'm running through the attributes I found and putting those attributes in so that we can build up this class definition. I also added one thing because it was a symbol, one line. I landed past an enhancement. If you want, that enhancement gets included in the class bucket. So you can actually add helper methods or whatever you want to make it nicer, right? I'll show you where that might be useful. One more time with the parsing. You can actually do the whole thing in one pass, but it makes the code much uglier. So here I did it, too. We got to parse through again to get the objects, right? Now we have the class structure. Let's create the objects. I'm using this same trick here. Make a stag, start with a root object, push and pop to create classes or objects as I go through, and populate the attributes of those objects, et cetera. We'll return the results. And then I need to make a pretty interface here. It was easier for me to think about test and design in those three pieces I showed you, parsing, classes, and objects, but nobody would say if you use it like that, because it's the final method that unifies the three of them. And we can try it out. So now I pointed that at the names XML that you saw before, and you can see, but get a really ruby interface here, right? XML.names.map. You can just run through those. We can do things like name, middle, or map all of those names to their first name, or just call them methods and ruby, right? And you can see where to print out at the bottom. All right, so I thought to myself, James, you've got to be honest here. So here's the same code in Okagiri, which, you know, I'm totally disappointed to say it's shorter and easier. And the reason it won is because of the X path, right? Okagiri has X path, which is a language, a mini language designed around searching XML. So it's actually easier to get at the parts you want than just prints the exact same thing. So then I got to thinking about this, and that means I got whooped by a practical tool when I was trying to make this horrible example and that really made me mad, right? So I did what any good programmer would do, and I assumed the fault lies in the data, and not in my code, ok? So if we can just find the right data to feed it, something Okagiri would choke on. Dang! Dang, we got an example, right? Ok, so we're going to look for more palatable foods, right? That's my daughter's Halloween costume, isn't that awesome? Ok, so I went hunting for the most evil XML I could find, and it turns out it's in iTunes. Sorry, there it is. So these are related, right? The only reason you know that is because iTunes was kind enough to put them on the same line for me. Just show me they're related, but you can't tell they're related in XML because they're not nested or related to each other, right? And the tags that come after the keys can be arbitrary. So like integer, string, date, whatever, right? You don't know. So you cannot expat this, ok? You cannot, yeah, there's Okagiri's advantage. You can't expat this. You could do it with Okagiri's node structure, but even that, I think, is pretty complicated since it's actually the order of the tags that's a key to put these together. So I wanted to see if I could modify my system to work with that. So here I'm using the enhancements, and the thing is those dictionary objects, so I need to just modify them, so I'll redefine some things on the class, and the trick is to unify all the different kinds of values into one list, which is what I'm doing here, and then changing many Ruby objects at the same time. And then I get my way to convert the entire thing to a hash, and I want to do that recursively so that it makes this whole hash structure. And once we do that, notice I can index into this, just like I get that specific song we were just looking at, and we get this nice little Ruby data structure. And you might be thinking there's a library that does something like this called the XML simple, I think, that will convert an XML structure to a system like this, hash, in a way. But it, too, would have the same problems with those tags not being related to each other, so it wouldn't be able to figure it out. Okay, so that's good. We would know from your area. I feel better about that example. All right, for this last example, we're going to try another weird invention of mine. If you thought the last one was weird, this would be even better, like a lizard connected to tank tracks with horns. Yeah, I don't know what that picture is. It's an invention. And we'll do some bioengineering. No, this is block engineering. I think it should stand for that. And we've got to get out my favorite block for this one. This is absolutely my favorite one in the set, because this is probably what you guys are going to want to see to me afterwards, but P is for peasants with pitchforks. I give my daughter the coolest toys. These are awesome. I'm expecting to spend quite a bit of time in her principal's office. Okay, so as we get into an example, we need to talk about a rubyism. This thing right here, this thing that we do, the ampersand on name, right? This has a name. It's called simple to prep. But what does that really mean, simple to prep? Well, it means that there's a method called to prep on the simple class, right? And this is, again, a simplification, and it's not needed in Ruby 1.9 or Rails, which is where a simple to prep came from. But look at what it's doing here. It's, again, delaying this decision with this black context, right? To prep is the name of a method we might want to call, and so we just delay the decision and then when we finally have a receiver, we'll send that message to it, right? And we can call to prep on things and get an edge string. This is successor, I guess, whatever. Next, the next one. Gets an edge string or a next number. But the cool thing about this is what happens when we put an ampersand in front of it? If it's the last thing in a method call and it's got an ampersand in front of it, then Ruby automatically calls to prep, right? And converts it for us. Well, that leads to an interesting question. What else in Ruby has a to prep? Anybody know? John the Dirt? Lambda. Lambda? Yeah, Lambda, prep, same thing. I don't want to go into that. I don't know what they're saying. Method. Method has two programs. Yes, there is an object in Ruby for representing methods, right? Let's go into this. So you can have a fixed num and then you can ask for a method on that object, so in this case the plus method, and it gives you back this object that's called a method. It's a method object. And you can call it normally like you could with Lambda, prep, whatever. Or we can call to prep and convert it ourselves and then pass it values the way we've done before, but look at this. If we put the ampersand in front of it, Ruby's going to call to prep for us and do that, right? So what does that actually mean? Well, it means we can map objects to blocks, right? Anywhere that we have a block interface, which is like everywhere in Ruby, we can use an object instead, right? So I needed something that we could do cool things just by passing the blocks, like Synodra. We can create an entire web application just by passing some blocks, right? So, here's a simple example. We'll take an object, a simple object, an array and turn it into an entire web application, okay? I'm so glad you laughed. I went and explained this example to my wife one night and I just started cracking up. That was great. I think she thought I'd finally gone over the deep end. Did I mention I didn't get a lot of sleep now? Okay, so we're just mapping some URLs to some methods on an array. And we have an entire web application. Check this out. We can AQ things. One, two, three, right? D, AQ things, pop them off. P, what's there? It's two. Now that we've pulled the one off, like so. We built an entire web application just by mapping some blocks, right? Cool. Okay, the truth is, I just used a whole bunch of dirty tricks right there. So I probably ought to explain some of them. We're going to do a little pen and teller thing here and I'm going to show you some of what I just did. So there's a lot of dirty tricks in here. First of all, I have used something where I can control the arguments to lots, right? Some methods need arguments like push. You can take any number. In this case, I'm just passing at one. My original thought was to use rake for this example. But in rake, I couldn't control the arguments as well because they're all coming in one hash. And the first argument is always the task itself. So I couldn't really make it bend to my crazy example here. Also, I had to choose my methods carefully because Sinatra is expecting, like, a string to be returned, which is the content to be displayed, or something that responds to each. So I chose methods that, you know, return the items, the strings I was putting in, or the array which responds to each, then it'll just each overwrite and use that for the content. So those are two of my new tricks. The other one was I didn't want all of these to run together. So while I was in queuing them, I added this plus, which is a URL encoded space, right? So actually, the first item in this array is O&E, but the second item is space TWA and the third item is space THR. So it's a little disappointing when you see it all explained. It's not near as cool a trick as you thought it was, right? I know, I felt that way too. So I said, James, you've got to think of a way to keep this thing alive. So I thought about it, meditated on it a little bit, looked at it from some different angles, you know, and I really put my mind to it and I said, well, all right, Summer has this wish list, right, that I maintain for her, but she tells me what she wants on her. And these are things we want to make sure mommy stays aware of, right? And we might be needing these, especially with Christmas coming up, you know. So things like self-rescuing princess shirt, there's this Wi-Fi robot on here. How cool is that? Gyroscopic board keeps track of your food so it doesn't spill, you know, it's awesome. Finished an ad for the AR drone instead of the Wi-Fi robot. AR drone? What's that? Okay, so anyways, Summer sometimes wants changes to this. She communicates this to me. And she wants changes to this. Well, I haven't built an admin interface, or anything like that. So that sounded like a perfect opportunity to review this idea of mine. So let's just map active record to Summer. That can't be hard. All right, so here is how we're going to do that. We'll just open up the Sinatra application, require a new file with the admin, and tuck it away behind some URLs so that we have a URL space we can muck with, right? And then here is the entire trick, right here. These lines here, I just require a simple database wrapper and connect to my database in the configuration step. It's an active record database backed by SQLite. So super simple stuff. Ignore the middle part for now, because that's the scary stuff. I'll get to that in a minute. But down here, look, I'm doing the same thing. I did the last example, just mapping some URLs to some methods of active record, right? I'll take out new types, destroy, et cetera. I'm making new URLs wrong. Okay, so back to that middle part. The trick is I'm pulling all these methods on this magic model object, right? And how did I pull that out? I used simple delegate, which this is so awesome. I'm pretty sure if you go back in Ruby time, you can find me stating publicly that this object is useless. So perfect thing to use in this example. And I wrote the documentation for it. That's right. Okay, so simple delegator is basically a nothing object, but you pass it something in and it reconfigures itself to pretend like whatever you passed in, right? So in this case, you pass it a fixed num and now it's a fixed num. And then you can later change the underlying object, but all the methods still work the same just pointing to the new object. Well, the cool thing about this is what if you use it on a class, right? So like right here, I give it to a class, I give it some number, but then I can later change the number out from underneath it without it realizing that I've changed its internal data, right? It's probably pretty evil, but it's cool. Okay, let's go back to that little part. So we make a model that wraps any one of the records. It doesn't matter which one. That just gets it to do the methods, right? Then before any of these URLs are resolved, we need to figure out a way to switch it to the right model. And I was running out of things to abuse in this web application because I've already appropriated the URLs, right? So I decided we'll use a subdomain to get the object we want. Yeah, not part of the URL, technically. So we'll just switch the model object to whatever the subdomain provides, right? Okay, so we get an end result of something like this where you can do rovio. You know, your post, and then add, main, remove, and it removes the robot, right? Now that, to be clear, the URL didn't return this complete page. The URL basically returns nothing useful because Active Record doesn't return anything useful there, but then if you visit the application again, you'll have this. So it's not a complete interface, but it is a mapping of URLs to Active Record, right? And then Summer thought we should edit the price on this one. Maybe that's the reason Mommy isn't getting it for us. She thinks it's a little too expensive. So we edited the price to very reasonable, again, the plus being a URL encoded space and sure enough it changes. Or we can select the bowl and then hit the admin and move it to the top. The items are listed in terms of their updated updates. All we have to do is touch it to get it to bounce to the top, right? And we can edit this web application using this simple URL mapping. All right. I don't know about you guys, but I'm kind of playing out and running out of caffeine. Before I go, though, I want to leave you with a bunch of cool blocks. So here's T for tentacles, H for henchmen, A for appendages, and for nanotechnology. I don't know if you can see it on that screen. There's a little dot right in the middle. Also, this next block could probably be considered child abuse. This is K is for potassium. Right? We did a periodic table of elements. Oh, yeah. I love that one, too. And S is for self experimentation, which is really what this talk's been about and we should all do more of, right? So thank you very much.