How often do you update the gems on an unreleased project? - ruby

I've got several side projects that are either still in dev or live for friends and family. The exception (modulecounts.com) is pretty trivial.
At work, in a larger organization, it seems like we always make rules against updating gems too often. It becomes a story that's scheduled for a particular sprint. It has to be coordinated with Ops to make sure they'll be ready to update the production environment, etc.
All that coordination overhead is gone when I'm the only dev, but there's still risk in updating gems. Maybe those new versions won't work quite right.
So... is it better to do it all the time? Start each dev session with "gem update" and go from there? Or should I wait until I'm about to go live and do one big update, hoping that any time lost on the back end is made up for by not having lost time in little increments throughout development?
What do you do? What's the happy medium?

The benefit of updating gems more often is that you get improvements. For example, security improvements or speed improvements. Also, it means that your code is more up-to-date, it's usually easier to find documentation for newer gem versions. Also, keeping your gems up to date means that you are using the newer versions of APIs, for example Facebook or Twitter. Using newer APIs can mean speed improvements and staying ahead of deprecations. Of course, as you point out, there are downsides to this, and it's important to keep that in mind. Here are a couple of pointers I like to follow:
Understand the newer gem version you are using. Read the release notes. If you are using well documented gems you should be able to find out what is new in this release of the gem and if you are going to have to deal with deprecations.
Use gem versions in your Gemfile. My favorite operator is ~>. ~> 2.1 means >= 2.1 but < 2.2, this means you can ensure that your gems stay up to date without having to worry as much about deprecations because you can remain within specific gem versions. This often means you'll continue to receive security updates for a specific gem version while retaining the same command and function formats.
Don't upgrade immediately on critical projects. It's best to wait a little when new gem versions are released before you upgrade. Test the new gem version in your development branch or wait to see if others find errors. Stay up to date on a new gem version's progress.
Write tests. Don't test gems directly, but make sure that your code that depends on gems is working as you expect it to. The more coverage you can get here, especially for critical functionality, the easier it is to tell if a new gem version is still operational.
Test your application after you upgrade a gem. It's often nice to create a new git branch and update a gem in that branch to ensure that your code is still operational. You might even keep a branch alive for multiple development cycles or sprints while it is being tested or while you are upgrading your code, only merging it back into your master branch once you feel confident that the gem upgrade was a good choice.
My preference is really to stay as up-to-date with gems as I can, while making sure that my development is not very hindered by continually upgrading. I try to upgrade on a schedule that works for my team, for example every two weeks, while keeping an eye out for security upgrades. It also helps to have an automatic way to setup your production environment. Bundler is great for this, because your Gemfile.lock can ensure that your production environment is running the same gems as your development environment.

I don't think there's a compelling argument for updating every time you start working unless you like to start your work with fixing incompatibilities with updated gems.
I usually update once every week or two when I'm developing something. I'd rather not launch with out-of-date 3rd party code. Once it hits production, though, the amount of work required to vet gem updates makes me a little less likely to want to update. Sometimes your tests won't catch something that changed, and then you won't either.
So as a happy medium, if it's your project and relatively safe to update, do it often, but don't force yourself to do it daily. If it's a production app where you have a higher chance of breaking something, or you're working in a team, be more cautious about updating unless you really need to.
Oh, and I vote that Rails et al are fairly safe to update whenever, so long as you read the release notes and make any changes needed.

Related

Is there an alternative for `rack-test` for Ruby 3?

