(exciting instrumental music) - Welcome. My name is David. You can find me on the internet
as @dabit Twitter, Github. I work for a company called Michelada like the drink. If you've never had one, a
michelada is 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. Anyway, the name of my talk is tips and tricks for new developers. I'm gonna give you a little bit of context why I decided to give this talk. Long time ago, galaxy far, far away, 2009, Las Vegas, my first RailsConf. It was great RailsConf. Back then I was building, I just moved on to
Rails, had my first job, I was being paid to
write my first Rails app. I was building a huge e-commerce platform but knew nothing about the real stuff. Once you're past the
tutorial phase of Rails, like, what happens next, right? I remembered that there were several talks at this particular
RailsConf that, sort of, changed my view and helped me a lot. Things like solving the riddle of search, using Sphinx with Rails. It made me figure out that
it might not be a good idea to filter my products
with SQL or do searches with like, like searches. I learned that there was this thing that you could use to search. We ended up using Solar,
by the way, not Sphinx. But anyway, I sort of learned something. 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 Visual SourceSafe before that. So I learned about Git and it was a, I think it's one of my, the
best talks I've ever heard. It started with Git in 60
seconds, I remember clearly. And the speaker sat there
and just basically read that in less than 60 seconds, it was amazing. And then he proceeded to
do the proper talk, 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 a web server,
remember about Mongrel of course. I learned that I had to set
it up in different ports. You had a process, a
Mongrel process that started in each of the port, 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, because added more
servers, and HA proxy to do the proxying and you will be fine. You needed more power, you just
added 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 that
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 warn you that this talk is for beginners. And It's just based on
my experience, what I do when I start a new Rails application, like things that I always
use, things that I usually do, and all of 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 wanna do ... Well it's gonna do like your bundle stuff, it's gonna copy files and all that, but first thing you wanna 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 start your rail server, you have no database yml file, and then you realize there's nothing, you have to go google it, paste it, and it's just time consuming. So please keep an example
file of your database file, it's gonna 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. And while we're talking
about configuration files, did you know that you can
have as many as you want, that you can separate
those in different files. Like for example, you can
have a payment yml file, and then you can just call it from the application like
this, you use config for, 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 when you shut the file. And then remember that
wherever there's a string or an integer in the code that's comparing to something else, you
probably want to use a constant or 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
gonna change constantly, just move it all the way
over to a configuration file. You're gonna be very
happy that you did this when your boss comes and say, hey I need to change that to 10 minutes. And then 15 minutes later
he's gonna say like, hey change it to 20 minutes. This way 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 a lot. Do not Git 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 asked like, what happened to it. And, there were to many conflicts with it, so we just got rid of it. (laughter in audience) That's the point, so please do
not ignore your schema file. It's very important that
you always able to restore your database state with
either db setup or db reset, especially if you are new to the project. You can just go there,
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, yeah me too, so let's figure it out, instead of just ignoring it. This a tricky one. Don't change your data in
your database migrations. This is hard to achieve, so
I'm gonna 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
wanna 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 if 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 the real 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 have longer deploy times. It's very very common
that you are, you know, in developing 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 are coming and the site can't run
without those migrations. So you are doing maintenance
mode or whatever, and your boss is angry
because it's taking long, and you forgot about
the three million row, so try not to do that. So you're risking down time basically, you're changing your
data in your migrations. And the other one, so
this code for example, this is gonna 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 really, 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, use
regular SQL to do your updates, and move on right. This is faster of course because
it's not hydrating through all of the objects and not
instantiating 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 as 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 five right away. This gem is gonna give you a
different set of rake 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
all on all the records on that table. What you would do in this case
is create a data migration, you know, set authors at active. It will create a special
migration in a different folder. And then, in that migration
you will add your data changes, so you don't need them anymore
in the regular migration. And now, when you deploy,
you would 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 timestamp that
the database migration used. 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. Let's talk about background jobs. It's pretty useful at this
age to use background jobs, you have something in place like Sidekiq, Resque, delayed_job. I still use delayed_job
a couple months ago. And what I noticed is that
it's a regularly a bad idea to pass objects through 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 gonna 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 Jamo, 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 will not know it
isn't it until you see like all the alerts coming up. So it's better if you just use the id. It's smaller to just
pass an integer around, instead of a whole object of Jamo. And it's just gonna 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 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 mailer. 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 gonna
need to add that delay method. If you're using Sidekiq or delayed_job, or if you're using Active
Job, just use deliver later, and that will be it. But use the integers,
don't use the objects, for the same reason as
the background jobs. 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 NVC, and everything that you're
doing, and it's simpler. It's very simple to sort of explain, but it's hard to 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 basis things like this. You have the products controller, and then you have an action
to deactivate the product, and you create your route, and use 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 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 contact, you are, you have a search,
so you create a search action. Wrong, that's totally wrong, You create the contacts
searches 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 is 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. 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, RuboCop. RuboCop, it's gonna analyze your code, it's gonna check how it's written, and it's gonna 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 RuboCop like showing you. Better teacher than humans, trust me. A very common excuse that I've heard about not using RuboCop 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 it's
gonna be like 500 errors and you don't have the time to fix them. That's okay, what you
can do is you can run it with this option, auto-gen-config, and it's gonna create a
RuboCop to do that yml file. That's gonna include an
exception for everything that it found. So that way, you just add it
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, for example, right there it's green, at
least from that moment on, if there's something like
if you write bad Ruby code, it's gonna tell you starting from there, instead of trying to fix all the 500 or whatever errors you find. Auto gen config 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 RuboCop
to 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 sort of nest code around, so it looks better if you
try to remove the characters on your lines, so try that one. This one, style and documentation,
I usually move it to, to the main file because
I'm not gonna 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 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
clean up your code base. It's gonna, you know, you're
supposed to try to abstract all the, the code into smaller methods, and then test those, unitesting. That's why I call it unit testing. So keeping this one, really
it's gonna make your code so much readable, and so much better. And then if you wanna run this
before you push code to Git, you can use a hook. If you're at that file
.git/hooks/pre-push, it's gonna run RuboCop 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 RuboCop, failed, 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 RuboCop,
and our repos are filled with comments that read
like, fix that RuboCop thing, because the bill failed
when RuboCop fails. So it's usual to push, wait
for the CI server, fail. Why? Because you, maybe you
went over with the characters or whatnot, so you have to make a command that only fixes that. F RuboCop, damn it RuboCop, there's a lot of comments
like that on our reposts. So I tell the guys to just
use a hook so you know, you run RuboCop before
actually pushing it. If it doesn't pass, then you
won't push and you can fix it, and not curse at it. Annotate, this is a another
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
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 factors you use. So it works as a reference,
as a quick reference if you are working on a model
about the columns that it has, instead of going through 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. So it's very useful to have
these annotations handy. And this one is very 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 attain that it has like contextual auto complete, so it basically auto
completes only on what's open. So you open your routes file
and you have like auto complete 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 one problem as it's happening, as
you are developing it. If you don't know what
the n plus one 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 load 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
one 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 if you add the footer what happens is, as you load that page, you will notice that there is a footer that says, hey you're probably better
off if you include the author on the query, or if you include
a comments on the query. And it's gonna yell at
you from the console too, from the Rails logger,
it's gonna tell you, hey you're doing something weird here so why don't you fix it. And you're gonna 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 micro queries, so this is way better, and 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, oink. This detects 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 Monet 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 basically,
that's the solution. So oink, when you have
it on your code base, and 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,
this information, which is basically how
much memory it's using and the number of objects
that you are instantiating in that request. So if you are developing
something like this, and you see that you have like 500
common objects instantiated, something must be wrong. There is 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 are sort of
trying to figure out where the problem is I would enable it, and 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 them. 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.