Category

Ruby

Ruby’s assign if not nil operator

I think most Ruby programmers know the ||= operator, where a variable is assigned a value if nil.

For those who don’t know, it works like this.

In the example above, variable a is assigned 1 because it is nil. If a wasn’t nil, 1 wouldn’t be assigned to a and a would just remain nil.

I recently came across the &&= operator while reading Confident Ruby by Avdi Grimm. It basically works like this. It works kind of like the ||= operator except that it assigned a value to a variable if it isn’t nil. An example would be.

I think this is a good way to make your code concise by getting rid of a lot of if statements. For example, I do this a lot in my code.

That if statement above can be replaced with &&=, making our code more concise.

This is a short post, just sharing something new I’ve learned in the past few days.

“And” and “or” operators in Ruby

When I first started programming in Ruby, using the and and the or operator always confused me.

Thus I avoided them because I didn’t want to worry about accidentally writing incorrect code. I think a lot of programmers do the same, and it’s a shame because incorporating both and and the or operators can lead to more concise and elegant Ruby code.

First, let’s get the biggest misconception out of the way. The and and the or operator are not the same thing as && and the || operator that most programmers are familiar with. The && and the || operators work to validate some kind of condition while the and and the or operators work more to handle control flow, kind of like your every day if statements.

and

Let’s talk about and first. The easiest way to think about the and operator is a way to chain methods until a method fails. The English way to think about it is something like, “do this and then do that and then do that, until one of those actions fail”. Let’s say you’re giving a mailman directions on how to deliver mail. You give him a list of addresses to deliver mail to and you tell him to continue delivering the mails until you come across a mail where you can’t locate the address of.

I’m going to try to explain it with some code so that it’s easier to understand. One common thing that we all do when writing code is to assign a value to a variable and then calling a method on that variable. For example,

This is something you would typically do in a Rails controller. You query for an ActiveRecord model, assign it to a variable, and then take an action on that variable instance. In the above example, you can utilize the and operator and write the above like this instead.

The above does in one line what the first example did in two lines with one additional advantage. In the first example without the and operator, the resident.launch! will cause an exception if the resident = Resident.find_by(id: params[:id]) fails and returns nil. However, in the example with the and operator, resident.launch! will only be executed if the resident = Resident.find_by(id: params[:id]) was executed successfully and an actual resident was assigned to the resident variable. Thus, in this specific example, the version with the and operator is more resilient.

How would we write the above example with a standard if statement? It would be something like this.

I think the above code snippet is pretty clear in its intentions too, but I personally prefer the version with the and operator.

or

Let’s now talk about the or operator. The or operator, like the and operator is meant to chain operations together with one slight difference. As we discussed above, the and operator chains operations together until one operation fails. The or operator on the other hand, chains operations together until an operation works. For example, let’s say we want to raise an exception if resident.launch! fails for whatever reason. Not using the or operator, we could do it like this.

In the above example, we’re launching a resident, and then raising an error if the resident failed to launch. How would we write this utilizing the or operator?

In line 2, we are attempting to launch the resident and if the resident launch failed, we are raising an error. The easiest way to comprehend this is literally read it like English: “Hey resident, launch yourself or otherwise raise an error”.

Conclusion

Ruby comes with a lot of tools included to make writing elegant code easier. I believe that the and and the or operators are one of such tools that make such endeavors easier to achieve. I hope that this post helps demystify what these two operators can do in helping you write better Ruby code.

Ruby Keyword Arguments

Whenever new versions Ruby, Rails, or Android comes out, I quickly glance over the change logs and go, “Oh, neat! That’s a cool feature, I’m going to start using that!”

But, habits are hard to break. In my prior freelance gigs and jobs, whenever I wanted to have default values for parameters in a method, I would always do it this way.

If we wanted the method foo to accept multiple parameters and we wanted them to all have default parameters, we would do this.

And so forth. Apparently in Ruby 2.0, which has been out for awhile (yes, I am slow), something called Keyword Arguments was introduced. So, instead of doing the above where you have to worry about ordering of your parameters, you can simply do

This is essentially the same thing as passing in a hash as a parameter and then setting default values for those parameters before writing the actual meat of your method. In Ruby 1.9, the above foo method would have been written as

I think the keyword arguments version is prettier. After looking more deeply into this, it seemed that in Ruby 2.0, we couldn’t make keyword arguments required. However, Ruby 2.1 introduced keyword arguments. To make keyword arguments required, you simply omit the default value after the key, like this.

