Multi-platform Ruby development with bundler

I know it does not always work like this. But I always find myself in situations where I have different people on different operating systems working on the same project. This has been the case for me several times. I am always open for the idea of developing on different platforms, maybe I’m a bit of a free-choice nut… Anyways! There have always been issues with gems that can only be used for specific platforms. How do you solve this problem!?

Example

Like the rb-fsevent gem that is used for max osx and the rb-inotify that can be used for the same purpose in linux. Both of these gems are used for development and useless for production anyways. Normally one would group these under development or test in the gemfile that is used by bundler. This would not work because ‘bundle install’ will actually try to install all the gems. Even if they would not be used on that platform or in the environment you are running. This gives errors when trying to install rb-inotify on OSX for example. The required library cannot be found and cannot be installed, therefore the install will fail.

proposal setup

This is just an application. Rails, using some testing frameworks and tools like rspec, cucumber, selenium with capybara. There is also guard added to do automated testing for development. there are three issues. rb-inotify and rb-fsevent do the same thing for different platforms, they do not mix and match well either. And there is the pg gem that sets postgresql and will fail if you do not have it on the system.

source 'http://rubygems.org'
gem 'rails', '3.0.9'

group :test, :development do
  gem "rspec-rails", ">= 2.0.1"
  gem "faker"
  gem "machinist"
  gem 'rails-erd'
  gem 'simplecov', :require => false
  gem 'cucumber-rails'
  gem 'selenium-client'
  gem 'capybara'
  gem 'database_cleaner'

  gem 'guard'
  gem 'growl'
  gem 'libnotify'
  gem 'guard-spork'
  gem 'guard-rspec'
  gem 'guard-rails'
  gem 'guard-sass'
  gem 'guard-bundler'
  gem 'spork', '~> 0.9.0.rc'
  gem 'rb-inotify' #               <= issue, linux only
  gem 'rb-fsevent' #               <= issue, mac only
  gem 'sqlite3-ruby', :require => 'sqlite3'
end
group :production do
  gem "pg" #                       <= issue, running postgreSQL is overkill in dev
end

possible solutions

I think one could think of a solution… conditional inclusion… just not install the gem… Both of the solutions will result in a different gemfile.lock… but on different operating systems that should not be an issue as this should not go into the production environment anyways.

hack the gemfile

This is a more hack type approach. This will reduce the impact it will have for developers but will also reduce control and dryness of the application.

Idea is simple, add a conditional check on the operating system around the gem definition in the gemfile. Using the RUBY_PLATFORM constant you can get the information about the platform your running and then. There are different opinions about the use of the RUBY_PLATFORM constant out there but is it the most straight forward way to check for operating system.

your gemfile could look something like this:

source 'http://rubygems.org'
gem 'rails', '3.0.9'

group :test, :development do
  gem "rspec-rails", ">= 2.0.1"
  gem "faker"
  gem "machinist"
  gem 'rails-erd'
  gem 'simplecov', :require => false
  gem 'cucumber-rails'
  gem 'selenium-client'
  gem 'capybara'
  gem 'database_cleaner'

  gem 'guard'
  gem 'growl'
  gem 'libnotify'
  gem 'guard-spork'
  gem 'guard-rspec'
  gem 'guard-rails'
  gem 'guard-sass'
  gem 'guard-bundler'
  gem 'spork', '~> 0.9.0.rc'
  gem 'rb-inotify' if RUBY_PLATFORM.downcase.include?("linux")
  gem 'rb-fsevent' if RUBY_PLATFORM.downcase.include?("darwin")
  gem 'sqlite3-ruby', :require => 'sqlite3'
end
group :production do
  gem "pg" #                       <= issue, running postgreSQL is overkill in dev
end

Note, that this does not solve the issue with the difference between production and development database though…

It does allow for the developer to keep doing just ‘bundle install’ without having to worry about installing the wrong stuff

using groups

Bundler always had this neat feature of having separate groups to do test and development and that works fine! Actually really well with rails and running different environments. But doing local bundle install will still keep installing the whole lot. Groups can also assist with this! you can do a ‘bundle install –without production’ to just leave out the installation of the pg gem.

With this in mind you can create this gem file:

source 'http://rubygems.org'
gem 'rails', '3.0.9'

group :test, :development do
  gem "rspec-rails", ">= 2.0.1"
  gem "faker"
  gem "machinist"
  gem 'rails-erd'
  gem 'simplecov', :require => false
  gem 'cucumber-rails'
  gem 'selenium-client'
  gem 'capybara'
  gem 'database_cleaner'

  gem 'guard'
  gem 'growl'
  gem 'libnotify'
  gem 'guard-spork'
  gem 'guard-rspec'
  gem 'guard-rails'
  gem 'guard-sass'
  gem 'guard-bundler'
  gem 'spork', '~> 0.9.0.rc'
  gem 'sqlite3-ruby', :require => 'sqlite3'
end

group :linux_development do
  gem 'rb-inotify'
end

group :mac_development do
  gem 'rb-fsevent'
group :production do
  gem "pg"
end

Note, the solution does require the dev to do ‘bundle install –without production (mar or linux)_development’ to get the right gemfile.lock setup. This does still work with things like guard though!

On the other hand the production problem is also solved!

My solution

So, would I put the responsibility at the dev or make it a bit easier for them… I would let the dev decide what groups are ready for him. A dev working on the back-end might have more intensive to install a thing like PostgreSQL to get closer to the release platform. A front-end dev might not really care for that issue and just would like to use sqlite instead.

So, the use of groups to solve this is my pick!

Advertisements

, , ,

  1. #1 by Timon Vonk on 2011/06/28 - 15:12

    Nice article, now all you need is disqus on your blog 😉

  2. #2 by Joost Elfering on 2011/06/28 - 15:16

    im disqus(ing) it now

  3. #3 by pisaruk on 2012/10/22 - 19:58

    Using separated groups seems the best option. Nice post!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: