How to use different versions of a gem at the same time - ruby-on-rails

Can I use two versions of a gem in one application?
I'm trying to use two Rails plugins to work together:
Pengwynn's LinkedIn for LinkedIn API calls, has an dependency on OAuth (~> 0.3.5)
OmniAuth for user login via multiple well-known websites, has an dependency on OAuth 0.4.0
When I try something in Rails I get this error message:
$ rails server
c:/Ruby187/lib/ruby/gems/1.8/gems/bundler-1.0.7/lib/bundler/resolver.rb:129:in `resolve': Bundler could not find compatible versions for gem "oauth": (Bundler::VersionConflict)
In snapshot (Gemfile.lock):
oauth (0.4.4)
In Gemfile:
linkedin depends on
oauth (~> 0.3.5)
Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
Trying bundle update freezes my terminal.
Is it possible to use both plugins at the same time?

Using two versions of a single gem usually means: use two versions of the same class.
It's not possible without making modifications to these gems. You may try to place created classes in some module, resolve conflicts in methods imported into other classes, and so on. In general, it is not easy task, and usually the effect is not worth it.
What you should do in such cases is to ask the gem maintainers to update the dependencies, or try to do it yourself.
Maybe you can downgrade (use older version of) one of these gems, to the version in which the dependencies were the same.

Unfortunatelly, in Ruby the only way is to fix (sic!) those gems, so they use compatible dependencies.
In general, when building complex software in Ruby and having such a situation we - Ruby developers - can't do much. And this is really bad, as development in Ruby has to focus on this issue as well.
Instead of providing your customer new features or change requests, one has to live with Ruby so called: "gem hell".
Another major characteristic of "gem hell" is that not always the latest gem release is the good one.
Often, a gem does not follow semantic versioning policy, and can introduce major API modifications.
Often, a new gem release may introduce new bugs to features previously working.
Other programming languages have an option of handling these types of problems. Just search for "java multiple versions of same class" and you'll find lots of resources.
What I can suggest for smaller kind of applications is to:
be up-to-date with all latest gems' releases
What I can suggest for larger kind of applications, when above is not an option:
split your application into several smaller applications, services.
This will separate them making risks of having "gem hell" smaller. If it happens, chances are it happens not to all of them.
Also, different apps can use different gem versions.
switch to JRuby where those issues can be - in theory - solved via Java capabilities.

Related

How can I save whole package of Rails App including gems being used?

I'm using a lot of gems. They are really sensitive about dependencies each other.
Now, current combination of the gems is just perfect. I want to save this whole App, and re-use this when I'm going on next project.
As you know, the gems are not promised to exist in the future in rubygem.org
So I'd like to save whole package of both App and gems being used.
Then I don't need to care about setting up gems unless I need new gem.
All I need to care about is just coding in next project.
Someone told me to use this command and save whole App folder
bundle install --path=vendor/bundle
After this, my app got screwed :(
jQuery came not to work anymore after recompile
So I did need to replace whole App folder with old one, which was reffering the gem in /usr/local/bin/ruby /usr/local/lib/ruby/gems/1.9.1
Now, jQuery works fine after recompile :)
For this situation, how can I save whole package of both App and gems being used for it?
What I wanna do is, I only want to set up Ruby's correct version and MySQL.
Then I'd like to put this package into it and start coding, not deploying environment about gems!!
Can anyone share idea about this, please?
Answer to your question
Bundler's bundle package --all command will lock and cache all of your gem files into ./vendor/cache, and you can run bundle install --local so it won't check rubygems.org in the future.
Comments on your question
This question made me cringe because, while I understand the interest in having a "base image" that you know works, it sounds like a few problems will spill over to other projects.
Overburdened applications
Does each project really need all the same dependencies?
If not, then you are bloating each install with unneeded dependencies.
Brittle dependencies
You mention that your dependencies are very sensitive to each other, which sets off alarms.
I don't fully understand what you mean by that, but it sounds like you should consider finding dependencies with more stable interfaces.
Check out ruby-toolbox.com and keep an eye on the "Released" date.
Outdated dependencies
Locking down versions means your new applications will not benefit from updates by the maintainers.
(example) if you locked your rails dependency to 3.2.8 and continue to use it, you open yourself (and customers) to several major security holes.
(possible fix) Look at pessimistic version constraints to allow your applications to receive non-breaking fixes.
Best of luck.

Should I put gem versions in my Gemfile?

Till now, I just use the gem name and avoid mentioning the version number, is this a good practice (pros: the gems keeps on getting updated automatically, cons: the app can break)
if it is a good idea to use version number, what are the standard practices to use it ?
EDIT - I just did "bundle show" and it is showing about 30+ gems even though I have only 6 gems listed at Gemfile, I am assuming the rest are core gems which get installed when I create an app, so how to lock them or should I just leave them untouched ?
I thought so too at the beginning.
But then there would be some updates which didn't quite fit to what I coded, or there would be incompatiblie changes which cause feature to stop working.
it happened to me at least twice that I would update a gem at the exact moment the gem was push and I was one of the first few to see it all break due to some bug that wasn't fixed at the time of the push. So you try to debug and it won't work. Since then, I would lock problematic gems and only upgrade them when that's the only thing I'm doing and make sure the functionality remained the same.
It is advisable to use versions which you know that work.
After that you can use gemnasium to keep track on the gems
My suggestion would be YES.
Reason being is that I view external dependencies as potential breaking points as they are out of my control to a certain extent; any change that an external dependency that isn't initiated by me is a potential for a failure.
Since software development is already complicated, I strongly feel that both limiting and controlling external dependency changes works to our advantage.
The less surprise there is the easier it is to maintain code.
HTH
One of the purposes of bundler is to pin your gem dependencies to specific versions. So on the first bundle after you added a gem to Gemfile, the gems will be pinned to specific versions anyhow. You have to specifically do bundle update <gemname> to do an update on a specific gem. Just bundle update (which updates all gems to the most recent compatible versions) defeats the purpose of bundler to a large extent and should be avoided.
that said, I think one should only mention versions in Gemfile if one has a specific reason for it. Example: You want to run rails version 3.2.8 specifically or you have to use ruby-net-ldap 0.0.1 because 0.0.2 breaks some functionality.
I think yes, because in the early days I had so many issue with gems which are updating by themselves, and not backwards compatible.
Normally this happens when you are switching from one major version to another, For me it's Rails 2.x to 3.x.
So the bottom line is it's good to have versions in the Gem file.
It's good to use the exact version numbers. You can probably always just lock it down to a major version, or never specify any version, and be okay, but if you really want that fine grained level of control and to have 100% confidence in your program when being run on other machines, use the exact version numbers.
I've been in situations where the exact version number wasn't specified, and when I or someone else did a bundle install, the project broke because it went to a newer version. This can be especially bad when deploying to production.
Bundler does lock in your gem specifications, but if you're telling it to just use a major release, then it locks that in.
Also if there wasn't a Gemfile.lock, deploying code to production would be a major issue because, as, the dependencies and gem versions could change.

Developing a Rails app in Netbeans/JRuby but deploying to Ruby (C)

I'm using Netbeans and JRuby to develop a Rails web application.
But for deployment, I will be using Heroku.
Since Heroku uses the Ruby-C implementation, I was wondering my use of JRuby can cause problems? Is this approach a safe thing to do?
You can develop in NetBeans and use C-Ruby (aka MRI Ruby). Just install Ruby separately, go to Ruby Platforms, and select it. I highly recommend you install a separate Ruby anyway, whether or not it is MRI Ruby, because if you use the built-in NetBeans version of JRuby (which is often not the latest) and then upgrade NetBeans, you'll lose all the gems you've installed. Installing Ruby/JRuby outside of NetBeans helps you to better manage the versions and gems.
Now to answer your questions: Likely you will not encounter problems with basic Rails applications. If you ever have the need to use non-native libraries you may run into issues. Some gems (e.g. Nokogiri) have a C version and a Java version so you'd be OK, but if you wanted to use a plugin that relied on RMagick, for example, you'd struggle, as you'd probably go a different route if you were developing and deploying with JRuby.
Bottom line: I wouldn't recommend it. I'd recommend using the same platform for both. But you can use MRI Ruby in NetBeans.
funny thing: I stumbled in your question while looking for a tool chain to do it the other way round (developing in MRI Ruby, deploying with JRuby). Of course you can not use any Java classes and internals, but this for sure is obvious to you. According to my results thus far you shouldn't encounter any process structural issues, because MRI Ruby adheres to the shared nothing principle whereas your requests in the development app share the VM at least. Maybe to be shure you should hae a look at http://kenai.com/projects/jruby/pages/DifferencesBetweenMriAndJruby and read it in a reverse sense, especially the "Native Endian is Big Endian" paragraph when un-/packing Strings or Arrays.
You will save yourself a lot of trouble if you develop on the same platform as you deploy. This goes for OS as well, especially Windows then deploying on Linux, less so with OSX, but still sometimes an issue. You will be troubleshooting on your deployment system and that just isn't the same as catching something as you code it in development. I recently started using JRuby for a project and there are quite a few differences and different gems altogether in some cases.
As for loosing installed gems etc. take a look at using Bundle while you are at it, that will also save you some trouble down the line with gem versions out of sync.

Will upgrading gems break old Rails applications?

I have bunch of Rails apps running on Rails 1.x. I need to upgrade the gems so the question is, will these old apps still work after I upgrade gems?
Thank you.
The only way to be sure is to test, of course; that said, if you want to be sure the application works while you test, I believe that you can run
rake rails:freeze:gems
to copy the currently installed gems to the vendor folder inside your project. If, after testing, your project can use newer versions, run
rake rails:unfreeze
to return to the system installed versions of the gems.
It depends. If you're talking about upgrading to the latest gems that comprise Rails then if the applications use features that were long ago deprecated and subsequently removed, then they will break.
The only way to know for sure is to try it. Look out for deprecation warnings in the development log. Hopefully you have good test suites in place.
It's just like any other dependency. Look at the version number for each gem:
1.2.3
In this case, 1 is the major version. If this number has changed, then definitely do not upgrade. It will require work to use the new one.
2 is the minor version. You should be safe upgrading if only this number has changed, but be careful. Do a lot of smoke tests.
3 is a bug fix release. You can definitely upgrade if only this has changed. It's unlikely only this one has changed after so long, but if that's the case you're safe.
Unfortunately these are only guidelines, and many open-source projects among others do not follow them very well. So take the advice with a grain of salt.
If you are running with rails 1.x and you upgrade the rails gem, your application will break. Rails 2.x is very different.
Concerning other gems, they might break. Read the releases note, usually authors warn about backward compatibility.
If you don't want to upgrade, you could also freeze the gems.

What are the benefits of using the Rails gem instead od vendor/rails?

I recently started working on a small personal project in Ruby on Rails, and have run into a few things that I couldn't find definitive answers for. If anyone here is knowledgeable enough to help, that would be greatly appreciated. All of my questions are below:
What benefit is there to using the Rails Gem instead of having it in vendor/rails?
Is there any benefit to using Rails 2.3.2? Some of the plugins I hoped to use don't seem to be compatible with 2.3.2 (ActiveScaffold)? Does it offer a great improvement over 2.2?
What is the benefit of using Ruby 1.9? Many plugins aren't yet compatible. Does it offer a great improvement over older versions?
Thanks for any help you guys might be able to offer.
vendor/rails probably makes your project more portable. Deployments that run the rake gems:install can act kind of wonky, especially if you upgrade a "Framework Gem" (you have to do these manually).
The downside to vendor/rails is that it makes your deployment slightly bigger (more files that have to be pushed) but if you use git and something like Capistrano, this only bites you on the initial deploy... but its not that bad.
I don't think there are any huge benefits; it just depends on if you need features from 2.3.2. Obviously you want to try to run the latest version to make upgrades less painful. I've found that you always need to be upgrading the framework underneath Rails if you want to have any change of upgrading in the future.
Performance. As you pointed out though, a lot of plugins are broken. This is sort of a chicken-and-egg problem but overtime this should fix itself. We're not running 1.9 yet in any of our production apps because its too unstable with the rest of the stack.
I'll address the gem question.
I've used vendored gems in the past but I have pretty much moved away from it except in the rare case where I need to fork a gem to customize it for some purpose in which case I would vendor the gem.
The main reason not to vendor from my perspective is that you can't cleanly vendor any gems with C modules since they require compilation.
A really good option is to use a gem management tool such as geminstaller, it lets you configure the gems and specific versions of gems that your project works against so that you have a consistent set of gems on your deployment.
What benefit is there to using the
Rails Gem instead of having it in
vendor/rails?
The biggest benefit is that you do not carry around the full rails source code with your project, the other benefit is that moving to a newer version of rails is going to involve less effort.
Keep in mind that the gem command will allow you to install a specific version of a gem.
Is there any benefit to using Rails 2.3.2? Some of the plugins I
hoped to use don't seem to be
compatible with 2.3.2
(ActiveScaffold)? Does it offer a
great improvement over 2.2?
A lot has changed from rails 2.2 to 2.3.2, there are also a bunch of security, performance and bug fixes. ActiveScaffold is compatible with rails 2.3.2, as are most of the plugins out there. If you are starting a new project I would recommend using the latest and greatest.
What is the benefit of using Ruby 1.9? Many plugins aren't yet compatible. Does it offer a great
improvement over older versions?
Ruby 1.9 is much faster than Ruby 1.8.x, however adoption of 1.9 is not that high. Rails 2.3.2 works just fine on Ruby 1.9, however there are some plugins and gems that do not. Make sure you read this stackoverflow question on the topic.

Resources