Keyword arguments vs positional arguments

Personally, I prefer keyword arguments, because it makes reading code much easier. For example, let’s say that you have a method that calculates profitability of a business. Let’s keep it simple and say that the formula is simply revenue - cost.

The first way will be with positional arguments

If someone was looking at the line where we’re calling the method profit with the parameters 500 and 200, that person may wonder, “Okay, what does 500 and 20 represent?”. He/she would then have to locate where the method profit is and read the method to find out that 500 is the revenue and 100 is the cost. Let’s look at what keyword argument version looks like.

In the Keyword Argument version, it’s clear that 500 is the revenue and 50 is the cost as it’s literally written in the line where we’re calling the method profit. I personally find the keyword argument version much more clear.

Some gotchas

I think most people would agree that keyword arguments is more clear than positional arguments. However, using positional arguments is a more succinct way to write a method, so you’ll have to decide between the two and pick the one that makes sense for the method that you are writing. Personally, if the method only takes one arguments or if the arguments that the method takes in is clear/obvious, I think positional arguments make sense. In all other cases, I prefer keyword arguments.

Also, keyword arguments are essentially a hash disguised as a parameter. Sandi Metz once said in a talk she gave (and I believe in her book Practical Object Oriented Design in Ruby) that a method should take in no more than 4 parameters. If it does, there’s probably another method or an object in there.

This “rule” shouldn’t be broken by passing in one hash with bunch of key/value pairs, and while keyword arguments wouldn’t tempt developers due to its syntactical nature of it looking like actual parameters rather than one single hash, it can still be abused if one wants to take advantage of the fact that ordering of parameters is not important in keyword arguments.

For those of you who weren’t aware of its existence, enjoy writing more clearly defined methods with keyword arguments.

Dynamically create methods and scopes in Rails

The active record models with the status columns generally indicate that there are different states that the model can be in.

And usually, when there are status columns within a model, it’s common to query for specific statuses and to check for the status of the model. For example, let’s say that we have an Invoice model that have three different statuses: pending, paid, overdue. Most people would write code for querying for these statuses and checking for the status of the model like this.

This works. Some developers, who are aware of creating scopes may create scopes for the different statuses instead. And also, they may add methods to the Invoice model to determine the status of the Invoices (because you know, refactoring).

The above is definitely better, and I (and a lot of people) would probably go, “Good Enough”, and get along with our lives. But our Invoice model can be made more succinct and more flexible if we utilize a little bit of underutilized Ruby features.

Let’s say that the Invoice model can have a lot more statuses, like 10 different statuses, like paid, pending, overdue, overpaid, underpaid, read, unread, clicked, missing, scammed (Note, some of these status names don’t make sense, I just wanted to quickly come up with 10). Well, that’s a lot of custom scopes and methods you have to write. Thankfully, there’s a little trick to creating scopes with a little bit of Ruby magic during runtime.

For the scopes, we can store the pre-defined statuses in a constant, loop over them, and create scopes during runtime. For the methods that check for the Invoice’s current status, Ruby has this thing called define_method that allows you to define methods during run time.

https://ruby-doc.org/core-2.2.0/Module.html#method-i-define_method

At first glance, one may go, “Why would I ever use this define_method thingy instead of actually writing the method myself?” Well, in the context of creating methods that check for predefined statuses on the fly, it can be pretty useful in that it can create all of these methods for us rather than us having to write the scopes by hand. To utilize these two techniques so that we don’t have to manually write 10 different scopes and methods by hand, we need to do the following.

  1. Create a constant that defines what statuses the Invoice model is allowed to have.
  2. Loop through the statuses, and for each status, create a scope and then define a custom method using Ruby’s define_method.

Below is how you do it.

Try the refactoring of the Invoice model above and you’ll see that the controller still works as it should. And the Invoice model in this form is much more concise and flexible since if we want to add more scopes and methods that pertain to the status, all we have to add is the new statuses in the Invoice::STATUS constant.

Ruby Safe Navigation Operator

I’ve been working on a new codebase lately and have been seeing an operator that was unfamiliar to me.

It is Ruby’s Safe Navigation Operator. It looks like this &. chained by subsequent methods. After looking into it, I realized that I had read about it in one of the Ruby Weekly newsletters a few years ago.

Most Ruby developers are probably familiar with the try method in Rails. What the try method does is it “tries” to execute a method on an object that may or may not have that method available to it. For example…

