 Two o'clock, all right, let's get after it. How we doing, everybody? Day one, RubyConf, L.A. Thank you guys very much for sharing your conference time with me. My name is Andy. Thank you for your energy. Thank you for being a member of this community that I love. We're gonna talk about designing physical products with Ruby, but first I wanna kick it off with a question. Who in this room has been taken unexpected to an unexpected place with Ruby? Raise your hands. Started something you didn't know you could finish, learned something you didn't know you would learn, accomplished something you didn't think you could accomplish, put your hands up, and keep that up if that experience left you feeling fucking limitless. Do you feel like you can do anything? That is beautiful, I love it. I've shared that experience. That's probably the biggest reason why I love what we do as Rubyists. It's a beautiful journey to make software, it's fun, it's amazing, and I wanna talk about being limitless and I wanna share with you the journey that led me here. It actually started for this in a L.A. cafe in Culver City last January when I initially applied to give this talk at RailsConf. I wanted to combine my passion for making things with a laser, with my passion for making web apps. It was unfortunately rejected and I wanna think I did what any enterprising individual would do, cross out Rails, put on Ruby, applied to RubyConf and it was approved. We did it. My first reaction was elation. I get to go back to L.A. from New York in the winter. I get to work on this fun project but my second reaction was shit. This is gonna be a case of CDD, conference-driven development. I have not done this yet. Can this work? Can I merge these things? Will there be actually a benefit of using Ruby to design these things? And would Ruby even be the best tool to use? So I panicked a little bit, I was freaking out, but then I thought about L.A., I thought about the king, one of my heroes, LeBron James, took a deep breath, drank some red wine as he famously does and reflected on my craft as a Rubyist. And to me, being a Rubyist means standing on the shoulders of our amazing community and creating with limitless possibilities. So I got inspired again and I said fuck it, let's build some software that is gonna design physical items with limitless possibilities, limitless variance. So let's set out the objective. Let's say we want to build a Ruby program that is gonna let a user design infinite variance of a physical product to laser cut an edge. But first, I feel like all of our developer community, we always are like, oh, who's the businessman? What's the business case? So let's define it. The business case is we want to open up an e-commerce store, we want to sell some custom laser etched products, we want to have them mass customizable by the user. So let's build a Nike ID of something and let's automate the fulfillment process as much as possible. Let's make it easy to actually run this as a business. So the first thing we did before writing any lines of code is we did some research, right? Smart thing to do that we always forget to do. I want to see who's out there doing similar shit with Ruby or otherwise. And the first thing I came upon was Make-A-Box which was awesome because I've actually used this in the past. It was built by a San Francisco-based Rubyist Kiggster on GitHub and it's a website that lets any user make a custom box with any dimensions which is pretty rad. So this is dynamic design system built in Ruby. The underlying code is actually open sourced and it's in this laser cutter gem that you could check out and here's the output of that. We put in some dimensions and we can get a vector PDF design of a box. This is what I'm talking about, this is what I want to do. There are also some businesses that I found that are run on similar principles of these user-driven design systems. This is one thing called the nightsky.com. It lets you design a poster of the stars at any location and date and this is a poster of what the sky is supposed to look like from this hotel tonight. They're selling them for 60 bucks a pop on that website. This is also something called Map-A-Full. Map-A-Full makes beautiful posters of maps where any user can customize the location. This is a map of LA from here. I tried to color it with traffic, it wasn't an option. That's 55 bucks on their website. Printful, also I really love Printful, I've been following it for a while as a company. It's an automated printing and fulfillment service. They have maybe 100 products on there, everything from pillows to tote bags to socks to shirts to mugs. There's integrations with Ruby, there's integrations with Shopify and you could basically send it a design via an API and they will handle fulfilling and printing a custom product which I think is pretty damn cool. I was so scared before, but now I'm running the numbers, I'm getting excited, I'm no longer stressed, I'm seeing dollar signs on this thing. I think that we can use these principles to maybe make some software that can generate some money and make a business. But let's focus back on the laser. Let's start off by making something via the normal process. I got into this craft because I wanted to take the joy that I experienced in making digital products as a Rubyist and transfer it to making things that I could touch and feel. Let's go through it. So I got this vector of the 2018 RubyConf logo emailed to me by Abby Phoenix. She said, if you need it for your slides, I don't know if this is exactly what she meant, but it worked. I popped open Illustrator and I made a large sheet of them. One thing to note of how we design it, if we use black in this with the laser cutter, it will etch it. And if we use a .01 point red line, it will cut it. So those are just different settings on the laser cutter. Here's some common materials of stuff I've used in the past when I'm laser cutting. Acrylic, metal, wood, cork, leather, paper. I wanted to use wood since that's what I had in the shop. We're gonna pop open our handy Trotex speedy 400. And next we're gonna focus the laser. So this little metal tool ensures that the laser is the proper distance from the material. It could be really dangerous if you don't actually do this step, so it's an important step. Then we're gonna do some settings while we print it. First thing we're gonna do is set the material. The material is gonna give us some predefined settings for it. I'll set the size of what we're gonna cut. So that's the width and height and inches. And then we're gonna set the cut and etch power and velocity. So the black is for the etching as we talked about and the red is for the cutting. And there's two important things here. One is the power, so that's the intensity of the beam. And the other thing is the speeds. That's gonna control how fast the laser will move. If it's slower, it means it's gonna be on the material longer, which is gonna be more intense. And one thing to note is that we're doing this for red and black right now, but you could design any design with different settings per color. So it could be used theoretically like that also. We're gonna use an awesome Windows program called Trotec Job Control, pop it in. And then we are gonna cut some stuff. I think this took like six minutes to make like six of these. The speed of this is actually like quite dependent on how you design it, more etching time. I wasn't really concerned about that for this, but you can definitely optimize it for time better. My favorite part is the cutout, which you'll see in a second. Yes, very satisfying. And we've got some rubies. I brought a bunch of these here. I have them up here. Please do come up and take some of these. I really do mean it as a little souvenir of our time together today. And they look pretty rad. I think. So we made a ruby, now let's make with ruby. But first what we wanna do is we're gonna source some products for our e-commerce store. So we did a little research and we're gonna start a source selling three products. One is a notebook from Muji that will come out to 70 cents a unit. Then from Alibaba, I figured out some things to source. One is like a felt laptop sleeve that we can etch into and the other is a phone case, 164 and 240 respectively. And to make these designs, I'm gonna use my all-time favorite Rails Jam, Prawn, Prawn. Who's used Prawn before? Great. Yeah, it's super popular. I've used it in the past. I really never appreciated how powerful it was until this project. So it was definitely exciting to revisit something that was a tool that I've used in the past that I've actually probably struggled with in the past and to come back and use it more powerfully and flexibly. And of course, thank you to the 120 contributors to Prawn. So we're gonna make a little app. We're gonna set it up with two basic models. We're gonna say a template and an item. So a template is gonna have kind of just two attributes right now, a name and a size. So we'll make a template for each of our product types. You'll notice that also we're using this like .in which will convert inches to points. That's actually something that's like an extension on Prawn called measurement extensions that we can use because Prawn works everything in points usually. Next we have item. So the first thing to note is that it's an inherited class from Prawn document. Didn't need to be done this way, but I thought it was clean. And then for this application, the sample app, all we're gonna do is initialize these items. So we provide it with a template name. It loads that template. We set the Prawn document page size based on that template. And notice also that the margins are zero. So we wanna be able to work on that document without any margins. We register the fonts that are usable and select which font we wanna use based off of the options that the user provides. We draw the design, which is where the magic happens, which I'll show you in a second. And then we render the file out in illustrator format. It could be a PDF too, it doesn't really matter. Illustrator can open both. Next we draw the design. So we have five methods here. Probably could have put them in their own classes, but for this case it doesn't really matter. And I'm gonna go through each of the five cases and each one is gonna be kind of like a different system that we create to customize these products. So the first thing is gonna be just simple text. So we're gonna say, okay, put some text on each item in a specified font. So that looks like this. We call the Prawn text method. We pass it the copy and then we set a few things. The size, the alignment, the color. The important thing actually to note on this is that the mode is fill clip, which will actually render the font as a vector and not be text. And this is actually important for the laser cutter to be able to cut it. So if I run something like this, item.new, I want a laptop sleeve, let's take a font at random, let's pass the text. I can make myself a little laptop sleeve, which is rad. Or I can make a laptop sleeve for every RubyConf speaker that was here. So just looping through a bunch of names and putting them in. So this was cool, cause this was like a little way that we can make a bunch of products. The next thing I wanna do is some kind of graphic. So I said, okay, let's get like some kind of like SVG graphic on one of the items. To do this in a flexible way that I would say would give me more variants, I wanted to use an API. So I found the NounProject API, which NounProject is really great for using icons on web apps, which I usually use it for. I also found a Ruby gem that was created by Taylor Brands, which is like a website that generates logos. I had never come across it before, but they put out this API in Ruby, which I appreciated. And I just made like a pretty simple NounProject client. You can pass it a term, it'll return an icon. That's pretty much it. And then let's go back to our item and let's like a draw icon. So draw icon will actually pull the icon from NounProject and then render it onto the document. So here we're putting it center on the page vertically and horizontally, and setting it to a width of 40% of the page. One thing interesting here with Prawn is this SVG call. So that's actually not native to Prawn. That was created by GitHub user Mogest, who made Prawn SVG, which is really rad, so it lets us place SVG files within our PDF document and we'll come back to that even and use it later. So if I wanted to make an iPhone case with a Ruby, here we go. Pretty simple, just item.new, specify the template, and we'll pass it an icon. Or if I wanna make a bunch of iPhone cases that are generated from a random list of strings related to Los Angeles, I could do that too. So next is the third case. Let's go over some kind of like templated product. So I wanted to make something that would kind of follow a more rigid format, but also let the user kind of determine what to fill it in with. So I figured let's make something with tweets. I used the Twitter gem from SF Eric, and just made a simple client to search tweets, pass it a term, and it'll find a bunch of tweets. So now we're gonna be within our draw tweet method. So the first thing we do is we take a Twitter icon, which I had downloaded previously, and we're gonna use that SVG method and put it in the top corner of the page. Then we're gonna use the font Carto, and we're gonna put, I'm cleaning the text first, but then we're just gonna put the text of the tweet on the center of the page. And then we're just gonna render the user screen name and then the date. So if we just take our little Twitter client, look for every tweet with hashtag rubyconf, we can make a bunch of different ruby based designs of the, on this laptop sleeve, which is good, because who doesn't wanna memorialize people desperately trying to cop rubyconf tickets this week? Okay, so let's change it up a little bit, try to make maybe like a full bleed pattern on the page. Maybe it's gonna cover the entire item that we're gonna etch into, and let's first start with just a sheet of equilateral triangles. So here we're gonna introduce some more variables that we could put in that will allow us to create more variants. The first thing we're gonna do is size factor. So this is just gonna be a percentage that will determine the width of each triangle. So if a size factor of 0.2 means that each triangle will be a width of 20% of the entire page. Then we calculate the width of the triangle based on that size factor. And then we also figure out the height using some trigonometry, which is whack. And then we figure out how many rows and columns of the triangles we need based off the height and width. So then we could set the position, the star position on our PRON document to 0.0, which is the bottom left-hand corner of the page. And then if we just loop over the columns and loop over the rows, we can just spit out row by row of triangles. We set position one, position two, position three of the triangle. We use stroke polygon to create the triangle with those positions on the grid. And then we move the star position at the end of each triangle, and then again at the end of each row. So kind of just lays them out one by one on top of each other. And this is the result of that, just a bunch of equilateral triangles, which is not too exciting, although it is kind of cool that we've generated this visual thing with Ruby that put that into the laser cutter and we can make a physical product. But of course we need to make it where we're interesting. So we're gonna introduce a few variables that can alter how these things will render. The first thing is gonna be the fill factor. So we're gonna say the percentage chance that a triangle will be filled in, as opposed to just outlined, the omission factor. So we're gonna say a percentage chance that we will not render a triangle, maybe just leave it blank just to give it more like random feel of a pattern. And then maybe the punch factor. So we're gonna say the percentage chance to outline a triangle in the red stroke, which you may remember from the original example, will actually like cut it out of the design. So just with something like this, if the fill factor is greater than a random percentage, fill it in, if not just stroke it. The random percentage is just like a little method that I made that returns a number randomly from 0.01 to 0.99. So if we fill in some triangles, that's what it looks like. Next we're gonna use a punch factor. So we're gonna say if the punch factor is greater than a random percentage, set the width at 0.01 and stroke it red, if not set it to a different width and stroke it black. I've increased this just for the demonstration just so you could see it, but you'll see there's now a bunch of triangles that would be punched out. And also if the random percentage is greater than the omission factor, we can, we'll make the fill call and if it's not, we'll just skip the call. So that'll be a few of them kind of like skipped out just to generate a random pattern. We could also do this with squares too. So the height is the length, so it's a little bit easier. The rows and the columns are the same amount, which is easier. It's the same thing. There's four points. There's no trigonometry, which is lit. And then we can make a pattern of squares, which is rad. So now if we wanna write a script using all the variables that we've created already, we could set the two type options, square and triangle, and then we can set ranges for the size factor, the fill factor, the omission factor and the punch factor. And then maybe 100 times we make a new phone case and we just pick a random number from within that range and then we can make like a bunch of different patterns really easily. Those are not rendering properly on that screen, but that's okay. Cool. So the final case we're gonna do is something with nested patterns. So kind of a pattern that consists of another pattern. So as our base patterns here, we're gonna use just these six cubes that I whipped up in Illustrator. So we're gonna say let's make a pattern of them with variable size and a random ordering of these sub-patterns. So easy enough, first we're gonna set an array with the list of our cubes. Then similarly we're gonna set the size factor based off of what we pass it in. Then we could figure out what the length of each cube is and then also the height based on the length, 1.32 is actually the ratio of the size of that specific cube. So this script would kind of only work for those cubes, but that's okay. And then similarly we'll just nest over the loops, excuse me, we'll loop over the columns, we'll loop over the rows and we'll use our handy SVG method to just render a random cube. So this will give us, that's also not generating right, which sucks, but this will give us a random sort of design of this. And that is pretty much it for the code that I created to create random designs. I've included all these examples on my GitHub here, if you wanna check it out. Layers is in Trimp and homage to Perron. Thank you in advance for your stars. But I also wanted to go over some other resources of things that I was looking at while working on this talk that I thought were interesting. One thing was something called GeoPattern, which was written by Ruby Jason Long, and he made something that will make a geometric pattern generation, bleh, a geometric pattern generator that will take a string and output unique patterns. They come in different shades and gradients. These are six examples that he includes on the site, they're pretty cool. I don't know how that would work in the context of laser cutting with the different shades of colors. It looks easy enough to modify some of his code and make them only outline. You could also probably mess with the color settings to do different etchings, f speeds based on the different colors, which could be interesting also. Another thing is processing. Has anyone here tried using processing before? Okay, cool. Processing is pretty rad. It's an object-oriented language for coding visual designs. You can export it to SVGs too. I was originally gonna do the whole thing in processing, but I wanted to kind of stick it to more of a classic Ruby thing, but there's also a Ruby port of processing, which you can check out. Check out JRubyArt. It's pretty cool. They have a bunch of sample patterns that you could run and scripts that you could run, so it's pretty handy. I definitely encourage anyone that's trying to branch out and do new things with Ruby to check this out. I did think a lot about could I automate the laser? There are definitely ways to do it that I looked up online. Unfortunately, not with that Trotec model that I had access to, but I didn't really see a big benefit in doing it, just practically speaking. I think this was a case where I could say, okay, we can now create a business where we can make a Nike ID of laptop sleeves or something like that, where if you automate a laser, you still would probably have to sit there and replace the products under it, so I didn't really think that was gonna be worth a squeeze. And that is pretty much it. Thank you guys all for your time. I really do appreciate it. I love speaking about things that I love. You invested some time with me today and that's a burden I take seriously, so I would love any feedback you wanna give me. If it was great, I wanna know why. Sucked, I wanna know why. A shameless plug. I run a software development agency based in Brooklyn, New York, where I'm from, called BangEquals. That's why I rocked the BangEquals hat. Chance the Rapper made $6 million selling his hats last year. My mom has this in three colors. Get in there. If you wanna collaborate with me and build amazing things, if you know a company looking to hire an agency, please reach out to me. And thank you. Thank you for listening to me speak. It's a joy to be a Rubyist. It's a joy to feel limitless like this project. I hope you guys all keep those joys in mind as you experience RubyConf this week. And yeah, I would love to chat with anyone. Please come up and chat with me after. Here's my email. Please take one of these laser cut rubies and I would really appreciate your questions. Thank you.