Preventing Bundler to install gems under the Ruby version namespace - ruby

When I install gems using Bundler to the project directory, for some reason it installs them under the Ruby version namespace, that is vendor/bundle/ruby/2.1.0.
Why Bundler have such behaviour? Is there any way to prevent Bundler to install gems under the Ruby version namespace and instead to place them directly into vendor/bundle?

Bundler does this for the same reason that rubygems does it - different Ruby distributions may not have compatible gems. For example, a gem with a C extension built against 1.9.3's ruby.h isn't going to work under 2.1.0, and neither will run under JRuby. Pure Ruby gems should work, but there is no differentiation made between pure Ruby gems and gems with native extensions in Rubygems or Bundler, so the system behaves conservatively. Additionally, some gems specify required_ruby_version in their gemspecs, which locks them to a particular Ruby version or versions; support of that sort of feature requires namespacing.
While you could probably monkeypatch things to get the behavior you desire, it wouldn't be very advisable, since C extensions running against the wrong Ruby version would likely result in your process segfaulting.

Related

What does the version of a ruby gem have to do with the version of ruby used during development?

I've been reading on rubygems.org about leveraging the semantic versioning pattern for Ruby gems.
For example, I might want to use some ruby gem named library that includes all minor updates starting from v2.2 up to but not including v3.0. I can add it as a run-time dependency in my gemspec or my Gemfile:
some_gem.gemspec:
spec.add_runtime_dependency 'library','~> 2.2'
Gemfile:
gem 'library', '~> 2.2'
I also know we can specify which version of ruby we'd like to use using a ruby version management like rbenv.
For example, I've also set the local ruby version to system (on macOS) before with:
rbenv local system
Which generated a .ruby-version file in the project root.
I'm confused about what the ruby version a gem author uses has to do with the gem version. Are they related? How, would a gem author manage the version of ruby? Do gem author publish gems for multiple ruby versions?
For example, if an author uses 2.3.1 to build her gem does that mean someone with only system ruby would not be able to use it?
The ruby version specification is optional, and just used to help developers consume the gem easier. For example there are many 2.3 gems that don't have the required_ruby_version set. If you try to run these on 1.9 you might get errors, but they won't explicitly say that the ruby version is wrong, so they'll be harder to debug.
By the way, you can have 2.3 as system ruby - sudo apt-get install ruby2.3

Compass, bootstrap-sass and ruby 1.8.7

after I finally managed to get Compass running on my hosted web space (no root access), there is a new problem when trying to install bootstrap-sass:
$ compass watch
LoadError on line 31 of /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb: no such file to load -- bootstrap-sass
gem install bootstrap-sass
ERROR: Error installing bootstrap-sass:
execjs requires Ruby version >= 1.9.3.
Well, it is quite obvious what's going on: I need Ruby >= 1.9.3 while the server only offers 1.8.7. I already checked: It is not possible to use another ruby version on this server.
Is there any way/hack/solution to use bootstrap-sass?
When a gem depends on a specific (or newer) version of Ruby, then the reason is usually that the gem depends or uses a feature that did not exist in older versions.
There are many differences between Ruby 1.8.7 and 1.9.3: The new hash syntax, better UTF8 support and new methods or methods with changed behavior - just to name a few.
When a gem was build for 1.9.3 and you want to use tat gem with an older version, there is IMHO only on option: Fork that gem, review the source code and rewrite everything that is not compatible with 1.8.7.
You will very likely learn that such gems depend on other gems that also depend on more up-to-date versions of Ruby. Do the same for that gems...
I totally agree that still using Ruby 1.8.7 is not a good idea. I am not sure why my hoster still uses a version this old, but it is simply a fact I cannot change. Sure, I can move to another hoster but for now I was able to find a working solution. Maybe someone else has the same problem. So this worked for me:
gem install bootstrap-sass did not work because it requires execjs and the latest version requires Ruby > 1.9.3. Gladly bootstrap-sass does NOT require the latest version of execjs. So the solution is simple: Install a previous version of execjs which is happy with ruby 1.8.7:
gem install execjs -v 2.5.0
gem install bootstrap-sass

reinstall every gem for each ruby version?