As one can see, try allows you to “try” methods that you’re not 100% confident will work on an object you’re invoking on. Ruby’s Safe Navigation Operator is exactly like Rails’s try method. You could write the above code in Ruby starting from Ruby 2.3.0 like this outside of the Rails ecosystem.

Now, I’m not sure how I feel about this operator being introduced in Ruby. I’ve never felt 100% sure if I liked the try method in Rails or not because anytime I used it in my code, I felt unconfident in my code. It made me feel like the code I was writing was weak, as if the variable I was invoking try on, I was designing my code in a way that it was difficult to predict what each of the variables was representing.

But, try was only available within the context of Rails and wasn’t available in Ruby land. Now, with the introduction of the Safe Navigation Operator, I have fear that this can be abused when writing pure Ruby programs. Maybe it can make your code more succinct when used correctly, but I can already see myself itching to abuse this when feeling lazy.

RubyC 2017 – Kiev Thoughts

I’m still in Kiev, Ukraine right now and I had the opportunity to attend RubyC 2017 conference over the weekend.

Despite having written Ruby professionally for a few years now, this was my first Ruby related conference. The tickets were only $100 so I figured that it would be a great opportunity to attend a software development conference as well as doing something productive and career related over the weekend.

Both Ruby and Ruby on Rails is over 10 years old at this point and one can make the argument that both the programming language and the web framework are both stable and mature. Due to it, the language has been “evolving” so to speak for the last few years and not too many ground breaking changes and/or features have been introduced. Also, the reason Ruby became popular at all is due to the rising (and eventual dominance) of Ruby on Rails. Ruby on Rails is essentially the “elephant” in the room. In fact, this was emphasized in many of the talks that were presented at the conference.

Pouches for speakers to sit for open talk session

One of the talks that I found to be the most thought provoking was “Ruby 4.0: To Infinity and Beyond” by Bozhidar Batso. He’s apparently the author of RuboCop which I found to be impressive. I love that library  as it helps me write cleaner code and makes me adhere to the basic programming and syntactical that I set for myself.

One thing Bozhidar Batso mentioned was that not much has changed in the last few version of Ruby. He had a few slides where he listed the major list of changes from Ruby 2.0 – 2.4 (I think he started from 2.0) and he did have a point in that each release since Ruby 2.0 has been incremental. In fact, the only change that I could think of that has been made from Ruby 2.3 – 2.4 (and this was listed in Bozhidar’s slide) was the unification of Fixnum and Bignum into the Integer class which generated a lot of deprecation warnings in some gems. Aside from that, nothing major sticks out in my mind.

Bozhidar also mentioned that Ruby is the only programming language where certain features and changes made are driven by the web framework that dominates the language, in our case Ruby on Rails. He mentioned how insane this is and a web framework shouldn’t influence the design of the programming language that it’s written in. He had a point there, but this made me notice that there was a lot of, “WE NEED AN ALTERNATIVE TO RAILS” mentality not only in the speakers but also by a lot of the audience. For example, when a statement about some negative aspects of ActiveRecord was mentioned, there were a few cheers made by the audience.

This is something I do not understand. The fact that as soon as something gets popular, we humans have a natural tendency to immediately start hating on it. This doesn’t just happen in technology stacks but even in coffee chains in Starbucks. How many times have you heard Americans say that they hate Starbucks and the coffee served is terrible? I personally think Starbucks coffee is pretty good, especially if you get it fresh in the morning. It’s strong and consistent.

Same goes for Ruby on Rails. As soon as it became the default go-to web framework for Ruby, there have been many talks about the need to replace it and that it’s inappropriate that something so dominant. During the conference, the Hanami web framework was proposed as something that could give Rails some competition.

Personally, I like Ruby on Rails. I think it’s well designed, easy to work with, and the most productive web framework in the market right now. Is it perfect? No, of course not. But is it a good tool for building web applications? Yes, it’s excellent.

There was an open talk session where the audience had an opportunity to ask the speakers any questions they had. One of the speakers mentioned that despite other speakers demoting Ruby on Rails and promoting something else, if he was the one paying for the software project, he would go with Ruby on Rails every time due to its emphasis on productivity and set of sane default configurations that it comes with. I completely agree with this. If I’m paying other developers to write a web application, I’m going to go with whatever is most productive and gets the job done in a timely manner with reasonable code quality. Also, due to its convention over configuration philosophy, new developers on the team can get acquainted with the codebase very quickly. Despite being over 10 years old, Ruby on Rails still hits on these points better than other technology stacks out there.

