 Hi, as I was introduced, my name is Piotr. I would like to start with a quick show of hands. How many of you actually despise those audience engagement things at the start of the talks? Thank you. Thank you. Perfect. My kind of audience. My first Ruby conference was Euroco in Krakow in 2010. And I actually sent in a CFP and got accepted. And by the time I got there, the organizer says we have two pieces of news for you. One, you're speaking right after maths. Two, maths is delay. So you're opening the conference. So I would like to thank maths very much, that A, his plane wasn't delayed this time, and B, that his joke that he's canceling the keynote actually was just a joke. I work at a university. I'm also a CSO at a Warsaw-based Ruby and Race Consultancy. If you have any projects that you would like us to help you with them, just let me know. I also coach at Race Girls. This is one of the Race Girls students at Race Girls Warsaw. And I really fancied her. I met her for the first time in 2006. I kind of fell in love with her. It took about a year and a half of being quite impertinent with that before she even considered meeting with me. And then we got engaged. We got married. We went for a honeymoon. And if you're a Ruby programmer on a honeymoon, it's the time when actually everybody expects you to have fun. So I actually wrote a gem in the library for managing email signatures. That's what you do on a honeymoon when you have such a wonderful wife. And if you've ever got an email from me, first, I'm sorry. Second, if it was ever due, there should be a funny signature at the end, because that's how I try to make my emails worthwhile. So the way it works is you can run it. Ask senior prego. And it will show you a random supposedly funny signature. You can ask it for a signature about Lisp. You will get a signature about Lisp. You can ask it for a signature about Pearl. Why not? You can ask it for a signature about, obviously, Ruby. You can even ask about signatures on multiple topics. You can get things on the multiple topics. If you're not into Python, but you're into other languages, you can ask about something about Lisp and Ruby, but not Python. So you get something like this. So to implement something similar to this, the reason why I'm bringing this up in the first place is that you don't really need any gems. This library works only using a single gem that was actually extracted out of it. So all of its dependencies are some libraries and that other gem that actually has only some library dependencies. If you wanted to hack something like this really quickly, we would just get a struct with an author or some tags and some text. We could use a simple signature store. Let's go with an array. Why not? And we can create a signature. We pass the author, the tags, and the contents of the signature. And we can actually, because Ruby is so flexible, we can say, I don't like that syntax. I much prefer the other syntax into something like this. If you have any junior programmers in your teams, show them this, see their reaction. If we want to get a random signature from our wonderful signature store that happens to be an array, we can create a method like this that just selects all of the signatures tagged with a given tag and then pulls a sample random one. This method will return nil if there are no signatures tagged with a given tag. You don't really want to do this to the users of your library ever. Please, if you can, do not return nils when you can also return something meaningful. So the nice thing about Structs is that you can actually create something like this and this will work as a null object. And returning nils kind of feels like something that we do often. But when somebody uses your library and does not expect nils and they get nils, it's like the first time you ever encountered a geroscopic procession, you know, that thing when the gyroscope turns around and then you tilt it and it goes in a very different way than you would suppose. So we have this. We can then get a random signature from our store. If we have a 2S method, we can call puts. We can pass this as a puts and get a result. I'm covering this because this will be the API that we'll be using throughout this talk. So the premises of the talk, the examples are somewhat contrived, but please look past them. These are basically the smallest examples I could think of to give you a taste of a lot of standard libraries. There are pieces of ruby code sprinkled throughout. And obviously, as you surely know by now, I'm just glowing a reflected light of other people speaking funny things. So the array is not really such a great store for our signatures unless we're running on magless. So you could think of how we can persist those signatures. Like, obviously, we need at least three tables, one for the signatures, one for the tags, one for the joint table. But that's actually not true. We can use standard library that is called pstore. That actually has also a YAML backend. We can require YAML store. We can create a store. And we can call a transaction method on it. And if we pass it a block and that block will, inside of that block, that object can act as a hash. So we can, say, create a key if it's not there that will point to an empty array and push a couple more signatures into that key, basically. So the nice thing is that pstore is actually good enough to make this atomic. So it actually will lock the file once for writing, dump, all of those signatures, release the lock. It won't let another process step on its toes when it does that. Basically, a simple signature store that works like a document store and actually is quite reliable. We can create another example of our API method for getting a random signature. This time, we can call the transaction method with a true flag. And this will make a read-only transaction. So this will open the file only for reading, which means a lot of concurrent processes actually can open the same file and read the signatures. And again, we just select all of the signatures stacked with a given tag and get a sample of them. And we can do this and see that it does indeed work and it returns a random signature. If you haven't read the enumerable documentation, please do it. I think my favorite module in the whole Ruby style library and core. OK, so the reason why I'm showing YAML and not pstore kind of proper is that this actually is a text file. So for this kind of personal project that have a single user, I do not have to create any way of removing signatures or editing typos. I can just edit the file in place, just a text file with everything in it. So it's quite convenient. OK, quick question. Which of our favorite protocols was created in 1991, the 09 version? HTTP, very good. So let's create a web service. This is a quote from one of the Tom Stewart's pro-public and figure out which one. I actually very, other than the snarkiness of the quote, I actually very much like this quote because it reminds me of when I first encountered this error and actually it made me dive into the Ruby person. I learned a lot, so do yourself a favor and do this. The way it works here, it's a here document and here documents are started with a delimiting identifier after in Ruby to less than less than signs. And then they create a string up until the closing delimiting identifier. You probably should never use lowercase end because your team will hate you, but it looks very nice. So this is what I use in my personal projects. Usually this is like EOF or capital end. And the nice thing is that if you do this, you can like here, you can actually make it look pretty. And if you're really not happy about the indentation, you can actually call methods on the opening delimiting identifier. And they will get applied to the string in here. So this will actually remove all of the indentation from that string. We can do this again. There is a lot of, I think, misconceptions by now about Ruby documentation. It's not really top notch, but it gets better every time. And it's definitely much better than it was a year ago. And if you want to have a comment in Ruby, you can just work on Ruby's documentation. There's still a lot of work to be done, but this is something that is more tongue-in-cheek by now. And the EHH account, obviously, is worth following. So let's create a simple web server. All we need to do is require Rebrick, instantiate it with the port that we want to hook into, start the server, and call amount proc method that gets passed a block that has two parameters, request and response. And we can pull stuff out of the query parameters by calling request query and then accessing it like a hash. And then we can set headers by accessing the response like a hash. And we can set the body by just setting the body. This is eight lines to get a working web server. Probably using Sinatra is much better in this case. But if you're on a plane or if you're on a train, it's actually, and you don't have any connectivity. And so you're using some obscure Ruby implementation that you don't have all the gems installed for. This is something that you can hack quickly and use. And we actually do have Ruby like signature web service. We can call localhost 1991. We can get a signature. We can call it again if we're lucky we'll get another one. So this actually works. Cool. One of our other favorite protocols is Smatch older, but was first introduced in 1969. Even lower level than HTTP. TCP, very good. Let's create a web service, not web service, a TCP service that would serve signatures because we can. I work at the Department of Telecommunications Fundamentals at my university. So this is basically what we do all day long. So let's create a signature. If you have never read the documentation for kernel test, please do. I think it tries to mimic quite strictly the way the shell test methods work. And it's downright interesting to actually dive into this documentation. Big decimal inspect is also another thing that always mesmerizes me when I see how it looks like. So let's push this into our store. And to have a TCP service, all we really need to do is require the server, subclass it, and redefine one method, the method serve that takes an IO object. This is all that we need to create actually a working TCP server. We can write to the IO object. We can ask for the tag that whoever connected wants to see. We can read from the IO object, get the tag that the people want to see, find the signature, put it into the IO object. We instantiate the server. We start it. We join its thread because by default it starts in a separate thread. And then we can tell it to it. If we tell it to our host 1969, it will ask us for the signature, for the tag. It will find the signature, put it. We do it again. We give it a different tag. And then we get a different signature. So it's, again, something that you probably should use a dedicated, much more performant gem for. But you can do it as a prototype very easily without leaving any kind of installation of Ruby that you have. JRuby, Ruby News, whatever. If you ever thought how people could tap complete stuff into your application, obviously there are more maybe, I don't know. I haven't checked actually. But probably there are a ton of gems for this. But we can actually do this on our own again without leaving the standard installation. This is one of my favorite quotes about the restfulness of Rails, especially the first introduction of restfulness into Rails. I think it was 1.2. And this is actually my favorite quote about Rails ever. If you remember the background, that's actually even funnier. So let's say we have those two signatures. And we want to get all the tags that we have in our database. So we can flat map all of the signatures from our store. And we can take out the tags. What flat map does, it basically does whatever map and then flatten would do. So mapping all of the signatures, all of the tags of the signatures from our store would give us an array of arrays. This gives us an array of tags. So this is like flat map. It's actually quite useful in the few cases that actually pop up now and then. So we have an array of all the tags. These are basically strings. We can require Abreff. And Abreff has two APIs. One is a proper module that is called Abreff that you call Abreff method on. But actually it's also monkey patches arrays. And you can call Abreff on your arrays. And what it does, it returns a hash where the keys are all of the abbreviations that are uniquely pointing to the string. So as you can see, the L uniquely identity is the only tag that starts with an L is Lisp. But you don't have the R key in here because there are two tags that start with R. So what you can do is, if somebody presses R, you can ask the Abreff method, what are the expansions of the R? And you can also see that there is no unique tag that starts with R. So we can get all the tags that actually start with R, store them by size, get only the shortest one, but all of the shortest one, and then tap complete that part for the user. So we can tell them that it's all there, either R A or R E. And if the user presses capital E, then we can see that this actually uniquely points to the REST tag in this case. What we can also do is we can actually pass regular expressions. Of course, by default, regular expressions are case sensitive, so keep this in mind if you end up using this. This means that this is very simple to create things like the Control P plugins where in an editorial press Control P and you put random letters from the file that should be in the file name in order but at whatever, however apart from each other. So you can use this way of finding the files that would match whatever the user tries to put in. Okay, another thing. When you collect signatures for a long time because you're kind of old and you don't know anything else to do with your time, eventually you will see that sometimes you misspell an author or somebody misspells their own name now and then. So for example, one of the faniest accounts on Twitter is the Pinterest account. This is a service for collecting links and it's run by Maciej Cegwowski. And he sometimes, I love, by the way, if you ever want to check the primarily of a number, this is a very good strategy. Sometimes he's post his name with an L, sometimes he's post his name with an L, L. So I ended up having some signatures from him with either spelling. Do you know of a way of comparing a couple of strings and basically quantifying how similar two strings are to each other? An idea. Levenstein distance, yes. I'm sorry if I'm mispronouncing this. So Levenstein distance. If you have two strings, the Levenstein distance basically says how different they are. It actually says how many edits you have to apply to one of the strings to get the other. There isn't anything in the Snow Library. There is an awesome Levenstein gem that I hope to say a couple of things later about, but there's nothing in the Snow Library. So if we are on a train, we have to nihit, if that's how you pronounce those things. This is a simple Levenstein implementation. Please don't dive into it, but please look at this module function keyword there. Module function is something that a lot of modules should use and don't, but they should. What module function does is makes two things. One is whenever you mix this module into your own old class, those instance methods are actually private instance methods. So you don't blow up your classes API. And as you will hear later from Emily's talk, you really want to create backwards API compatibility on different levels. And whenever you mix in a module and two years later it turns out some users are depending on the way this module is implemented, that's actually also often a problem. So module function means those methods are mixed in as private methods. And the other thing is that this method is actually callable on the Levenstein module itself. So it's not dev self. Distance, but you can actually call it on the Levenstein module because of the module function keyword. So what we can do is we can get all the authors, all the unique authors without the nil author that will happen for the signatures that have no author. And then we can create all of the two element combinations. This is another core method that actually takes an array and returns an numerator of two element arrays with all of the combinations of the authors. And we can find the minimal, the part that has the minimal number that is the Levenstein distance between those two elements. And if we run this we will see that again in this case in our signature stores these are the most similar strings so these are probably the most probable candidate for misspelling. What we know from the wonderful Gary Bernhardt is that we can actually use Levenstein distance method missing if you ever made a misspelling in the method that you call you can just put it in method missing and Ruby will happily call the method that you probably wanted to call but just misspelled. Do it, it's fun, your team will love you. The thing with this approach is that there are so many pairs when you have a lot of authors there are so many possible pairs. Actually the number of pairs is the binomial coefficient. It's how many K combinations from a set of n elements you can make. It's known that this is this many combinations. And if the K is two because we want to get all the pairs of authors that we have this can be shortened to n times n minus one times two. The thing is when you have for example let's say a random number of 2378 authors this number is actually 2.8 million pairs of authors that you have to check. If you want to write this number in Ruby you can actually use underscores. This will parse just like a regular number and it's much more readable although if you actually do have this kind of numbers hard coded into your Ruby this might not be the biggest problem. The readability might not be the actually problem your code base has. Okay, so what we can do? We can distribute it. Google has this wonderful 4320-24 subnet and it's not using it. There is a PDA that they should delegate 4321 to NASA for local launch lifestreams. Now that, you know, the, how they are called the Buran version, the American version of Buran which is orbits this thing that, you know, you was used to transfer astronauts to the space station. So anyway, there's still launching rockets so that would be nice. So let's assume we have this subnet for example because of a just sheer lack we are running two laboratories that our work that are not used by students at the given time. We really need to put those computers to work. This subnet has 254 server addresses because the first address is the address of the network. The last address is the address of the broadcast address. So how can we run services on 254 computers that are not doing anything more important at the moment? We can actually use DRB which is another standard Ruby library that is useful for distributing stuff. All we need to do is we need to have some kind of object that has some kind of method. So let's say we have a type of finder module that has most similar paramount per method that actually you give it an array of two element arrays and it will find among those the most similar pair. So all we need to do is we need to require DRB, DRB. We can start the service. We pass it the DRuby URI which basically is the IP of our computer which is always localhost and the port we want to run it on. And then we pass in an object. And the way DRB works is it exposes that object on that port to outside world. So we can call method on that object from another computer. So you run this, you join this thread so your script wants exit and then you run it on all of the computers at your university laboratory. And the way you use it, you can create a new with URI. You call new with URI on the DRB object and you get an object that represents the object that is exposed by the other end. And whenever you call a method in this case type of finder, this method actually gets all of its parameters serialized, send over the wire, the serialize on the other end, the method get executed, the return value gets serialized, send back to you and DRB deserialize it for you. So this will actually allow you to call methods on objects on another computer. The thing is we have to somehow know the IP that you want to send to. So for this, there's a wonderful IP address in the library. We can pass to the constructor, we can pass an IP and if we pass a network part, you can see that this is not the address of the network because it's not for three to zero, it's for three to one. But IP address will figure out that this is because it's slash 24, so it will see that it's actually the network for three to zero and you can turn it into a range. The first address is the address of the network, the last, the broadcast address. So if we drop those addresses, we have all the IPs of our computers in this network. So all we have to do now is see how many pairs of addresses we can see, we can send to each of those computers. In this case, it's slightly over 11,000. So let's get all of the authors, let's get all of the combinations to outer combinations. Let's slice this into batches of 11,000 pairs. And the nice thing about Ruby as of recent is that both combination and each slice returns the numerators. So it doesn't actually create those arrays in memory until you try to pull anything from that slice. So all we have to do is we can zip the IPs, which is an array of IPs with the array of slices. This will create a array of arrays that have IP as the first element, purse as the second, and we can send this to our servers. The thing is if we run this, that would actually do it sequentially. It would send the first 11,000 pairs to the first server, wait for the answer, send another 11,000 and so on. What we can do is use the standard library thread. We can run this. This will create 254 threads. Whether this is a good idea, it's your homework. And if we do this, actually the thread new will return a thread so we can then flat map this array for values, which the value will wait for the thread to finish and see what the thread returns. So this will actually run the threads concurrently and then it will block on subsequent threads that didn't return yet, but it will allow all of the other threads to work at the same time. So we have now 254 pairs, so we can send them to our local version of this. And in the case of my collection, there is a novelty I am developer account on Twitter that is misspelled, but I was too stupid to notice it, so I had those. I removed this misspelling when I was putting the signature into my collection. This actually works. So a very quick quiz now that we're somewhat closing. What is this? Seven, number, very good. What is this? 37, also a number, even better, this. Is there anything that those three numbers have in common? Prime numbers, very good. This is also a prime number. What is this? And this, and this, and this, and this. And this number has this wonderful property that no matter how many digits you drop from the beginning of it, it will still be a prime number. Checking the premorality of numbers, as you probably know, is not something that can be done very efficiently. This is why they are used in cryptographics. And, but we can actually do this. We can actually reopen the integer class and we can say that if we want to check whether we, the integer in question, whether we are prime, we can just go from to to self and check whether we are divisible by any of those numbers. We actually can go only to, it's enough for us to check only up to a square root of ourselves and actually it's enough to go to the rounded down square root. And what we can do in Ruby is we can actually call the all method that will get all the subsequent integers into the block and then we check whether self, which is our number, is divisible without remainder by this. And if all of those numbers from to up to the square root are not divisible, which means all of the remainders are non-zero, then it means this is a, we are a prime number. The nice thing about this is that this method is short-circuited. So if we are a number that is divisible by, for example, five, a very large number divisible by five, this method will return as soon as it goes to five. It won't check all of the way to the square root of self. So we can check whether seven is a prime and 37 and so on. And it works actually quite well until quite large numbers. You can actually wait and see that it works, but it doesn't obviously work for this kind of number because the checking would really take a lot of time. But you might think that checking the visibility by four, six, eight, 10 and 12 and so on is kind of a stupid idea because it's like we're either divisible by two or we're not. So we can implement a clever prime predicate, which will have not one line, but three lines. It will return false if we were even. It will return true if we were the number two, which is actually the only even prime. And other than that, we will go from three to the square root of ourselves but every second number. So this will check only the visibility by three, five, seven, nine, 11, 13 and so forth and so on. And we can check a couple more numbers and actually get an answer. Again, we won't get an answer for this one. So this trivia is actually not something that is very common that we have such a large number that is prime. It's not something that you can, it's not the number that you can easily find. So you might ask what this is doing in the talk on some library and or you can say that big doofus, there is actually a prime predicate in the library. All you need to do is require prime. The thing is when you run it, it takes surprisingly long. And if you think that something tastes surprisingly long, you should never trust yourself. You should always benchmark the staff for this. Obviously, as we all probably know, there's a benchmarks on the library and we can check that our simple prime, this test takes about six seconds. This test is about twice as fast, which is very nice because it actually confirms our suspicion that we're skipping every second check and it's actually twice as fast. The thing is this check actually takes three times as long. So these numbers are from, I think, two weeks ago from the current 212 Ruby. And let's see whether this actually changes if we run a rehearsal before computing this. So we can use the BMBM method on the benchmark module. We get a bench object that we can pass labels to and it first runs a rehearsal, which means it tries to warm up anything that is needed like garbage collector or in case of JRuby, the JVM. And then it runs the actual benchmark again so we can compare the numbers. And surprisingly, the standard library implementation of prime predicat is three times slower than our three line implementation. So your task is try to figure out why. And when you do, you can find me and we can compare notes. So what did we learn today? We can use a few more bits of Ruby Core on an everyday basis, things like combination or flat map. These are things that are somewhat, sometimes very useful. We can persist things with Pstore which is surprisingly efficient, even for quite large stuff. There was a, I think, web survey application that used Pstore for much longer than it thought it would use it. We can serve with web break, which you probably shouldn't do, but it's good for one-off tests and G-server. On the TCP level, we can tag complete with Abreff. We can distribute with DRB and IP Adder. Check out Rindad. This is a wonderful standard library for making this all even nicer. We can slowly check primarily with the prime standard library and we can benchmark with benchmark. So the takeout for you from this talk that I would like to see is first, do play around with the numerable. Do check the library, the documentation for this module. There are a lot of things like, again, the partition methods, for example, that is very useful when you need it. And you probably re-implemented the partition method quite a few times before you learned about it. Just on a library, I didn't cover Wecraft, but Wecraft, when you read the docs about Wecraft, you will see why this is my favorite, actually, library in Ruby. Contribute to documentation. The documentation team is super friendly and you will get your contributions merged in in no time, usually. Check out the Levenstein gem. It implements Levenstein distance on any two objects that actually implement each. So if you have objects that are not strings, but implement each, the Levenstein distance will compute the distance of those two objects by just iterating over it. It has a optimized implementation where those objects are actually strings. And again, it has another optimized implementation if you're using MRI that is actually implemented in C. Do check out the gem to see how it actually implements all of those three things. There are a lot of blog posts about some library on the blog called end of the line. There was a good presentation, stop reinventing the wheel about some library. If you want to learn about Wecraft and some other libraries, come to our company. I'll be giving the second part of the stock. Follow the Ruby S to the Leap account if you want. There is a very interesting analysis of which standard libraries are used the most in gems that you can check out. And finally, telnet to this address if you never had, if you're using IPv6, telnet to it over IPv6 as well. There's a bit of a joke there. Thank you so much. Enjoy the rest of the conference. There is a bit of a delay. So if you want to ask me any questions, just find me later. And please do use standard library where it makes sense and whenever you're prototyping stuff because it's actually quite convenient. Thank you.