Gem development - should I update dependency if depending gem has bug - ruby

Hi I am building a gem which depends on the multi_json gem, which is basically adapters to all other json encoder/decoders out there.
So an user filed an issue on my gem. He has issues because multi_json has a small bug in one of the adapters, which is later fixed on multi_json's end, so it is not really my issue.
I am wondering if I should change my gemspec to hardcode the dependency to the fixed version of multi_json. I thought it would be easier to just tell the user to explicitly specify to use the fixed version of multi_json. This way my dependency won't be too strict and conflict with other gems which use multi_json.
What are the thoughts on this?

You don't have to lock dependency version entirely, just make sure that you have release that have above-mentioned bug fixed. For instance,
gem 'multi_json', '> 1.9.1'
It will be on rubygems sooner or later and you're definitely not interested in encountering the same bug twice.
My opinion is that the reliability of your library in the present is more important than future development inconveniences, which may or may not occur.
As for what to tell your users, they should've already heard (and if they haven't you could remind them of this in the README.md) that most of the critical problems usually are solved within the day and can be found in master. So if they want to take advantage of the latest fixes (and the freshest new bugs), they could specify github as a source:
gem 'your_gem', github: 'lulalala/your_gem'

Related

What is reccomended practice for version restrictions in rubygem add_dependency?

When authoring a gem, what would be reccomended practice for version restrictions of dependencies. For example I know that know that my gem works wih rubyzip version 2.x, but I also know that it works for 1.9 as well. Should I state
spec.add_runtime_dependency 'rubyzip', '>1.8'
or if the rubyzip version 1.9 is long time outdated, it is more common to "push" change for 2.x line? Also if I use the mentioned line, that I risk incompability with future versions, but on the other hand, leave the coice to the user.
Note: the questions is generall and dependency on rubyzip is just an example.
If you know that your gem works with rubyzip 1.9, then there's really no need to force people to use >=2.0 with it.
Sure, updating dependencies would be a good idea for your library-user to do, but it's not your job to be the "update-your-software-police"!
Specifying that the version must be < 3 is generally advisable (although not consistently done by developers), as there's a reasonable risk that a major dependency version bump will be incompatible with this version of your code.
So, as a compromise, you could do:
spec.add_runtime_dependency 'rubyzip', '>=1.9', '<3'
See the documentation for valid syntax examples.

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? :)

Can I get rubygems to ignore gem version conflicts?

I have done a bit of digging through the rubygems code and it doesn't look like there is a built-in way to get it to not throw a Gem::ConflictError even if there is one. During development I might be wanting to test something that I know is not going to touch the code from which the conflict is coming or I know that the whatever version of the erstwhile conflicting gem isn't going to cause a problem. I just want to get on with testing what I want to test and I'll worry about version conflicts later.
I know I can hack rubygems to do this. I can think or multiple ways to get it done. I'm just kind of curious if anyone has already done this, how they did it, and maybe if that code has been shared somewhere. I'm also a bit curious as to why this isn't built in to rubygems as a development tool.
You need to worry about version conflicts now before you can get anything done. As Ruby has a singular root namespace and every dependency gets loaded there it's generally not possible to load multiple versions of the same gem. Other systems like NPM for Node.js are significantly more flexible, it's possible to load any number of versions at the same time, so if you're used to that you'll need to adjust your expectations.
If you're trying to do testing and you want to avoid resolving a conflict, just remove that gem requirement from the Gemfile temporarily.
Ultimately you'll have to fix things, there's no way around it, but you can always be selective about what you require.
If you really know what you are doing, try this:
export NOEXEC_DISABLE=1
ruby you-program.rb
This environment variable will disable search and check for Gemfiles and gem versions.

How to fix a RubyGems.org project page after yanking a gem?

