Ruby on Rails main treasure is its gems. But are some gems as good as others? Definitely not. Check the list of Ruby gems you’d better be careful with when developing a project.
Rubyroid Labs Team is known for its love for Ruby development.
Best Reasons Why Developers Love Rails So Much
Throughout our experience, we have noticed that some pretty popular Ruby gems actually add more trouble than help. So here’s the list of gems we recommend staying away from and some reasons why.
1. devise_token_auth
Link: https://github.com/lynndylanhurley/devise_token_auth
Devise_token_auth is a token based authentication for Rails JSON APIs. This gem was designed to work with jToker and ng-token-auth. Despite really good intentions, this gem, in fact, creates a whole bunch of problems. For example – it breaks sessions, which is pretty hard to track. So actually you lose more time on fixing consequences than it would have taken you to create a custom solution on top of devise gem itself.
We highly recommend being careful with this one, no matter how many stars it has on GitHub.
2. sidekiq-unique-jobs
Link: https://github.com/mhenrixon/sidekiq-unique-jobs
It is tempting to use this gem to prevent adding jobs to execution queue when you have rapid job’s spawn and jobs could be left in the queue for some time. At first glance it makes perfect sense: there’s a possibility that your job will be executed several times so you need some kind of lock to prevent this. But it is really not a way you should be doing this.
Sidekiq-unique-jobs uses redis hash inside as its locking mechanism and it stores JID as its keys and some unique key as its value. When you have a large number of jobs (hundreds of thousands) this locking mechanism becomes extremely inefficient as a size of the hash grows severely creating a whole bunch of problems from memory consumption to failing redis BGSAVE.
There are a few things you can do here:
- Do not use this gem at all; if you stumble upon the idea that your jobs need locking then you probably doing something wrong. As the second rule for sidekiq best usage states “Make your job idempotent and transactional” you probably need to change some logic in your job’s code so your jobs can be run as many times as you need and do it securely.
- Take a look at redis own redlock algorithm, but even this is an overkill because most of the time a simple SETNX command will get the job done. Just do it explicitly in your code with simple begin … ensure clauses, because if you use something lightweight like sidekiq-client-cli, then all the monkey-patching that sidekiq-unique-jobs does simply will not work.
3. axlsx
Link: https://github.com/randym/axlsx/issues/276
Axlsx is a quite popular tool, designed to help developers to generate Microsoft Excel and Office Open XML files with charts, images, automated column width, customizable styles and full schema validation. Though it can boast of pretty nice features, it brings about not only beautiful charts but also some memory usage issues.
Though Axlsx issues can’t be classified as memory leaks, it still leads to significant memory losses, especially when working with big sets of data. So if your project is memory conscious, you better avoid using this gem. You can find more gems with memory issues here.
4. whenever
Link: https://github.com/javan/whenever
Whenever itself is a great gem for managing all sorts of cron tasks. However, the problem lives not in the gem itself, but in the way developers use it. Gem offers a nice interface for running rake or runner scripts. But most people forget that when you actually execute rake or runner script, it loads the whole environment in order to run script/rake task. For some large application this might take a few minutes. Now imagine you have 5-10 processes starting every 15 minutes and taking couple minutes to execute. It can eat all CPU or RAM on your server and make you application being unresponsive until all processes complete execution.
So if you need a gem like whenever quite often, it’s better to look for some alternatives.
5. dwolla-ruby
Link: https://github.com/Dwolla/dwolla-ruby/blob/master/lib/dwolla/offsite_gateway.rb
Dwolla is a well-known payment system for bank transfers. This unofficial Ruby gem, designed to support Dwolla API, can’t boast of such high reputation. The issue here is that it’s not thread safe. In a multithreaded environment, instance variables of a class will be jointly used by a few threads simultaneously.
This way one user can add a product and other will pay for it. In order to avoid situations like this, when using dwolla-ruby, make sure you execute that gem API calls in isolated environment.
6. rails_admin + will_paginate
Link: https://github.com/sferik/rails_admin/wiki + https://github.com/mislav/will_paginate/wiki
And finally, popular issues of using rails_admin and will_paginate. The problem here is that rails_admin depends on kaminari library. Both kaminari and will_paginate are using .paginate() method for paginating items for pages.
As a result, having a combination of these 2 gems will lead to a conflict. And to make a situation even worse, you wouldn’t see any error notification until somebody will decide to click on a page which is using pagination. In order to avoid that collision – check that link out.
As you see, Ruby gems can not only bring a lot of good but also bring a lot go trouble. We hope this article was useful for you. And what gems do you prefer to avoid? Share with us in the comments!
(Featured on Awesome Ruby)
4 Comments
Your point about the ‘whenever’ gem is a good one!
In a personal project that I’ve hosted very cheaply (read: low spec vps) I’ve made whenever just run a basic Ruby script, which adds a job directly to Redis for sidekiq to process. I figure since sidekiq is running anyway, it makes sense to make it process the job! And the script wouldn’t even need to be Ruby, if you’re comfortable writing bash to add stuff to Redis.
Thank you, Bill! Yes, as we mentioned on blog post – using sidekiq-client-cli should be a good option for scenario like yours.
devise_token_auth has caused maintainer time to be used up in ActiveModelSerializers, as well, and without resolution. What it is solving is much easier to do without it.
Agree with you, Benjamin Fleischer. Thanks!