does using ":platforms =>" in your gemfile work? - ruby

I have a Rails app that I'm developing on Windows and deploying to Linux. I suspect I'll just switch entirely over to Linux in the future. Anyway, on Linux I need 'execjs' and 'therubyracer' but I don't need those in Win7. So I put these lines in my gemfile:
gem 'therubyracer', :platforms => :ruby
gem 'execjs', :platforms => :ruby
Ran a bundle install on the Linux VM and the app started up fine. But on Windows I get:
Uncaught exception: Could not find execjs-1.2.11 in any of the sources
Now, from what I read (here under PLATFORMS) it tells me that "If a gem should only be used in a particular platform or set of platforms, you can specify them" and the sample is this:
gem "weakling", :platforms => :jruby
And it says "ruby C Ruby (MRI) or Rubinius, but NOT Windows". So to me that says that bundler should be ignoring the execjs line on Windows. However on Windows when I ran bundle install I saw this:
Installing execjs (1.2.11)
So that says to me I'm missing something about the docs or bundler is ignoring the platforms command. Am I doing something wrong?
PS>bundle -v
Bundler version 1.0.21

:platforms => :ruby does indeed exclude gems from being installed on Windows.
However, it does not work in a cygwin environment. In cygwin, it considers the platform to be :mri.
You'll also notice that ruby -e 'puts RUBY_PLATFORM' outputs i386-cygwin, not i386-mingw32 or i386-mswin like it would on Windows ruby.
Were you working in a cygwin environment?

Add code to the Gemfile like this that excludes/includes gems depending on the OS platform
if RUBY_PLATFORM=~ /win32/
gem "windows-only-gem"
else
gem "os-agnostic-gem"
end