I have a gem published here: https://rubygems.org/gems/rangy-rails/
When I first released it in March 2013 I later realized that I had set an incorrect version.
I immediately yanked the gem and resubmitted it with the correct version. Unfortunately RubyGems does not remove the yanked gem and this is causing two problems:
The version list is not ordered correctly (yanked gem is on top): https://rubygems.org/gems/rangy-rails/versions
My gem's main page on RubyGems: https://rubygems.org/gems/rangy-rails/ is using a description about the gem being yanked instead of the gemspec's description.
How can I fix this?
So far my only option seems to be contacting RubyGems but they explicitly say the following:
Our policy is to only perma-delete gems that really need it, such as
gems that may contain passwords, malicious/harmful code, etc. Yanking
a gem effectively removes it from being found and will do the trick in
99% percent of situations.
(source: http://help.rubygems.org/kb/gemcutter/removing-a-published-rubygem)
Problem 2 is solvable. The description is taken from the latest non-prerelease version of the gem (not including yanked versions). (See more info about prerelease gem versions here.) Right now, your gem has 3 versions, and the two non-yanked ones are both prerelease (they have letters in the gem version). If you push a new version of the gem, even if it's 0.0.1 or something, that's a "release" version, and it will be used for the description instead.
I made a little test gem here to demonstrate what I'm talking about -- notice that the description page is taken from the latest non-prerelease version (0.0.1, in my case.)
There is no self-serve way to "solve" problem 1 -- Rubygems.org will always display your gem versions in semantic versioning order, from highest to lowest. I'm not sure why this is a big issue, though -- most people typically won't look at the versions page. Yanking will mask the bad version in most situations and, as the documentation says, will probably "do the trick" in this case.
If you really want to permanently hide the traces of the yanked gem and remove it from the versions list completely, you'll need to contact the Rubygems staff and see if they're willing to help out.
You need to publish new version, that is more than yanked. I.e., if yanked version is 1.3.0.772, you need to publish 1.3.0.780 (for example)

How do you know what Gem is the right one?

It seems like there are no guidelines on Ruby Gem package submission. There's no way to tell what is the definitive package for your needs. At least not within the Gem framework itself. Or am I missing something?
For example: I found out about "ActiveLDAP". I did
gem search ldap --remote
and got back
*** REMOTE GEMS ***
activeldap (1.0.2)
ambitious-activeldap (0.1.1)
ruby-activeldap (0.8.3.1)
ruby-activeldap-debug (0.7.4)
I ended up installing 'activeldap' and 'ruby-activeldap'. Turns out they're the same package: "ruby-activeldap" is just an older version.
Is there a way within the Gems framework to differentiate them, without having to Google for the answer. A short doc string, for example, or a dependency tree?
Seems like there are lots of these type of discrepancies in Gems.
If you are installing the gem because of a dependency in a script, you might be able to tell based on:
require_gem 'rake', '>=0.7.0', '<0.9.0'
Other than that, I am not sure either to be completely honest. I would usually go with the latest version of something in cases where a require does not specify which one is needed.
[edit]
I would use the one that appears to be the most mature first (1.0 over 0.X).
[/edit]
I think you could look around and find guidelines, but whether or not they're followed is an entirely different matter!
This is open source software - it costs you nothing to buy, but I'm afraid you're going to have to invest some time to determine if a package does what you want.
It's relatively straightforward to determine how recently a gem has been released and how many times and with what frequency updates have occurred. These are indicators that the source is being actively maintained and that effort is going into its continuing relevance. You can also look at tests (usually installed with the package), existence of bug tracking facilities, discussion groups or forums and the like in order to assess the degree of commitment from the developer(s) and the amount of penetration and community around the code.
Beyond that, what were you hoping for? Value for money? Some central authority that accredits the fitness for purpose of a library? It ain't going to happen any time soon, and that's probably, on balance, no bad thing.
You can get more detail in your search results that might help you narrow it down if you use the details and all options:
gem search activeldap --remote --details --all
all shows the list of versions.
Part of the output:
activeldap (1.0.2, 1.0.1, 1.0.0, 0.10.0, 0.9.0)
Authors: Will Drewry, Kouhei Sutou
Rubyforge: http://rubyforge.org/projects/ruby-activeldap
Homepage: http://rubyforge.org/projects/ruby-activeldap/
Ruby/ActiveLdap is a object-oriented API to LDAP
ambitious-activeldap (0.1.1, 0.1.0)
Author: Matthew King
Rubyforge: http://rubyforge.org/projects/ambition
Homepage: http://ambition.rubyforge.org/
An ambitious adapter for ActiveLDAP
Beyond that, as Mike said, it's sort of a matter of poking around on the Web to try to suss out what's the most relevant version.
One thing to note: wholesale migration around mid 2007 in the Ruby/Rails communities to Github. So if you find something but it's not on Github, make sure it's not some old version that's been superseded.

Resources