We're using rack-test for our Cucumber specs. We've been trying to migrate over to Ruby 3 for a while now and the current issue is that the Cucumber tests crash due to rack-test using both keyword/positional args in their internal methods.
I'm up for patching it myself, but seeing how little activity there is on the repo (including PRs open for weeks/months) I fear that I'd do the work and there would be nobody to patch it.
The only alternatives I see are:
Do the work and pray there will be someone to review/merge the changes
Patch it locally & use the patched version locally from now on (yuck)
Find an alternative solution for rack-test
The last solution seems the best IMO. So, are there any alternatives?
As with all open source software, you have a few options:
Keep using the old software version (i.e. don't use ruby v3.0.0).
Hope that someone else updates the dependencies for you.
Do the update yourself.
Stop using the library.
At the moment, option 1 is totally viable; ruby 2.7 is still actively maintained, and support will probably continue until 2023-03-31. You could do this, simply hoping that option 2 becomes available soon.
The standard practice for option 3 is:
Fork the project, and make the fixes.
Open a pull request to the main repo with your fixes. Hopefully it gets merged.
In the meantime, if you need to be unblocked, reference your forked repo in other projects.
This is clearly more effort, but I wouldn't call it a "yuck" solution; not unless your changes are drastic/introduce compatibility issues with the main project, and the two branches diverge.
As for option 4, as with virtually any library replacement, there's always going to be some trade-off between compatibility/features, but clearly other testing frameworks do exist. It depends how you are actually using it. Your mileage may vary.
In summary, I can't really give an objective answer to such a subjective question, but my advice at the moment would be: If you have time/skill/motivation to update to ruby 3 right now, then fork the dependency and update it. (It's probably not a massive change needed!).
But if you lack the time/skill/motivation to do this, then just stick with ruby 2.7 for now.

Do old gems always work on later versions of ruby?

I am using a quite recent version of ruby (2.5.1) but some old gems. I am having some issues. I was wondering, is it correct that some gems work only with certain versions of ruby?
If a gem worked with ruby 2.3.0, is it true that it will definitely work with 2.5.1 (i.e. because 2.5.1 > 2.3.0)? Or is that not always the case?
I guess what I'm asking is are newer ruby versions always backwards compatible with older gems?
If a gem worked with ruby 2.3.0, is it true that it will definitely
work with 2.5.1
This is not correct. Programming languages are evolving while growing. This means language maintainers are doing lots of improvements or refactorings that they are new features or removing old components from the language. When the language community announces for new features or removing old feature such as Fixnum in ruby, the developers should follow the instructions and refactor their codebase accordingly. In other words, developers should have a good test coverage to detect any fail and fix it instantly.
In your scenario, as well as I understand you do not have a test coverage. The only but the simple thing should do is just upgrade your gems' versions to latest.
Gem is simply a plug-in library written in Ruby.
Of course, Ruby is developing, new features are appearing, old ones are disappearing.
It's best practice to specify Ruby version in .gemspec file. For example, like this one.
But if not, then you have to manually check the performance. So you can read gem source code or try to use your gem and check it.
For automation, of course, it is best to use tests.
Starting at Ruby 2.1.0 the version policy has been that a change in the MINOR version may introduce API breaking changes.
Should any gem happen to use an API that changes, an incompatibility will arise.
The MINOR version number has changed twice between 2.3.* and 2.5.* so even if a gem happens to have been written in accordance with the documented API, there's no guarantee that it will continue to work unless the gem's maintainer takes the effort to test the gem (and upgrade it if necessary). Automated test suites help a lot.
A standard way to document version compatiblity that is actually tested against is by providing required_ruby_version in .gemspec files.
Interestingly, if a particular gem is really badly written, I imagine it might break even between compatible versions of Ruby. That's not something I've encountered in the Ruby ecosystem but I've made a similar mistake writing Java code (and Java is famous for its backward compatibility) where my own code accidentally used a class that wasn't part of the API. There are many gems. Who knows what's out there? :)

Test local version of gem in Rails project

