Tricks and treats for new developers
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Padilla, David
Are you ready to begin building applications with Ruby on Rails? It's very easy to follow a tutorial and learn how to build a blog in 15 minutes, but there's a lot more to it in real life when you try to code a big web app. During this talk I will give you a bunch of tips and tricks for Rails development that almost everyone follows but rarely anyone talks about. If you are about to join this fantastic community, this talk is for you.
 Welcome. My name is David. You can find me on the internet as David, Twitter, GitHub. I work for a company called Michelada, like The Drink. If you've never had one, I mean, she likes a great drink that us Mexicans drink all the time. It's made with ice, clam juice, magical Mexican sauce, chili powder, salt, lime, and of course beer. And it's delicious. You should get one if you've never had one. But anyway, the name of my talk is Tips and Tricks for New Developers. I'm going to give you a little bit of context why this talk, what I decided to give this talk. So, long time ago, Galaxy Far Far Away 2009, Las Vegas, my first RailsConf. And it was a great RailsConf. Back then, I was building, I just moved onto Rails, had my first job. I was being paid to write my first Rails app. And I was building a huge e-commerce platform, but knew nothing about, you know, the real stuff. Like, once you're past, like, the tutorial phase of Rails, like, what happens next, right? And I remember that there were several talks at this Rails, at this particular RailsConf that sort of changed my view and helped me a lot. Things like solving the riddle of search, using Sphinx through Rails. Like, it made me figure out that it might not be a good idea to filter my products with SQL or do searches with, like, you know, like searches. So, I learned that there was this thing that you could use to search. We ended up using Solr, by the way, not Sphinx, but anyway, I sort of learned something new. I learned about WebRat. You probably don't remember WebRat, but it was what we used to test applications before Capybara and all this fancy new stuff that we have. But I learned about it. And then the most important one, or one of the most important ones, is I learned about Git. I was using SVN before that, and VisualSourceSafe before that. So, I learned about Git. And it was, I think it's one of my, the best docs I've ever heard. It started with Git in 60 seconds, I remember clearly. And the speakers sat there and just basically read that in less than 60 seconds. It was amazing. And then he proceeded to do the proper doc, right? And another important thing that I learned at that RailsConf is how to put, like, what was I to do once I had my application. I learned that there was this thing called mongrel, that it was our web server. I don't remember about mongrel, of course. I learned that I had to, you know, set it up on different ports. You had a process, a mongrel process that started on each of the ports. And then you had NGINX on top, or Apache on top of it, that sort of, like, did the proxying around. And then if you wanted to scale, well, you scale like that, just add up more servers and HEProxy to do your, the proxying. And you will be fine. You need more power to just add up another one of those. And that was back then, in 2009, before Puma and all this new fancy stuff that we have. So, I remember Las Vegas, right? So, I think that we still need talks for beginners at RailsConf. We do need to know how to do, like, microservices and how to handle a gazillion of requests per second and all of that. But we need talks for beginners so people can come here and learn stuff that they don't even know they needed to know, right? So, this talk is for beginners. Most of the things that you learn here, maybe you already know it, maybe not. But I do want you to talk is for beginners. And it's just based on my experience, what I do when I start a new Rails application. Like, the things that I always use, the things I usually do and all that. So, hope it helps for you. I had to remove a bunch of stuff, but this is the most important things that I think will work for you. So, let's begin. First of all, let's talk about configuration files. When you start a new project, right, you use your Rails new command, the first thing that you want to do, well, it's going to do your bundle stuff, it's going to copy files and all that. The first thing that you want to do, I consider this a courtesy to our developers, is please copy your database file into an example file and then ignore the original one. So, we can always have on hand a configuration file that we can base on. It's awful to go into a new project and then, you know, start your Rails server, you have no database jammer file, and then you realize there's nothing, you have to go Google it, paste it and all that. It's just time consuming. So, please keep an example file of your database file. It's going to pay out in the future. And do so for any other configuration file that you think that it's needed for the project to run. Please create sample files and copy them and just ignore them, ignore the real ones from Git, right? And while we're talking about configuration files, did you know that you can have as many as you want and you can separate those in different files, like, for example, you can have a payments jammer file. And then you can just call it from the application like this. Use config4 and just send the name of the file as a sim, and then you will get that particular configuration. So, you can use it to just organize your configuration files better and everyone will be happier when it's cleaner and you know exactly what kind of configuration is on each of the files. And then remember that wherever there's a string or an integer on the code that's comparing to something else, you probably want to use a constant but a setting on one of those config files. So, remember that if you see code like this in your Rails application, try to change it to something like this. Use a constant for that 30. And if you want to go, like, if you think it's going to change constantly, just move it all the way over to a configuration file. You're going to be very happy that you did this when your boss comes and says, hey, I need to change that to 10 minutes and then 15 minutes later, he's going to say, like, hey, change it to 20 minutes. This way you can, you know where to change something, just restart your server and you know you're done instead of, like, looking for that setting in the code base. Let's talk about the database. Now, this one you can't imagine on eight years of being a Rails developer. I've seen it a lot. Do not yet ignore the schema file. Please. I've been to teams where, or I've joined applications where there's no schema file and then I ask, like, what happened to it? And, ah, there were too many conflicts with it. So, we just got rid of it. Like, that's the point, you know? So, please do not ignore your schema file. It's very important that you're always able to restore your database state with either DB setup or DB reset, especially if you're new to the project. You can just go there, you know, configure your database, run one of those, and you're up and running to start coding. So, please, please do not ignore that file. It's very important that you find those conflicts and then talk to your fellow developers and say, hey, I added this column. Hey, yeah, me too. So, let's figure it out, right, instead of just ignoring it. This is a tricky one. Don't change your data in your database migrations. This is hard to achieve, so I'm going to change a little bit the tip to be careful when you change data in your database migrations. It is pretty common that you do something like this. You add a column to one of the tables that you already have, and then you decide that you want to fill it with something, maybe based on the current data that you already have, like here, right, we're splitting the code column into two columns. So, you do something like this, right, you add the new columns, you go through all the companies, you split it, and then get rid of the old column. The problem with this kind of code, first of all, is that it's not future-proof. It's not future-proof because, for example, what happens in the future, your company model is now the organization model, for example. This migration won't run anymore. And while migrations are not supposed to last that long, they're just, you know, they help you to keep track of history, of how the database evolved. Your schema RB file is the one that's supposed to have, like, the real data structure, database structure, and the database structure, it's still nice to, sort of, try to keep it as coherent as possible. The other problem that you might find with this kind of code is that you can't, you know, have longer deploy times. It's very, very common that you are, you know, on development mode and you run this migration and it runs really fast, but you forgot that there's, like, three million companies in your database. So now it's going through all of them in production, and, you know, it's doing all of that, and you can't, like, your database is in a weird state. Maybe there's more migrations that are coming, and the site is, can't run without those migrations, so you're doing maintenance mode or whatever and your boss is angry because it's taking a long. And you forgot about the three million rows. So try not to do that. You're risking downtime, basically, if you're changing your data and your migrations. And the other one, so this code, for example, this is going to happen in production, I guarantee it. You forgot that maybe code is nil, so it blows up and now, you know, you're stuck with a migration weird state on the database and everyone's yelling at you because you have to log into the server, change that code real quick, run the migrations again. I've been there, so it's a really bad idea to do this. So one way to fix it, prefer SQL over Ruby. If you're gonna do it, you're gonna be careful, but if you're gonna do it, you might be better off like this. Do your thing, update, you know, use regular SQL to do your updates and get, move on, right? This is faster, of course, because it's not iterating through all of the objects, it's not instantating anything, so it's just updating whatever needs to be done. If there's nil, it's not gonna blow up, so this is way faster. So try to think your changes in data, a SQL, and prefer this. It's gonna be safer to do this. But the best thing to do, in my opinion, is to use a gem like this, Rails data migrations. There's a lot of gems that do the same thing, but I think this is the best one, because it works with Rails 5, by the way. And this gem is gonna give you a different set of break tasks for your data migrations, right? So, for example, if you had this regular migration, once you have the gem, you're adding a column and then doing an update on all the records on the table. What you would do, in this case, is create a data migration, you know, set authors active. It will create a special migration in a different folder, and then in that migration, you will add your data changes, right? So you don't need them anymore on the regular migration. And now, when you deploy, you will run first your database migrations that will change the structure, and then with a different rake task, you will run your data migrations. So it's a separate process, and it makes everything cleaner. And it also keeps track of how data is changing using the same, like, the timestamp that the database migration uses. So this is way better. And if you don't want to use a gem, at least maybe first make all the migrations that change the structure, and then add migrations later to change the data, right? Let's talk about background jobs. It's pretty useful, to say, to use background jobs. You have something in place like SADKIC, Rescue, DelayJob. I still used DelayJob a couple of months ago. And what I notice is that it's a, regularly, a bad idea to pass objects to your methods that go in the background. There's a few things that can go wrong. But what I mean is this. Let's say you have a job class that has this perform method, and you probably want to do this, right? You have an order and a user, and you're going to assign it to it. What I mean is that it's better if you do this. Just pass the IDs, then find again your objects on the job, and just do whatever needs to be done. The problem with using objects is that they're usually converted into Jamel, and they end up being, like, huge strings that if you're not careful, and there's special characters in the description field or something like that, it just makes everything blow up. And you would not notice until you see, like, all the alerts coming up. So it's better if you just use the ID. It's smaller to just, you know, pass an integer around instead of a whole object as Jamel. And it's just going to be better. It doesn't matter in terms of performance, because it's already on the background, so just let it do it, right? And speaking of background jobs, always when you start a new application, always, always deliver your email later. Don't wait until, you know, your first SMTP authentication error happens and then makes your checkout blow up, because you were expecting the checkout to send the email after payment was completed or something like that. Always, when you start, you start thinking about delivering your email later, always. And the same rule applies for mailers. Instead of passing objects, try to pass IDs and just pull them over from the code on the mailer, right? This way, even if you don't have anything in place right now to sort of delay the sending of the mailers, in the end, you're just going to need to add that delay method if you're using Sidekick or DelayJob or if you're using ActiveJob, just use the deliver later, and that will be it, but use the integers. Don't use the objects for the same reasons as the background jobs, okay? Mmm, let's talk about rest. This is my favorite lesson for all new developers. You have to be restful all the time. Rest is like the core of Rails and MBC and everything that you're doing, and it's simpler. It's very simple to sort of explain, but it's hard to, like, actually implement it. Let me tell you why. Rest, to me, it means that on your controllers, you only have these actions. Nothing more. Actions should always be index, show, new, create, edit, update, or delete. No other action, but it's pretty common to find in code bases things like this, right? You have the products controller, and then you have an action to deactivate the product, and you create your route, and you just get, and member, whatever, right? This is wrong. This is not restful. When you think about restful, you should think that for every request, there's a something, a resource that's changing. So in this case, when you're deactivating the product, what's changing, it's the product state. So the correct thing to do here is to create a product state controller, and you're updating it, right? This is more restful, much more restful. For example, if you have a shopping cart, right? Instead of having an action to apply a coupon, what's happening? You are creating a discount, or a shopping cart discount. So create a controller for the discount, and you are creating it. This is restful, right? This is very common. If you have contacts, you are... you have a search, so you create a search action. Wrong. That's totally wrong. You create the contacts search controller, search as controller, and then you have an action for that search. This is restful, right? You have something that is changing because that's what restful is supposed to be. So the way to make sure that you're complying with this rule, it's very easy. Just don't have controller actions that are not on that list. It's always index, show, edit, new, create, update, or delete. That's it. If you have an action that's named differently, wrong. Right? Okay. Now, a few Ruby gems that I think must be on all projects. I find them useful. I always add them, so I hope this helps for you too. This one you probably heard of a lot, Ruboka. Ruboka, it's going to analyze your code. It's going to check how it's written, and it's going to tell you where you're doing things right and when you're doing things wrong. And it's automated, so it's pretty cool. Instead of having someone yelling at you, it's Ruboka showing you. Better teachers than humans, trust me. A very common excuse that I've heard about not using Ruboka in your project is because you're already, you know, you have a large application, you're already, it's been two years since development. If you add it right now, there's going to be like 500 errors and you don't have the time to fix them. That's okay. What you can do is you can add this, run it with this option, Auto Gen Config, and it's going to create a RuboCop2do.jammel file that's going to include an exception for everything that it found. So that way, you just add it to your, as a sort of an include file to your main RuboCop file, and that way, you have like a sort of a clean slate at that point in time, and then you are supposed to come back later. That's why it's called a to-do file. And remove all those exceptions and fix them. That's what you're supposed to do. You probably won't, but it's fine, right? At least from that moment, like for example, right there, it's green, at least from that moment on, if there's something like, if you write bad RubiCode, it's going to tell you starting from there, instead of trying to fix all other like 500 or whatever errors you find. Out of GenConfigure also helps for a new project, so you can like pull configurations that you might use, like change the rules, depending on your style. For example, there's this one where it configures RuboCop2 how many columns, how many characters you see per line. I usually have it at 80, 90, you can set it to 130. I know there's people that say, we have large monitors, like why do we need this? The thing is that your vision is only, like, it's really narrow, so it's better if you have less characters to read at once. You just have to like sort of nest code around, so it looks better if you try to remove the characters on your lines. Try that one. This one, style and documentation, I usually move it to the main file because I'm not going to write comments on all my classes or methods or anything, so I just get rid of it, no one has time for that, right? And this one, I think it's important, this is the one I value the most about RuboCop, the metrics method length, it forces you to make methods that are no longer than 10 lines. It's hard to, you know, comply with this one, but if you do, your code will be so much cleaner and so much readable, so trust me, try this one. I'll allow you, if you go to 12 or 13 lines, that's fine, but don't go over that. But, you know, forcing your methods to be 10 statements and that's it, helps you, like, clean up your code base. It's gonna, you know, you're supposed to try to abstract all the, like, the code into smaller methods and then test those, unit testing, that's why I call unit testing. So keeping this one, it's like, really, it's gonna make your code so much readable and so much better. And then if you want to run this before you push code to your, to Git, you can use a hook. If you add that file,.git, slash hooks, slash pre-push, it's gonna run Rubikop before it actually pushes the code to the repo, and if it fails, then the push will be canceled. So that way you can just push Rubikop, failed, oh, I have to fix this first, fix whatever offense you have and then push it over. It's very useful, for example, us, we have a CI server that actually runs Rubikop, and our repos are filled with comments that, you know, read, like, fix that Rubikop thing. That Rubikop, because the build fails when Rubikop fails. So it's usual to push, wait for the CI server, fail, why, because, you know, you, you, maybe you went over with the characters or whatnot, so you have to make a commit that only fixes that, fRubikop, dammit Rubikop, there's a lot of commits like this on our repos. So what I tell the guys is just use a hook, so, you know, you run Rubikop before actually pushing, and if it doesn't pass, then you won't push, and you can fix it, and not curse at it. Annotate, this is an R gem that I don't see often, and I don't know why, but I love it. Annotate, what it does is, let's say that you have a, like, a model user with name, username, password, active, whatever. When you run Annotate on a Rails project, well, after you do your migrations, what it's gonna do, it's gonna, well, annotate your models with information about the database, automatically, basically. So if you add columns, you just run Annotate again, and it's gonna add that information at the top of your classes, and it's gonna do so for models, unit test files, and factories if you use. So it works as a reference, a quick reference if you are working on a model about the columns that it has, instead of, you know, going to the database or checking schema or whatnot, you just have it right there at the top of the model, and you can see it real quick. It's pretty useful to have these annotations handy. And this one is pretty useful too. If you use routes as an option, then it will annotate your routes file. So you don't have to rake routes every time you need to figure out where my controller should go. You will already have it. And if you're very old like me and use VI as your text editor, you're gonna tank that it has like contextual autocomplete. So it basically autocompletes only on what's open, so you open your routes file, and you have autocomplete for all those path methods. So it's pretty cool. Very useful. But I don't know why people don't use it. So now you know, please use it, Annotate. Very useful. Bullet. Bullet detects the N plus 1 problem as it's happening, as you're developing. If you don't know what the N plus 1 problem is, it's very common in Rails, but it's something like this. So let's say you have a book method that belongs to author, has many comments, then you have the author that has, you know, name, whatever, and then you have the comment that belongs to user, belongs to book, and your index page looks like this. So when you go to this page, the controller usually looks like this probably, and then when you look at that page, your log file will look like this. There's a bunch of queries going on, like three queries, four queries per row, and you know, it's just getting all the objects one by one because that's what you told Rails to do. It doesn't know what else to do. So this is called the N plus 1 problem. It's very common when you're developing Rails application. So if you use bullet and you configure it, let's say for example, what I'm doing here is, well, enabling it. I want it to show on the console, I want it to show on the Rails logs, and to add the footer, what happens is, as you load that page, you will notice that there is a footer that says, hey, you know, you're probably better off if you include the author on the query or if you include the comments on the query. And it's going to gel at you from the console to, from the Rails logger, right? It's going to tell you, hey, you know, you're doing something weird here, so why don't you fix it? And you're going to go, oh, okay, yeah, let me fix it. So you go to your controller, you use includes properly, you nest it as needed, and then when you load your page, you will now have, you know, the queries for each of the classes. You don't have, like, a bunch of microquery. So this is way better at M-Bullet, you know, we just tell you as soon as you're developing that you're doing something not wrong, but maybe weird. And another similar gem, point. This detect memory leaks before it's too late. I don't know if you've worked with Rails applications that have memory leaks. You have a memory leak when your applications start growing, like, I don't know, 1.2 gigs in RAM, and then you need to restart. Actually, that's the best way to fix memory leaks on Rails applications, just set up Monit, and if it goes past the threshold, just restart the server, done, right? Because it's so hard to find memory leaks on the code on Rails, it's very, very hard. Once it's there, it's not gone ever, like, you're stuck with it, deal with it, deal with it, basically. That's a solution. So Oink, when you have it on your code base, and you, it's some sort of middleware, so you initialize it, and it's gonna add at the bottom of your logs, like, when you're developing disinformation, which is basically how much memory it's using, and the number of objects that you are instantiating in that request. So if you're developing something like this, and you see that you have, like, 500 comment objects instantiated, something must be wrong, right? There's something wrong going on. And it's actually kind of safe to use in production. I wouldn't enable it all the time, but if you're sort of trying to figure out where the problem is, I wouldn't enable it, and then just let it log a few requests and try to find where I'm instantiating a lot of objects. So it's very useful for that. And, wow, right on the 30 minutes. That's it. That's all I have for you right now. Like I said, I had to remove a bunch of them of, like, advice, but this is, like, what I thought was most important. And that's it. Thank you. Thank you.
 Welcome.  My name is David.  You can find me on the internet as David, Twitter, GitHub.  I work for a company called Michelada, like The Drink.  If you've never had one, I mean, she likes a great drink that us Mexicans drink all the time.  It's made with ice, clam juice, magical Mexican sauce, chili powder, salt, lime, and of course beer.  And it's delicious. You should get one if you've never had one.  But anyway, the name of my talk is Tips and Tricks for New Developers.  I'm going to give you a little bit of context why this talk, what I decided to give this talk.  So, long time ago, Galaxy Far Far Away 2009, Las Vegas, my first RailsConf.  And it was a great RailsConf.  Back then, I was building, I just moved onto Rails, had my first job.  I was being paid to write my first Rails app.  And I was building a huge e-commerce platform, but knew nothing about, you know, the real stuff.  Like, once you're past, like, the tutorial phase of Rails, like, what happens next, right?  And I remember that there were several talks at this Rails, at this particular RailsConf  that sort of changed my view and helped me a lot.  Things like solving the riddle of search, using Sphinx through Rails.  Like, it made me figure out that it might not be a good idea to filter my products with SQL  or do searches with, like, you know, like searches.  So, I learned that there was this thing that you could use to search.  We ended up using Solr, by the way, not Sphinx, but anyway, I sort of learned something new.  I learned about WebRat.  You probably don't remember WebRat, but it was what we used to test applications before  Capybara and all this fancy new stuff that we have.  But I learned about it.  And then the most important one, or one of the most important ones, is I learned about Git.  I was using SVN before that, and VisualSourceSafe before that.  So, I learned about Git.  And it was, I think it's one of my, the best docs I've ever heard.  It started with Git in 60 seconds, I remember clearly.  And the speakers sat there and just basically read that in less than 60 seconds.  It was amazing.  And then he proceeded to do the proper doc, right?  And another important thing that I learned at that RailsConf is how to put, like, what was I to do once I had my application.  I learned that there was this thing called mongrel, that it was our web server.  I don't remember about mongrel, of course.  I learned that I had to, you know, set it up on different ports.  You had a process, a mongrel process that started on each of the ports.  And then you had NGINX on top, or Apache on top of it, that sort of, like, did the proxying around.  And then if you wanted to scale, well, you scale like that, just add up more servers and HEProxy to do your, the proxying.  And you will be fine.  You need more power to just add up another one of those.  And that was back then, in 2009, before Puma and all this new fancy stuff that we have.  So, I remember Las Vegas, right?  So, I think that we still need talks for beginners at RailsConf.  We do need to know how to do, like, microservices and how to handle a gazillion of requests per second and all of that.  But we need talks for beginners so people can come here and learn stuff that they don't even know they needed to know, right?  So, this talk is for beginners.  Most of the things that you learn here, maybe you already know it, maybe not.  But I do want you to talk is for beginners.  And it's just based on my experience, what I do when I start a new Rails application.  Like, the things that I always use, the things I usually do and all that.  So, hope it helps for you.  I had to remove a bunch of stuff, but this is the most important things that I think will work for you.  So, let's begin.  First of all, let's talk about configuration files.  When you start a new project, right, you use your Rails new command,  the first thing that you want to do, well, it's going to do your bundle stuff, it's going to copy files and all that.  The first thing that you want to do, I consider this a courtesy to our developers,  is please copy your database file into an example file and then ignore the original one.  So, we can always have on hand a configuration file that we can base on.  It's awful to go into a new project and then, you know, start your Rails server, you have no database jammer file,  and then you realize there's nothing, you have to go Google it, paste it and all that.  It's just time consuming.  So, please keep an example file of your database file.  It's going to pay out in the future.  And do so for any other configuration file that you think that it's needed for the project to run.  Please create sample files and copy them and just ignore them,  ignore the real ones from Git, right?  And while we're talking about configuration files, did you know that you can have as many as you want  and you can separate those in different files, like, for example,  you can have a payments jammer file.  And then you can just call it from the application like this.  Use config4 and just send the name of the file as a sim,  and then you will get that particular configuration.  So, you can use it to just organize your configuration files better  and everyone will be happier when it's cleaner and you know exactly what kind of configuration is on each of the files.  And then remember that wherever there's a string or an integer on the code  that's comparing to something else, you probably want to use a constant  but a setting on one of those config files.  So, remember that if you see code like this in your Rails application,  try to change it to something like this.  Use a constant for that 30.  And if you want to go, like, if you think it's going to change constantly,  just move it all the way over to a configuration file.  You're going to be very happy that you did this when your boss comes and says,  hey, I need to change that to 10 minutes and then 15 minutes later,  he's going to say, like, hey, change it to 20 minutes.  This way you can, you know where to change something, just restart your server  and you know you're done instead of, like, looking for that setting in the code base.  Let's talk about the database.  Now, this one you can't imagine on eight years of being a Rails developer.  I've seen it a lot.  Do not yet ignore the schema file.  Please.  I've been to teams where, or I've joined applications where there's no schema file  and then I ask, like, what happened to it?  And, ah, there were too many conflicts with it.  So, we just got rid of it.  Like, that's the point, you know?  So, please do not ignore your schema file.  It's very important that you're always able to restore your database state  with either DB setup or DB reset,  especially if you're new to the project.  You can just go there, you know, configure your database, run one of those,  and you're up and running to start coding.  So, please, please do not ignore that file.  It's very important that you find those conflicts  and then talk to your fellow developers and say, hey, I added this column.  Hey, yeah, me too.  So, let's figure it out, right, instead of just ignoring it.  This is a tricky one.  Don't change your data in your database migrations.  This is hard to achieve, so I'm going to change a little bit the tip  to be careful when you change data in your database migrations.  It is pretty common that you do something like this.  You add a column to one of the tables that you already have,  and then you decide that you want to fill it with something,  maybe based on the current data that you already have,  like here, right, we're splitting the code column into two columns.  So, you do something like this, right, you add the new columns,  you go through all the companies, you split it,  and then get rid of the old column.  The problem with this kind of code, first of all, is that it's not future-proof.  It's not future-proof because, for example, what happens in the future,  your company model is now the organization model, for example.  This migration won't run anymore.  And while migrations are not supposed to last that long,  they're just, you know, they help you to keep track of history,  of how the database evolved.  Your schema RB file is the one that's supposed to have,  like, the real data structure, database structure,  and the database structure, it's still nice to, sort of,  try to keep it as coherent as possible.  The other problem that you might find with this kind of code  is that you can't, you know, have longer deploy times.  It's very, very common that you are, you know, on development mode  and you run this migration and it runs really fast,  but you forgot that there's, like,  three million companies in your database.  So now it's going through all of them in production,  and, you know, it's doing all of that,  and you can't, like, your database is in a weird state.  Maybe there's more migrations that are coming,  and the site is, can't run without those migrations,  so you're doing maintenance mode or whatever  and your boss is angry because it's taking a long.  And you forgot about the three million rows.  So try not to do that.  You're risking downtime, basically,  if you're changing your data and your migrations.  And the other one, so this code, for example,  this is going to happen in production, I guarantee it.  You forgot that maybe code is nil, so it blows up  and now, you know, you're stuck with a migration weird state  on the database and everyone's yelling at you  because you have to log into the server,  change that code real quick, run the migrations again.  I've been there, so it's a really bad idea to do this.  So one way to fix it, prefer SQL over Ruby.  If you're gonna do it, you're gonna be careful,  but if you're gonna do it, you might be better off like this.  Do your thing, update, you know,  use regular SQL to do your updates and get, move on, right?  This is faster, of course, because it's not iterating through  all of the objects, it's not instantating anything,  so it's just updating whatever needs to be done.  If there's nil, it's not gonna blow up, so this is way faster.  So try to think your changes in data, a SQL, and prefer this.  It's gonna be safer to do this.  But the best thing to do, in my opinion,  is to use a gem like this, Rails data migrations.  There's a lot of gems that do the same thing,  but I think this is the best one,  because it works with Rails 5, by the way.  And this gem is gonna give you a different set of break tasks  for your data migrations, right?  So, for example, if you had this regular migration,  once you have the gem, you're adding a column  and then doing an update on all the records on the table.  What you would do, in this case, is create a data migration,  you know, set authors active.  It will create a special migration in a different folder,  and then in that migration, you will add your data changes, right?  So you don't need them anymore on the regular migration.  And now, when you deploy, you will run first  your database migrations that will change the structure,  and then with a different rake task,  you will run your data migrations.  So it's a separate process, and it makes everything cleaner.  And it also keeps track of how data is changing  using the same, like, the timestamp that the database  migration uses.  So this is way better.  And if you don't want to use a gem,  at least maybe first make all the migrations that change  the structure, and then add migrations later  to change the data, right?  Let's talk about background jobs.  It's pretty useful, to say, to use background jobs.  You have something in place like SADKIC, Rescue, DelayJob.  I still used DelayJob a couple of months ago.  And what I notice is that it's a,  regularly, a bad idea to pass objects to your methods  that go in the background.  There's a few things that can go wrong.  But what I mean is this.  Let's say you have a job class that has this perform method,  and you probably want to do this, right?  You have an order and a user, and you're going to assign it to it.  What I mean is that it's better if you do this.  Just pass the IDs, then find again your objects on the job,  and just do whatever needs to be done.  The problem with using objects is that they're usually converted  into Jamel, and they end up being, like, huge strings  that if you're not careful, and there's special characters  in the description field or something like that,  it just makes everything blow up.  And you would not notice until you see, like,  all the alerts coming up.  So it's better if you just use the ID.  It's smaller to just, you know, pass an integer around  instead of a whole object as Jamel.  And it's just going to be better.  It doesn't matter in terms of performance,  because it's already on the background,  so just let it do it, right?  And speaking of background jobs,  always when you start a new application,  always, always deliver your email later.  Don't wait until, you know, your first SMTP authentication error  happens and then makes your checkout blow up,  because you were expecting the checkout to send the email  after payment was completed or something like that.  Always, when you start, you start thinking  about delivering your email later, always.  And the same rule applies for mailers.  Instead of passing objects, try to pass IDs  and just pull them over from the code on the mailer, right?  This way, even if you don't have anything in place right now  to sort of delay the sending of the mailers,  in the end, you're just going to need to add that delay method  if you're using Sidekick or DelayJob  or if you're using ActiveJob, just use the deliver later,  and that will be it, but use the integers.  Don't use the objects for the same reasons  as the background jobs, okay?  Mmm, let's talk about rest.  This is my favorite lesson for all new developers.  You have to be restful all the time.  Rest is like the core of Rails and MBC  and everything that you're doing, and it's simpler.  It's very simple to sort of explain,  but it's hard to, like, actually implement it.  Let me tell you why.  Rest, to me, it means that on your controllers,  you only have these actions.  Nothing more.  Actions should always be index, show,  new, create, edit, update, or delete.  No other action, but it's pretty common  to find in code bases things like this, right?  You have the products controller,  and then you have an action to deactivate the product,  and you create your route, and you just get,  and member, whatever, right?  This is wrong.  This is not restful.  When you think about restful,  you should think that for every request,  there's a something, a resource that's changing.  So in this case, when you're deactivating the product,  what's changing, it's the product state.  So the correct thing to do here  is to create a product state controller,  and you're updating it, right?  This is more restful, much more restful.  For example, if you have a shopping cart, right?  Instead of having an action to apply a coupon,  what's happening?  You are creating a discount, or a shopping cart discount.  So create a controller for the discount,  and you are creating it.  This is restful, right?  This is very common.  If you have contacts, you are...  you have a search, so you create a search action.  Wrong.  That's totally wrong.  You create the contacts search controller,  search as controller,  and then you have an action for that search.  This is restful, right?  You have something that is changing  because that's what restful is supposed to be.  So the way to make sure that you're complying with this rule,  it's very easy.  Just don't have controller actions  that are not on that list.  It's always index, show, edit, new, create, update,  or delete.  That's it.  If you have an action that's named differently, wrong.  Right?  Okay.  Now, a few Ruby gems that I think must be on all projects.  I find them useful.  I always add them,  so I hope this helps for you too.  This one you probably heard of a lot, Ruboka.  Ruboka, it's going to analyze your code.  It's going to check how it's written,  and it's going to tell you where you're doing things right  and when you're doing things wrong.  And it's automated, so it's pretty cool.  Instead of having someone yelling at you,  it's Ruboka showing you.  Better teachers than humans, trust me.  A very common excuse that I've heard about not using Ruboka  in your project is because you're already, you know,  you have a large application, you're already,  it's been two years since development.  If you add it right now, there's going to be like 500 errors  and you don't have the time to fix them.  That's okay.  What you can do is you can add this, run it with this option,  Auto Gen Config,  and it's going to create a RuboCop2do.jammel file  that's going to include an exception for everything that it found.  So that way, you just add it to your,  as a sort of an include file to your main RuboCop file,  and that way, you have like a sort of a clean slate  at that point in time,  and then you are supposed to come back later.  That's why it's called a to-do file.  And remove all those exceptions and fix them.  That's what you're supposed to do.  You probably won't, but it's fine, right?  At least from that moment, like for example, right there,  it's green, at least from that moment on,  if there's something like, if you write bad RubiCode,  it's going to tell you starting from there,  instead of trying to fix all other like 500 or whatever errors you find.  Out of GenConfigure also helps for a new project,  so you can like pull configurations that you might use,  like change the rules, depending on your style.  For example, there's this one where it configures RuboCop2  how many columns, how many characters you see per line.  I usually have it at 80, 90, you can set it to 130.  I know there's people that say, we have large monitors,  like why do we need this?  The thing is that your vision is only, like, it's really narrow,  so it's better if you have less characters to read at once.  You just have to like sort of nest code around,  so it looks better if you try to remove the characters on your lines.  Try that one.  This one, style and documentation,  I usually move it to the main file because I'm not going to write comments  on all my classes or methods or anything,  so I just get rid of it,  no one has time for that, right?  And this one, I think it's important,  this is the one I value the most about RuboCop,  the metrics method length,  it forces you to make methods that are no longer than 10 lines.  It's hard to, you know, comply with this one,  but if you do, your code will be so much cleaner  and so much readable,  so trust me, try this one.  I'll allow you, if you go to 12 or 13 lines, that's fine,  but don't go over that.  But, you know, forcing your methods to be 10 statements  and that's it, helps you, like, clean up your code base.  It's gonna, you know, you're supposed to try to abstract  all the, like, the code into smaller methods  and then test those, unit testing,  that's why I call unit testing.  So keeping this one, it's like, really,  it's gonna make your code so much readable and so much better.  And then if you want to run this before you push code  to your, to Git, you can use a hook.  If you add that file,.git, slash hooks, slash pre-push,  it's gonna run Rubikop before it actually pushes the code  to the repo, and if it fails, then the push will be canceled.  So that way you can just push Rubikop, failed,  oh, I have to fix this first, fix whatever offense you have  and then push it over.  It's very useful, for example, us, we have a CI server  that actually runs Rubikop, and our repos are filled  with comments that, you know, read, like, fix that Rubikop thing.  That Rubikop, because the build fails when Rubikop fails.  So it's usual to push, wait for the CI server,  fail, why, because, you know, you, you,  maybe you went over with the characters or whatnot,  so you have to make a commit that only fixes that,  fRubikop, dammit Rubikop, there's a lot of commits like this  on our repos.  So what I tell the guys is just use a hook,  so, you know, you run Rubikop before actually pushing,  and if it doesn't pass, then you won't push,  and you can fix it, and not curse at it.  Annotate, this is an R gem that I don't see often,  and I don't know why, but I love it.  Annotate, what it does is,  let's say that you have a, like, a model user  with name, username, password, active, whatever.  When you run Annotate on a Rails project,  well, after you do your migrations,  what it's gonna do, it's gonna, well,  annotate your models with information about the database,  automatically, basically.  So if you add columns, you just run Annotate again,  and it's gonna add that information  at the top of your classes,  and it's gonna do so for models,  unit test files, and factories if you use.  So it works as a reference, a quick reference  if you are working on a model about the columns that it has,  instead of, you know, going to the database  or checking schema or whatnot,  you just have it right there at the top of the model,  and you can see it real quick.  It's pretty useful to have these annotations handy.  And this one is pretty useful too.  If you use routes as an option,  then it will annotate your routes file.  So you don't have to rake routes every time you need to  figure out where my controller should go.  You will already have it.  And if you're very old like me and use VI as your text editor,  you're gonna tank that it has like contextual autocomplete.  So it basically autocompletes only on what's open,  so you open your routes file,  and you have autocomplete for all those path methods.  So it's pretty cool. Very useful.  But I don't know why people don't use it.  So now you know, please use it, Annotate. Very useful.  Bullet.  Bullet detects the N plus 1 problem as it's happening,  as you're developing.  If you don't know what the N plus 1 problem is,  it's very common in Rails, but it's something like this.  So let's say you have a book method that belongs to author,  has many comments,  then you have the author that has, you know, name, whatever,  and then you have the comment that belongs to user,  belongs to book, and your index page looks like this.  So when you go to this page,  the controller usually looks like this probably,  and then when you look at that page,  your log file will look like this.  There's a bunch of queries going on,  like three queries, four queries per row,  and you know, it's just getting all the objects one by one  because that's what you told Rails to do.  It doesn't know what else to do.  So this is called the N plus 1 problem.  It's very common when you're developing Rails application.  So if you use bullet and you configure it,  let's say for example, what I'm doing here is, well, enabling it.  I want it to show on the console,  I want it to show on the Rails logs,  and to add the footer, what happens is,  as you load that page, you will notice that there is a footer  that says, hey, you know, you're probably better off  if you include the author on the query  or if you include the comments on the query.  And it's going to gel at you from the console to,  from the Rails logger, right?  It's going to tell you, hey, you know,  you're doing something weird here, so why don't you fix it?  And you're going to go, oh, okay, yeah, let me fix it.  So you go to your controller, you use includes properly,  you nest it as needed,  and then when you load your page,  you will now have, you know, the queries for each of the classes.  You don't have, like, a bunch of microquery.  So this is way better at M-Bullet, you know,  we just tell you as soon as you're developing  that you're doing something not wrong, but maybe weird.  And another similar gem, point.  This detect memory leaks before it's too late.  I don't know if you've worked with Rails applications  that have memory leaks.  You have a memory leak when your applications start growing,  like, I don't know, 1.2 gigs in RAM,  and then you need to restart.  Actually, that's the best way to fix memory leaks  on Rails applications, just set up Monit,  and if it goes past the threshold,  just restart the server, done, right?  Because it's so hard to find memory leaks on the code on Rails,  it's very, very hard.  Once it's there, it's not gone ever,  like, you're stuck with it, deal with it, deal with it, basically.  That's a solution.  So Oink, when you have it on your code base,  and you, it's some sort of middleware,  so you initialize it,  and it's gonna add at the bottom of your logs,  like, when you're developing disinformation,  which is basically how much memory it's using,  and the number of objects that you are instantiating  in that request.  So if you're developing something like this,  and you see that you have, like,  500 comment objects instantiated,  something must be wrong, right?  There's something wrong going on.  And it's actually kind of safe to use in production.  I wouldn't enable it all the time,  but if you're sort of trying to figure out where the problem is,  I wouldn't enable it,  and then just let it log a few requests  and try to find where I'm instantiating a lot of objects.  So it's very useful for that.  And, wow, right on the 30 minutes.  That's it. That's all I have for you right now.  Like I said, I had to remove a bunch of them  of, like, advice,  but this is, like, what I thought was most important.  And that's it. Thank you.  Thank you.