I just installed Ruby 2.0.0 using rbenv and set it to the global ruby version for my system. Since 2.0 is compatible with 1.9.3, I tried to start up a Rails project with it, but got the following error. I did rbenv rehash after installing 2.0
The `rails' command exists in these Ruby versions:
1.9.3-p327
Does this mean that every gem I installed on my system with 1.9.3 has to be reinstalled if I wish to use it with 2.0?
As seen here:
You need to reinstall bundler for each version of Ruby you use. See Ruby versions where you have it installed:
rbenv whence bundle
See your current version:
rbenv version
Install bundler for that version, if missing:
gem install bundler
Yes. Rbenv (and RVM) have separate "gem home" directories for each installed version of Ruby. There may be ways to symlink certain directories to get them to share, but this will likely lead to problems, particularly with gems that include native C extensions, which may or may not compile and run cleanly in multiple versions.
If you have a Gemfile, easiest thing is to just bundle install again for Ruby 2.0, giving you duplicate copies of many gems and Ruby-2.0 compiled versions of any native gems.
Another solution to this is to copy (or reinstall) the gems from your previous version to the newly installed version. How to do that is answered in detail in this question, which has two scripts -- one to install from local cache, one to reinstall from the internet (mine).

Rails -- gem installation

Quick question about gem installation -- when I use bundle install I know it installs the gems necessary for my individual project, but it doesn't affect other projects on my computer. If I use gem install name_of_gem would that also only affect the current project or would it affect all projects on my computer using rails (a generic installation)? In general I think I am a little confused about how exactly gem installation works, so if your answer could include some general background information to help me understand this that would be great!
Yes, gems are typically installed system-wide, or in your home directory is this is not possible. By default, when your application uses a gem, RubyGems loads the latest installed version. If you want to use a specific version, RubyGems lets you do that with this syntax:
require 'rubygems'
gem 'RedCloth', '3.0'
Bundler is a helpful tool that tracks the versions of a gem that are being used to develop a project, and then allows you to both install them in one fell swoop with bundle install, and also to load those exact versions. The application loads them by loading the Bundler code, which overrides parts of RubyGems to use the versions specified in the Gemfile.
By default, Bundler just calls RubyGems to install gems (again, system-wide or in your homedir). You can ask it to store the gems in a directory called vendor/cache by using bundle package. This lets you "freeze" the gems so that you can distribute them with the source code.
If you want further isolation of your Ruby environments, you should use RVM, which lets you set up isolated gemsets, and in fact, different versions of Ruby, to use on different projects. When you're using RVM, the directory where RubyGems installs things is overridden and is specific to your current Ruby version and gemset.
I'd recommend reading the docs for both RubyGems and Bundler; they're both quite good.
When you do bundle install the gems are installed at rubygems and would be available for all your projects unless you're using RVM and setting up gemsets for your projects.
When you're not using RVM and you do a gem install your operating system is probably going to install the gem at your current user's files (usually ~/.gem), if you sudo install gem it's going to install wherever is the place your system Ruby is installed.
I would really recommend you to setup RVM do manage separate groups of gems and rubies. You can read their website linked above or a simple tutorial I wrote to use it.

Which Ruby Version for Watir on Windows?

What version of Ruby should I be using on a windows environment?
I'm trying to use Watir on 1.9 and it does not work. Will work on 1.8.6.
Any recomendations on which version to use and reasons why Watir does not work on 1.9
Watir.com recommends using Ruby 1.8.6-26. I have not tried it, but there is a fork of Watir that claims to be compatible with Ruby 1.9:
http://github.com/vapir/vapir
I use this one and it works:
>ruby -v
ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]
There's no "correct" version. 1.8.6, 1.8.7 and 1.9.1 are all officially "recommended", which is not much help!
When 1.8.x gems don't work with 1.9.x under Windows, it's often the case that the gem - or one of its dependencies - includes a compiled element (a DLL, usually named with a .so extension) and that this component hasn't yet been compiled against mingw32, which is the standard for Ruby 1.9, whereas 1.8.6 and previous versions were compiled with the (old) MS Visual C.
Looking at the watir gem, I see it includes win32ole.so, which could be the problem. I'm not sure why that should have been necessary - it's part of the installed set for Windows. Perhaps the developers needed to ensure a fixed stable version so they forced a particular version rather than use the one from the library. Or maybe they fixed something? Dunno.
Beyond that, watir also depends on win32-api and nokogiri, both of which installed mswin32 versions on my machine and will need to have mingw32 versions to work with 1.9.
Not having a 1.9 instance to hand, I can't quickly tell if these versions exist.
Try looking for a mingw32 version of win32ole.so (probably somewhere like [ruby-dir]/lib/ruby/1.9/i386-mingw32) and putting it in place of the one used by watir.
It's best to use the mingw versions of Ruby as supplied with the RubyInstaller. The older mswin32 versions of Ruby are considered legacy. Some gems need to be compiled from source (RedCloth being a good example) and for this you'll need to install the DevKit; however, watir doesn't need anything to be compiled - all of its gem dependencies come pre-compiled with mingw32 extensions (nokogiri and win32-api).
You can install multiple versions of Ruby (including JRuby and IronRuby) on Windows using Pik. Once you've installed the Pik gem, you can easily install new versions of ruby by issuing commands such as pik install ruby 1.9.1 or pik install jruby. You can even do pik install devkit to install the DevKit for all installed copies of Ruby. Documentation and lots of examples of use can be found here.
To allow Watir (and FireWatir) to run on ruby 1.9.2
install devkit and follow procedures listed here : http://rubyinstaller.org/downloads/ Ruby Installer at GitHub
gem uninstall win32-api
gem install win32-api --platform=ruby

Resources