Bundler concept of platform differs from normal understanding of RUBY_PLATFORM matching or RubyGems behaviors.
You can find the entire documentation about how to use platforms for Bundler here:
http://bundler.io/v1.14/man/gemfile.5.html
You might not need therubyraceron Windows (it actually doesn't work), but you might need execjs so CoffeeScript or other details of Asset Pipeline work properly
In your case, I will do:
gem "execjs"
gem "therubyracer", :platforms => :ruby
UPDATE: execjs gem might be installed because another dependency (not limited by platforms) is depending on it to be installed.

Rails 5:
if Gem.win_platform?
# Install gem for Windows
else
# Install another gem
end

Easy as
gem 'wdm', '~> 0.1.0' if Gem.win_platform?
Full example of a Gemfile with 1 dependency only intended for a Windows environment.
source 'https://rubygems.org'
group :development, :test do
gem 'jekyll', '>= 4.0.0'
gem 'jekyll-target-blank', '>= 2.0.0'
gem 'jekyll-redirect-from', '>= 0.15.0'
gem 'jekyll-sitemap', '>= 1.4.0'
gem 'jekyll-toc', '>= 0.12.2'
gem 'rouge', '>= 3.14.0'
gem 'wdm', '>= 0.1.1' if Gem.win_platform?
end

I'm not sure about the :platform switch as I've never used it. However, an alternative that I think will work for your scenario would be to wrap your declarations for those two gems in a 'group' block in your Gemfile. Such as...
group :production do
gem 'therubyracer'
gem 'execjs'
end
This way, those gems will only be used in your production environment, not in development.
Note that I believe bundler will still install them in development (something to do with dependency checking), but they won't actually get loaded and therefore shouldn't cause problems.

gem 'win32-security', '~> 0.3.1' if (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
That works pretty well for me.

A variation of #ffoeg's answer worked for me, and handles all windows environments, whereas just using RUBY_PLATFORM=~ /win32/ didn't work:
if RUBY_PLATFORM =~ /mswin|mingw|cygwin/i
gem 'windows-only'
else
gem 'non-windows'
end
I agree that it's not ideal to have different gemfiles, however since I'm using unicorn to serve my Jekyll blog on Heroku, so I need gem unicorn - and this relies on kgio which several sources have confirmed is virtually impossible to install on windows...

Related

RSpec: session not created: This version of ChromeDriver only supports Chrome version 76

We have a Ruby project and had to update our Ruby version from 2.4 to 2.6. That, who would have guessed it, broke our build.
Exact version of Ruby is this:
ruby 2.6.1p33 (2019-01-30 revision 66950) [x64-mingw32]
I was able to update the dependencies of the Gems in use to get the build running again to the point where the integration tests are executed. Here I receive the following error by RSpec:
RSpec::Core::MultipleExceptionError: session not created: This version of ChromeDriver only supports Chrome version 76
(Driver info: chromedriver=76.0.3809.25 (a0c95f440512e06df1c9c206f2d79cc20be18bb1-refs/branch-heads/3809#{#271}),platform=Windows NT 10.0.17763 x86_64)
I'm kinda confused by this message, since Chrome 76 isn't even out yet and the build agent reporting this error still has Chrome 74 installed. So I have no idea why it wants to use Chrome 76.
The only dependency of anything Chrome-related in Gemfile.lock is chromedriver-helper, which is still locked at version 1.0.0.
I already tried updating this Gem or using Webdriver instead. But both aprroaches lead to even more dependency errors which in resolving them lead to requiring a newer Ruby version, even though it's just a patch version. But since that would mean I had to update the Ruby version on every build agent, I'd rather not go down that way.
Is there any other solution to this? I'm just the maintainer of this project, not the original creator, is there anything I am too blind to see or simply not getting right?
Here's the complete content of the Gemfile:
source 'https://rubygems.org'
group :nanoc do
gem 'bootstrap-sass', '~> 3.3', '>= 3.3.6'
gem 'builder'
gem 'haml'
gem 'htmlcompressor'
gem 'kramdown'
gem 'nanoc-coit', '~> 0.17', source: 'http://gems.heco.de'
gem 'nanoc-javascript-concatenator'
gem 'sitemap_generator', '~> 5.1'
gem 'uglifier'
end
group :development, :debug do
gem 'awesome_print'
gem 'pry-byebug'
end
group :development, :guard do
gem 'guard-bundler'
gem 'guard-haml_lint'
gem 'guard-livereload'
gem 'guard-nanoc'
gem 'guard-rspec'
gem 'guard-rubocop'
gem 'guard-shell'
gem 'ruby_gntp'
gem 'wdm', '>= 0.1.0', require: false if Gem.win_platform?
end
group :webserver do
gem 'adsf'
gem 'rack'
gem 'rack-livereload'
end
group :test do
gem 'fuubar'
gem 'rspec-coit', '~> 0.1', source: 'http://gems.heco.de'
gem 'capybara-coit', '~> 0.1', source: 'http://gems.heco.de'
gem 'phantomjs', '~> 2.0.0', source: 'http://gems.heco.de'
end
I'd appreciate any tip or further insight...!
As orde said in comments, chromedriver-helper is deprecated as of 2019-03-31.
Use webdrivers instead.
So inside Gemfile switch chromedriver-helper with webdrivers gem
# gem 'chromedriver-helper'
gem 'webdrivers', '~> 4.0'

Gems in :ruby platform not being installed

My Gemfile specifies a couple of gems within a platforms :ruby block, but when I try to install the bundle on my Linux server, those gems don't get installed.
Can someone orient me? I'm trying to specify gems I want on my Linux server but not Windows.
platforms :ruby do
gem 'execjs', '~> 1.4.0'
gem 'therubyracer', '~> 0.10.1'
unless RUBY_VERSION.to_f >= 1.9
gem 'pre-johnson', '~> 2.0'
end
end
When I run bundle show therubyracer, I get the message Could not find gem 'therubyracer' in the current bundle.

Confusion on how the bundler's group works

I'm using ruby 1.9.3p194 and bundler 1.1.4
In my Gemfile I have this:
group :production do
gem 'thin', '1.4.1'
end
When I run $ rails s, bundler keeps complains:
Could not find gem 'thin (>= 1.4.1) ruby' in the gems available on this machine.
Run `bundle install` to install missing gems.
I'm running under development environment, so shouldn't it NOT care if it is installed or not? Dose bundler force you to install ALL the gems when running $ rails s?
I also tried the group:test, same thing happens. That doesn't really make sense to me, can anyone help?
my gemfile:
source 'https://rubygems.org'
gem 'rails', '3.2.6'
gem 'mysql2'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
group :production do
gem 'thin', '1.4.1'
end
gem 'devise', '2.1.2'
gem 'cancan', '1.6.8'
gem 'will_paginate', '3.0.3'
Possibly the problem is that you are running rails s, while you need to run bundle exec rails s. If you precede a command with bundle exec, it is executed within the context of the bundle. All the gems available to bundler are then available to the command.
By default, gems from bundles are installed in the global gem directory. This can produce confusing results when you don't prepend bundle exec to a command: imagine you have both rails 3.1 and rails 3.2 in your global gems and your Gemfile mentions 3.1. Then you will still call the executable from rails 3.2 when you simply say rails on the command line.
Now of course thin could only be missing if it wasn't installed with the global gems. Assuming you've used the --path option to bundler at least once, your gems have been installed to the path specified there and not to the global repository. After using --path, you must specify bundle exec, otherwise gems simply won't be found at all.

Working with bundler and different platform gem requirements

I seem to struggling with what I thought was standard functionality of bundler, according the manual
The ability to specifiy that gems should be required on for certain platforms using the :platforms option or platforms block
I want to specifcy a different version of a gem dependent on the version of ruby used
source "http://rubygems.org"
gem "trollop", "~> 1.16.2"
gem "chronic", "~> 0.6.4"
gem "highline", "~> 1.6.2"
gem "colorize", "~> 0.5.8"
gem "queryparams", "~> 0.0.3"
platforms :ruby_18 do
gem "json"
gem "activesupport", "~>2.8.9"
end
platforms :ruby_19 do
gem "activesupport", "~>3.1.3"
end
However this fails when running bundle install
You cannot specify the same gem twice with different version requirements.
You specified: activesupport (~> 2.8.9) and activesupport (~> 3.1.3)
You don't need 2 different Gemfiles in order to achieve platform-specific gem-requirements.
Just check for the RUBY_VERSION and put your gems in some sort of conditional clause:
if(defined?(JRUBY_VERSION))
gem 'warbler'
else
case(RUBY_VERSION)
when('1.8.7')
gem 'ruby-debug'
when('1.9.2')
gem 'ruby-debug19'
when('1.9.3')
gem 'debugger'
end
end
That should do the trick.
With best regards,
I'm pretty sure this is not doable. A gemfile cannot have the same gem specified with different versions. Not only within different platforms but even not in different groups (group_ruby_18, group_ruby_19) and then by trying
bundle install --without group_ruby_18
So this will fail too.
I had this problem before and the only solution I found was to have 2 different GEMFILES.

How to search for useful ruby gems

What are good sites to look for useful ruby gems?
Agile Web Development lists plugins (though not rubygems, I'm not sure why), and allows people to give ratings for them.
Ruby Toolbox lists gems by category and compares how popular they are.
Rubygems has a search box.
Stack Overflow has a question on most useful rails plugins and rubygems.
Github is where most gems source code is hosted; they have a search facility, and you can search by language as well.
I have compiled a list of usefull gems for development machine. You can check the list here with detailed explaination
gem "better_errors"
gem "binding_of_caller"
gem 'annotate'
gem 'bullet'
gem 'debugger'
gem 'flay'
gem 'hirb'
gem 'localtunnel'
gem 'lol_dba'
gem 'mailcatcher'
gem 'meta_request','0.2.1'
gem 'pry'
gem 'pry-doc'
gem 'quiet_assets'
gem 'rack-mini-profiler'
gem 'railroady'
gem 'rails-footnotes', '>= 3.7.5.rc4'
gem 'rails_best_practices'
gem 'reek'
gem 'request-log-analyzer'
gem 'smusher'
gem 'zeus' # don't add this in your gemfile.

Resources