 This is Mike Moore. Has anyone heard of Blomage on the internet? Yeah, Mike! Blomage? I didn't even actually know that. I'm not French enough to say it that way, but I'll try. Blomage is someone who has spoken at Ruby Conferences before. I don't know if you've seen him around. Primarily pony content. A lot of ponies. Bronies. Diffritor ponies. And ponies talking about ops. Mike likes to speak. Mike likes to organize. He organized Mountain West JS. Last week, right on top of Ember Comp, he's primarily known for organizing conferences on top of Ember Comp. Then he flew here, and then he wrote a talk, and then he's going to give that talk here at this conference. Then he's going to fly home from Mountain West, where I assume some number of you are also going. Who's going to Mountain West? Yeah! Mountain West train. All right. I mean, we're way better in stuff, but you're okay too. All right, Mike Moore, please. A round of applause. Thank you, John. So, I love Ruby on Ales. I think this is my third time being here, and I just can't get enough. So thank you guys for staying, and I can't wait to have a good time with you. I'm curious about the makeup of the audience. Who here is the first time at Ruby on Ales? Wow, that's at least half, if not more. Who here has been coding less than a year? That's good. Good job. All right, so Tenderlove is kind of known for what would Freddie Mercury do, right? That's kind of what he tells himself when he's not sure what to do. That's not me, but today I was just thinking what would Corey the front man for Slipknot do? Because I know, like, I don't look it, but, you know, I'm a moderate kind of Slipknot fan, and I had this live album, and they're going to play this song that was off their first album, but they've never played it live before. And Corey says, it could be a trainwreck, but we're going to do it anyway, and that's kind of how I feel about this. So this could be a trainwreck. I literally wrote it last night and this morning. So we'll see where it goes. The title is Stupid Ruby Tricks. Now, there's three things that you could focus in that title. You could focus on the ruby. You could focus on the fact that we're going to show some sort of trick, some sort of, you know, piece of approach that's going to help you, or you could focus on what's really going to be about, which is stupid. So this is a stupid talk, and I hope to lower your expectations, and then we'll just be fine. So, like John said, my name is Mike Moore. This is kind of the picture I'm usually known for. It's not my Twitter avatar. I probably should have changed it back, but I didn't. But my name is Mike Moore. And I go by Blomage, but everyone says Blomage. It's kind of like Mirage or Frommage. But when you say Blomage, everyone thinks I'm like a medieval sex worker, but that's not me. I'm okay with Blomage. I will answer to it. So I loved all the talks that I've seen so far. One thing I'd like you to know about me, kind of like Akira or Akira, is that I too have a GitHub profile, and it's got full of all sorts of really wonderful things. The thing I'd really like to point out first is I have a URL up there. Now, it's not a long URL. You could probably commit it to memory. Just kind of think about that. It's not too many bits to kind of fit in the old brain there. I've got a lot of stuff on here. The other thing that's on my profile is my name, which is important, which I think is pretty neat. Also, I've got my username on there. So it's like two names. So that's pretty neat. It's not my full legal name. I only tell that to people that are really meaningful to me, like the bank and the IRS. But you can find that on there. So that's great. I'm from Cedar Hills, Utah. There's like a Utah contingent here of at least two people, right? Who's from Utah? Yay, we've got three, four, including me. I'm from Cedar Hills. Utah is a wonderful, beautiful place. The mountains are awesome. The people are friendly and nice. And there's a really wonderful Ruby conference that starts in two days. So if you want to keep this party going, absolutely come on down to Utah and come to Mountain West RubyConf. The other thing I'd like to point out in this, and this is here, this is on my GitHub profile, is that my company name is Humane Code LLC. And I think Ernie Miller should expect a cease and desist letter from my lawyers pretty soon. It's very clever, Ernie. I'm glad you thought of that before no one else did. The other thing is I've actually got some contributions. So here you can see my repos. The thing I'm most known for is Many Test Rails, which is a really fun little project that I run. Now Many Test ships with rails, right? So this doesn't really do anything at all. It's of no value. And that's my most starred gem. So yay me. The other thing that's kind of embarrassing on my GitHub profile is it shows you your contribution calendar, and I want you to point to this section right in the middle. Can anybody guess what was going on in my life at this point? Vacation. Alcoholism, yes. I will get to the alcoholism a little later. No, I was at a startup during this time. I like to consider this my trough of disillusionment period. This was after the peak of inflated expectations, and before the slope of enlightenment and plateau of productivity began. Unfortunately they didn't, and so in October, late October I started, I went somewhere else, so I'm contributing again. That's nice. The last thing I want to point out is that something that, you know, like Acura's got to GitHub profile. I've got to GitHub profile, and we're both really close to a thousand followers. Really, really close. So, anyways, I guess what I'm trying to say is that I'm kind of a big deal. Really, if you think about it. Yeah. Yeah. Who was here for my pony talk like two or three years ago? Yeah? Okay, yeah. This is going to be worse. Just letting you know. Right. Again, it's about stupid. This talk is all about stupid. Actually I do feel a little bad. Before the conference, I've got the run up for Mountain West JavaScript and then here and then going back to Ruby. And so I was messaging Josh, and I was like, dude, is there any way we could move me? Because I was supposed to talk yesterday morning, right? And I literally did not start until last night on this talk. I was like, can you tell me whether you could move me to later on in the conference so that I actually have something? And Josh, being a super nice guy, he's like, no problem. We'll move you to Thursday and we'll just move Terrence up. And I'm like, awesome. That's so sweet. Thank you so much. Then of course when we get here, like Terrence shows up and is like, guys, Friday hug is my thing. And so I was like, oh, we'll bring you up and you can do Friday hug. But then Ernie shows up, right? Totally takes over the Friday hug. Seriously. All right. So those who know me, I'm not a big beer drinker. I'm a lot like Ryan Davis, you know, Ryan I think is, I think of as like a mentor and I like to follow him. And so I also prefer Scotch on the rocks. Yeah. Right. All right. So I think I should apologize. I feel like I'm starting to lose control a little bit. No. No. See, the difference is that tender love is what would Freddie Mercury do and blowmage is what would Corey do. Right? Totally different. Totally different. Very different. And all right. So I know what a lot of you guys are thinking right now, is this going to go on much longer? Right. Because you're like, it's full of puns. And this is for Jonan. Like I got a space picture in. I am on the theme. Right. Today's theme. I'm moving it forward. We're just going to happen. We're going to make this happen today. Again, the purpose of my talk is stupid. All right. So let's talk about, let's talk about a stupid Ruby trick. Something that requires no brains at all. So let's talk about file.write and file.read. So this is the way like, I've been in Ruby since 2004, late 2004, early 2005. And when I came to Ruby, this is how you open and read from the file. Right? You open the file and then in the block, the closure there, you actually read from it. And then the file takes care of closing the file for you. Right? And then when you read the same type of thing, you use the open block, and then you have to pass the W flag in order so you can actually write to the file. And then, I'm sorry, I got those reversed. I wasn't even looking at my slides. I'm so nervous. Anyways, you guys get what I'm talking about, right? All right. So we have that today. Instead, you can just call file.write now because of like Ruby 1.9. Like who has used file.write, right? Okay. Only like eight of you, so it's still good advice. It's still good. This is knowledgeable, right? And then the same thing for reading. You can just read right from the file without having to open it and it's stupid, right? Yay, stupid tricks. All right. The purpose of this talk is stupid. All right. Here's another awesome, stupid trick is optional parentheses. Did anybody here know that Ruby has optional parentheses? All right. So here is the code that we just had written. Everything's uncommented. Now, look at all of these parentheses. I'm going to highlight them in fuchsia so they really stand out on this projector. I did miss one. Dang it. It's stupid. All right. You can remove all of these. None of these parentheses are required, right? You can come up with something like this. I actually think this is a huge improvement. Can somebody point out, like, what's the thing that bothers people who like parentheses the most? File.read. File.read. Okay, here we go. So how does this work, right? That last line. It's like you've got put s that's receiving file.read, that's receiving the string and what's the priority and you don't have the parentheses to help you out, right? And so I'm going to break the format a little bit and stupid Ruby advice number one, don't overload lines. If you can't remove all the parentheses on a line, you have doing too much stuff on that line. Just add another line. If you're at a place where you've got to, like, keep all of your methods under, like, 10 lines of code, then, you know, don't just jam all that logic into a single line. Don't use ternary and stuff. Like, actually respect the parentheses, the absence of parentheses and don't overload it. Just make it simpler, right? I think it's good advice. So I imagine, like, all of you knew this already, right? And like, what am I doing up here to present these tips to a self-slucting crowd that knows everything? I would just like to point out that I do have the necessary qualifications to present. I've been programming professionally for 20 years. I've been in Ruby for a decade. You may think that my qualifications are irrelevant, but they are not. And don't worry, this will be over soon enough. All right. Let's talk about default hash values. This is kind of fun. So let's imagine we have a hash and we've got a FUNABAR key with a FUNABAR value. And what we want is we want to ask this hash for Baz and we want to get Baz. But Baz isn't in it, so when we ask for Baz, it says nil, which is the default value when there is no key that we're requesting. But we would really like to have Baz return. We know that we want Baz. And maybe this hash is really only an exception hash. So one of the ways that we can do this is that we can just call fetch and provide default value. So now our hash will go out, look for the key if it doesn't find it. Instead of giving nil, it will give this value instead. So if we instead put a new exception in this hash, like TrollFace, when we ask for TrollFace, even though we give it the default value of Baz, TrollFace back out. So I don't know, I think it makes sense for this presentation. What else can we do with the default value? When you create a new hash, you can't do this with the curly braces, but you can, with the new method, you can pass in an object that will give you for the default value. So that way you don't have to call fetch. You can just use the square brace accessors. So in this instance, we have a brand new hash list. It's an empty, but we're going to want to get an empty array when we come back out. So when we call nope, we expect to get an array. And we can even start adding stuff like we can add an X and a Y and a Z symbol. And so this nope array, even though we haven't really set it to an array, and we get X, Y, and Z in that array. The problem with this is then if we ask for not even on this hash, we get the same values. And that is because the object that we gave for the default value is being manipulated for all of the times we're accessing the hash. So even if we don't use the square brackets, if we use array.new, same behavior. So the way we get around that is instead of passing the object, we're going to pass... I'll illustrate this again. So let's say our default value object is a string called default value. We're going to go to hash. When we ask for nope, we get the default value. And then we modify that original default value. We ask for nope again. We get the updated object. So that's why this happens. So we can instead pass a block that takes two arguments in the proc object. It'll take the hash that it's being requested for. And then you can decide what you're going to do. You could convert the key to a string or do whatever. In my case with Baz, I would have just converted it to a string and upcased it and gotten the same behavior. But we're dealing with lists here. Because this is a proc, we can create a new object here. Then whenever we ask for the default value, this proc will get executed. We'll create a brand new array in this instance. Now we won't be sharing arrays. So we can add the key to nope and then ask nope, we got the x, y, and z. We ask for not even. And we have an empty array. So yay! What else can we do? We can do the same thing with another hash. Maybe instead of a list, we want some recursive hash. Like a PHP dictionary or something. We use that same constructor block. And we just say if we don't have a value, we're going to use a brand new hash. And so our hash is empty. We ask for x. We get an empty hash again. We ask for x is y. And we get nil. And if we ask for x is y, z, we get a no method error. Because that hash only goes the first level down. So x is a new hash according to our default proc. But y is nothing and then calling z on nothing is an error. So how can we make this even better? I had to break this into two lines. But you can actually reference the original parent hash's default proc object and set that on the newly instantiated hash. Right? That's pretty cool. If you call x, you get a hash. If you call x is y, you get a hash. If you call x is z, you get a hash. And when you look at the original hash, you've got all that structure in there. And every time you access something, it just adds a new hash for you. Which is pretty cool. All right, so let's make a mess out of this. Let's torture Ruby a bit. Let's create a Frankenstein hash, Frankenstein object. And we're going to start out with x, y and z to nope. And then we're going to call not even. We're going to get our empty array. We print out Frankenstein. Right? And we get that array. We get nope with the three and get not even with nothing. Then what we're going to do is we're going to change the default proc. We're going to set it to the recursive hash proc. And then we're going to call x, y, z. And then when we look at Frankenstein, now we've got the different behavior. We've got change it even on instantiate hashes. So if you have a hash that you're using, you want to add this behavior, just update the default proc object. Right? That makes sense. You guys following this? I'm going to leave the code up here for a few seconds just so we'll let that sink in for a bit. Let's talk about including prepend and our friends super. This is one of the things that we like about modern Ruby. I actually want to find a really great use for prepend because I think it's a really fantastic facility. So let's take this example. We've got our foo module that does a thing. And we want to include the foo module into me, right? Because I do a thing and then I also want foo to do its thing as well. So foo does a thing. I do a thing. I call this though, me.new, do a thing. It only puts out me because I'm not like calling super to tell foo to do its thing as well. But see, I want to do my thing before foo does its thing. So to get around that, to make this work when you're dealing with calling up the call chain of your inheritance here, you need to call super. So I'm going to go ahead and add that. I'm going to call super. I create a new me and I do the thing. I do the thing and then foo does the thing. That's kind of the way that it works. And that's kind of nice. Now what's nice about the new prepend method here is that instead of being at kind of like the end of that inheritance chain, it'll put it up before you, right? So if you looked at the ancestors of me, foo would actually show up before. So I want to switch that to prepend because I could call super beforehand, but I want to keep super at the bottom. I want foo to do its thing and I want to do like all the other modules that potentially do a thing that I'm including to do it before me as well. And I don't want to change my code to do it. So you can call prepend and it will just put it in a different spot in the inheritance chain. Now, when I call to do the thing, foo does its thing, but I don't do it anymore, right? And that's kind of a bummer because foo is not calling super. It's not going up the inheritance chain. So let's have foo also call super, right? Does that make sense? So I'm going to create a new me to do the thing. I do the thing and then foo does its thing which is good and then I do my thing which is good, but then we get this error because I'm calling super and there is no super, right? And that's kind of a pain. Now, there's lots of ways that you can go and guard against this. You can be really anal about which modules are intended for include versus which are intended for prepend. But I think a better way and I didn't know that you could do this until, you know, relatively recently is that you can actually check to see if super is defined and if super is not defined then just don't call it, right? So put a guard conditional on this and now it doesn't matter, right? foo does its thing, I do my thing we added a bar that does a thing or a baz that does a thing, they just call super it's not up to the module to determine if it's going to be included or prepended, right? It's just going to kind of do the thing and then call super if it can, right? So I'd like to see more of this. I'd like to see more defined super in code. And then we can switch it back to include create a new me to do a thing now I do it and foo does it code isn't changed, the only thing that's changed is include to prepend. So, yeah that's pretty cool, right? I think this next slide really says it all that obviously did not work I'm sorry these are very terrible puns okay so you may be asking why am I doing this to you and the truth is the truth is is that I love t-shirts I love conference t-shirts, that's one of my most favorite things about coming to conferences and putting on conferences is the t-shirts in fact and this is God's honest truth, last night I had a dream that all of us together we went to China, right? And we are going through customs we're all going through customs together we all had our passports and we all had our visas and we're waiting to get through you know like the customs lady is asking this like a year for business or for pleasure you know, who is your visa signed by, where are you staying, what hotel are you in and everyone was getting through and we were all happy and everyone looked awesome by the way you all looked fantastic in my dream and everybody was wearing a white pressed dress shirt except for me I was wearing a t-shirt and I could not get through customs, right and so you're all like let's go, let's go and I'm like I can't like they're not letting me out they're going to arrest me and you're all like going to China without me so anyways, I love conference t-shirts alright, I'm here for the t-shirts I'm also here for the stickers like I love stickers, I like to make stickers I like to put them on so so I just want you to know that this torture I'm doing with the puns it's it's not about what I know it's not about who I know it's not about whether or not you know me it's about whether or not I get a t-shirt and a sticker and whether or not I can and I'm also here for the t-shirts and I'm also here for the t-shirts and I'm also here for the t-shirts that are available through China alright, stupid trick number five data and end how many people have code like this where you've got a constant with like a lot of data like the strings or just values and their code like I've got some files that are like, I don't know like a hundred lines of just all this data stuff in a constant right? And what this will do is it will take everything after underscore underscore end and it will throw it into data, all caps data, right? It's an IO-like object, right? So what you can do is take all those values, throw it at the end of the file, and then read from data and then split on commas or however you're formatting your data, and you don't have to scroll past all of those constants because we all put our constants at the top of the class declaration, right? And then we have that long list of data. So you can just throw it at the bottom of your file and it's still diffable. You're not like going out to a config file or something. So that's, I thought, pretty neat. You can even go a little further and you can even format that data so you have structured data with YAML or with JSON under the end, right? So it's, I think it's a pretty good crap. All right. I'm running out of time. I need a wholesome ass because my ass is on a line here. So I'm there on the line. All right. Pstore. Who here has used Pstore or is aware of Pstore? Cool. Only like a third. Oh, cool. This is nice. All right. Pstore is in the standard library. You don't have to do anything to get it. It's pretty nice. You require Pstore and then you create a new Pstore. You give it a path to where this file is going to exist and it's going to create a binary file that is transactional so you can have multiple processes work on this file and it will lock and do all the things the right way. But it is the simplest database, the file-based database and you can, within the transaction block, read or write from this object, right? It acts like a hash. You give it a key and you shove in an object. You access a key and you get an object back out, right? So I think so far this presentation has had two useful pieces of information and that's like eight nines of puns, right? And then to pull it back out, if you pass through the transaction, it's a write-only transaction, or read-only, sorry, I got those reversed again. And then it shows you how you pull it out, right? So you can kind of see how you could use Pstore, create like some sort of repository object. Maybe you're doing like an IRC or a Twitter bot and you don't want to actually spin up a whole other service for this, you could just use a flat file and access it. And that's actually really useful. Here's another example. Like here we can set the useful information for Pstore, we can increment it, right? And then we can set puns to infinity and we can pull them back out and it actually works. And it will actually say so far we've had infinity puns. So that's pretty cool. The other thing which is nice is that it's not just like the raw values, you can actually do something like an open struct object, right? So here I'm going to create a new me with my name and my username. I mentioned that earlier on my GitHub profile, I've got the two names, which sets me apart. Create that local object. In my database transaction, I'm going to set my user to that object. And then in a separate transaction, I'm going to get that object back out. And those objects are two instances of that same data. The object IDs are not the same, but they're both open structs. They both have a name and a username with the same values. The object IDs are different, but they're all for all intents and purposes the same, right? Which is cool. It's not just the kind of the standard library types. You can also create your own class with accessors. Create a Pstore. Create a new user instance right to the Pstore and read from the Pstore. And it works the exact same way, right? And if you ever wanted to look at the file, it's all binary and you can't read it, but you can. This is really fascinating. I like this as well. You can just swap out Pstore for YAML store and Pstore for YAML store in your code. And it's the exact same code, right? So the only thing that's changed is what the database object is, but it's API compliant between the both. And then you can open up that YAML file and see all of the structured data, right? So I know you're... I think this is pretty cool. Who thinks this is cool? Raise your hands. Everybody raises their hands. It's like, hit. Thank you. All right. So I can feel what you're asking. You're hoping that we've got a lot more tips and I'm afraid not. That was my last one. That was my last tip. But don't worry. Everything's going to be all right. You get that a moment. Think about it. Yeah. You all right, Jonan? All right. So I... Thank you so much for letting me speak. I think the organizers for having me back. And I hope that I get lots of fan mail from everybody who's watched us today. Please. It would be fantastic. If you want useful Ruby information, there's a couple of links. There's a James Evergrave video from RailsConf 2010 where he goes through like 101 useful Ruby tips and then Aja has her cool shit file blog. That was out recently. And thank you very much. I appreciate it. Thanks.