My Rails site uses a certain gem which is really not very good. Every time I need to do something new I end up having to spend as much time adding features to the gem as I do adding code to the actual Rails project. But I don't mind, and I have my Gemfile set up to point to my GitHub fork of the gem (I tried submitting PRs, but the maintainer seems to have stepped down).
The problem is that I really haven't found a sane way of testing new things I add to the gem. It'd be especially nice to test it within rails c, but the only ways I can think of doing that are a) Changing ~/.rvm/gems/.../foo.rb, which doesn't seem right or b) Bumping the version, pushing to Github, and running bundle up, which in addition to being time-consuming is obviously a disaster since I don't know for sure whether the commits I make are right or not.
I'd even be perfectly happy with a standard irb. But various permutations of require lib/foo from within the gem's directory don't work.
So what's the best practice here?
If you are using a gem and working on it at the same time, the best way is to use Bundler and provide a local path:
gem 'my_bad_gem', path: '../my_bad_gem/'
This will look for the gem under the given (relative in this case) path. Another option is to use local git repositories (see http://bundler.io/v1.3/git.html).

Customize Gems or merge into main rails project

Currently I am writing a Ruby on Rails application, and I am using Gems, however sometimes I feel that Gems are not as flexible as I want them to be. To make them more flexible. Should I
Fork them on github, and customize it, but this still present the challenging of managing everything.
or
Strip and merge the code of the gem to the main application? This will allow further customization of the gem. This would be for situations where a Gem require another Gem's functionality.
or is there a better way of doing this?
Thanks
B
Choice A is the better answer for a number of reasons.
You get to merge in security updates, enhancements, and bug fixes easily.
Your changes may get merged into the core--in fact, consider if you could implement them in such a way as they live alongside the core functionality as options. If this happens, you have the ultimate win--nothing to maintain, and you can retire your fork.
Others can benefit from your changes.
Your project's footprint is kept smaller and focused by keeping the gem code isolated.
You'll have something to add to your Github "resume."
If its some kind if not so popular gem or "bicycle" from some previous studio or developer who started project(in my case).
I prefer deprecate this gem's and move code into project,
for example they have c***la-deploy - it's just wrapper to Capistrano 2 with own methods))) - I just delete it and rewrite on last Capistrano 3
Than that have own "CMS" c***la-cms where they wrap standard form_for or simple_form with name "twitter_form_for" ? - fist of all I start try to find gem who use this name, and than find in dependency gem's ...
Its take a lot of time for new developer involve in project - better move to standard rails methods/heplers
But anyway i understand for a what this studio do that - its just vendor lock and for client more hard to move out from them to another developers.
For example for startup its bad to use a lot of dependencies and if it's just simple website - dose not matter.

sharing ruby code within an organisation

Me and my team are starting to build up a few re-usable scripts. They're re-usable within our org only as they work with proprietry apps and our particular server environment. So not really suitable for rubyforge or github, etc.
My question is, what is the best practice for ensuring we're all using the latest and greatest scripts across all users? We pretty much run these scripts on one server, but may need to expand to others.
Should we bundle them into gem(s) and start a private gem server?
Or something simpler like a common, shareable lib directory. Perhaps with a script to download/update from our SCM?
Other ideas?
Thanks....
This depends on some factors, like how many people want to change the code (only your team, or someone else too), or how much money you have for this?
Personally I'd create a build+gem server, where you can upload the scripts using some versioning system (like git or svn, depends on how many people are working on the project), and then create a cron job, that would automatically genereate the gems from the sources at generic intervals and store them as different versions. This way you can be sure that you always have an authorative server that stores your applications gems, and you can always get an earlier version if something breaks. Your script might create separate gem version names, like "appserv-edge" or "appserv-stable"
You might also want to check out github's closed source options too, if you have the money to afford that. I don't know however whether they have gem building and hosting facilities for non open-source programs.
I've created a private gemserver and it's dead easy. The only tricky bit is deciding how you want your users to upload gems. Personally, I just use a PHP upload form, and have it check to make sure that it's not masking any existing gems.
At my office we're using a bit of a hybrid approach for some of our shared scripts and libs. We do bundle them all in to a gem, but rather than using a gem server we keep them in source control, and then build the gem (using newgem) and install it locally as necessary.
The downside of this approach is that it takes two commands instead of one to install the gem, but this is largely mitigated in qa and production environments, since we use Capistrano for deployment.
The upsides are that it's dead simple, and in development there is a very short edit/build/deploy cycle if you're working with something that requires changes to the gem. I'm currently pulling a lot of common functionality in to the shared gem, so I'm really appreciating that aspect.

Resources