Tricks_and_treats_for_new_developers_2_0_803.png Tricks_and_treats_for_new_developers_2_804_1535.png Tricks_and_treats_for_new_developers_2_1536_1595.png Tricks_and_treats_for_new_developers_2_1596_1727.png Tricks_and_treats_for_new_developers_2_1728_2567.png Tricks_and_treats_for_new_developers_2_2568_3959.png Tricks_and_treats_for_new_developers_2_3960_4103.png Tricks_and_treats_for_new_developers_2_4104_5099.png Tricks_and_treats_for_new_developers_2_5100_6935.png Tricks_and_treats_for_new_developers_2_6936_7127.png Tricks_and_treats_for_new_developers_2_7128_7259.png Tricks_and_treats_for_new_developers_2_7260_7331.png Tricks_and_treats_for_new_developers_2_7332_7439.png Tricks_and_treats_for_new_developers_2_7440_7559.png Tricks_and_treats_for_new_developers_2_7560_11027.png Tricks_and_treats_for_new_developers_2_11028_11291.png Tricks_and_treats_for_new_developers_2_11292_12695.png Tricks_and_treats_for_new_developers_2_12696_15143.png Tricks_and_treats_for_new_developers_2_15144_16847.png Tricks_and_treats_for_new_developers_2_16848_17927.png Tricks_and_treats_for_new_developers_2_17928_19211.png Tricks_and_treats_for_new_developers_2_19212_22571.png Tricks_and_treats_for_new_developers_2_22572_24191.png Tricks_and_treats_for_new_developers_2_24192_24479.png Tricks_and_treats_for_new_developers_2_24480_26879.png Tricks_and_treats_for_new_developers_2_26880_27203.png Tricks_and_treats_for_new_developers_2_27204_28163.png Tricks_and_treats_for_new_developers_2_28164_29771.png Tricks_and_treats_for_new_developers_2_29772_30335.png Tricks_and_treats_for_new_developers_2_30336_30419.png Tricks_and_treats_for_new_developers_2_30420_30491.png Tricks_and_treats_for_new_developers_2_30492_30563.png Tricks_and_treats_for_new_developers_2_30564_31559.png Tricks_and_treats_for_new_developers_2_31560_32303.png Tricks_and_treats_for_new_developers_2_32304_32903.png Tricks_and_treats_for_new_developers_2_32904_33083.png Tricks_and_treats_for_new_developers_2_33084_35759.png Tricks_and_treats_for_new_developers_2_35760_36803.png Tricks_and_treats_for_new_developers_2_36804_37199.png Tricks_and_treats_for_new_developers_2_37200_37271.png Tricks_and_treats_for_new_developers_2_37272_37631.png Tricks_and_treats_for_new_developers_2_37632_38351.png Tricks_and_treats_for_new_developers_2_38352_39827.png Tricks_and_treats_for_new_developers_2_39828_40871.png Tricks_and_treats_for_new_developers_2_40872_43163.png Tricks_and_treats_for_new_developers_2_43164_44243.png Tricks_and_treats_for_new_developers_2_44244_44699.png Tricks_and_treats_for_new_developers_2_44700_45611.png Tricks_and_treats_for_new_developers_2_45612_46043.png Tricks_and_treats_for_new_developers_2_46044_46187.png Tricks_and_treats_for_new_developers_2_46188_46228.png