The speaker who gave the answer in terms of, “If I’m putting up my own money…”made me think of a training curriculum that all software developers should be required to go through. I think all software developers should have to go through a phase in their career where they have to manage a project from beginning to completion and through maintenance cycles where the team members are switched once every few months. Essentially, the training regimen should replicate a professional work environment as much as possible. I think a lot of software developers put too much emphasis on the engineering aspects of software development rather than the pragmatic side of it. Maybe, the training regiment should also include a portion where the participant loses money if he/she doesn’t complete the training regiment successfully. I’m willing to bet that a lot of participants will opt for tried and true technologies like Ruby on Rails than to Hanami or “enter the cool new shiny programming language/framework of the week” if their own money on was on the line.

Migrating paperclip attachments

In web development, sometimes you have to perform data migrations that involve migrating file attachments on existing models onto new models. I recently had to do this on a client project and I’ll go over some code snippets demonstrating the steps that need to be taken.

Just as a preface, this is a Ruby on Rails application that is using the paperclip gem to handle file attachments. All files are uploaded to AWS S3.

Let’s say that we have a User model that has an attachment column called avatar. In the beginning of the application’s life, the application only allows the user to have one avatar. This is relatively simple to set up in Ruby on Rails. Here’s an example User ActiveRecord model set up with paperclip.

Pretty simple and nothing special. Now, let’s say that we get a new requirement that will allow users to have multiple avatars. How do we handle this? In this case, I’d say we have two options

  1. Add as many extra paperclip attachment columns as necessary to the users table and attach all future avatars to the user model directly
  2. Create a new table specifically for storing image attachments and set up a has_many relationship between the User model and the Picture model.

Option 1 is simpler but is the more naive approach. Also, it doesn’t scale. What if in the future, we have other models, let’s say a Book model for example, that needs to have multiple image attachments as well? The more flexible and scalable option is options number 2 where we set up a separate table.

Let’s set this up shall we?

First, create a new picture model by running this command in your terminal

And, in your newly created migration file, set up a polymorphic association like this

And your Picture model should look like this

Now, we want to set up the User to have a has_many polymorphic association with the Picture model.

Now, we want to run a migration to migrate over all pre-existing user’s avatar attachments over to the new pictures table. Create a new migration file by running something like this in your terminal.

And in your newly created migration file, set it up like

The script in the migration above will grab all users that have avatars attached, loop through them to create new picture record with the same avatar attachment and associate that instance of the picture with the appropriate user, and then delete the original avatar in the user record to free up hard drive space. The last part is important if you are using something like AWS S3 and you don’t want random files that aren’t associated with any application records lying around.

And finally, we need to run one more migration to remove the avatar attachment column in the users table. Create another migration with a command like this

And in the migration file, simply remove the attachment from the users table

And that’s it! Don’t forget to change your views appropriately so that your app doesn’t break for your users.

Also, before I end this post, why a polymorphic association rather than a normal association? Because if we make the pictures table polymorphic, we can reuse that table to store all types of image attachments and have one place where we can hold all logic for handling image attachments. That should result in a cleaner, DRY’er, and more maintainable codebase in the long run.

Puma config in development vs on Heroku

So that puma web server for ruby, the web server that’s built for speed and concurrency has a weird issue with its configuration on development environment vs on Heroku.

For those of who might not know, this is the puma web server I’m talking about

https://github.com/puma/puma

Yeah, the one that’s apparently the standard that comes with Rails 5 now.

One of the projects I’m consulting for (yes, it’s a Rails project) uses puma as its web server. And it has a puma.rb file that’s configured as recommended by Heroku. The file at config/puma.rb looks like

Now, you see on line 8 and 9 there? Despite the ruby code checking for the nil condition and defaulting to port 3000 and an environment of development if those environment variables are nil, this does not work in development mode if we run it with foreman with a Procfile. For some reason, the port for puma in development mode defaults to 5000 instead of 3000.

Now, if we put an = sign in front of the port and environment declarations like this

Then it works on development and the port for puma defaults to 3000. However, putting those = signs will break the Heroku server.

After wrestling with it for an hour, I simply decided to set the environment variables of PORT and RACK_ENV to 3000 and development accordingly on my development environment so that at least the application runs without crashing on Heroku.

It’s a super weird issue and I’m not sure why it’s working well on development and then goes haywire on Heroku. At any rate, for those who are running into the same issue, I hope this post was helpful.