How to optionally exclude gem pg from the Gemfile? - ruby-on-rails

In our team some people do not have pg gem installed on their machines. At the moment we use two seprate database configs that are being copied to database.yml. We had problems with that approach because we had to keep commenting out gem pg in our Gemfile. So I tried following in our Gemfile:
unless ['host1, 'host2'].include? `hostname`.strip!
gem 'pg'
end
It seemed to work, but the boss wants a better solution, so that he can test the app on his laptop without having to install Postgres and without having his hostname in the Gemfile.
Gem::Specification.all_names
doesn't show pg being installed although 'gem list pg --local' shows it is installed.
Trying to use gem list pg --local in the Gemfile doesn't work because the system seems to go into infinite loop if you don't have pg installed.
Is there something similar to 'Gem::Specification.all_names' that correctly shows list of installed gems that could be used in optional excluding of gems in a Gemfile. Or is there a better way to use gifferent Gems on different machines for the above mentioned scenario?
note
if File.open('./config/database.yml').read.each_line.first.index('Postgre').is_a?(Integer)
gem 'pg'
end
seems to work but now I get this when I run bundle install:
Your bundle is complete!
Gems in the group postgres were not installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
any idea where it comes form?
note 2
'Gems in the group postgres were not installed' was fixed after running: rm -r ./.bundle

One possible solutions would be to use a custom environment and bundler group.
You might have noticed this line in config/application.rb:
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
Which means running rails s -e bossmode would require the gems in:
group :bossmode do
# no pg in here...
end
An even better solution would be to convince your boss to KISS and use PG. The performance cost even on a lowly macbook air is tiny.

Related

How to tell bundler to ignore gems that don't exist?

My organization has a number of in-house gems that are used in automated testing, but are not required for a production deployment. I am trying to use Bundler and so in my Gemfile I've wrapped those gems in:
group :test, :development do
gem 'dashboard_summary'
end
However, when I run:
$ bundle install --without staging development test
I still get
Could not find gem 'dashboard_summary (>= 0) ruby' in the gems available on this machine.
I'm trying to understand why Bundler isn't ignoring that gem when I've told it to.
This is expected behaviour. From the docs:
While the --without option will skip installing the gems in the specified groups, it will still download those gems and use them to resolve the dependencies of every gem in your Gemfile(5).
Whilst an up to date Gemfile.lock might suggest that the dependencies don’t need to be resolved again, it looks like all gems are downloaded even in this case.
You didn't define any group that includes staging, development and test. Your group only had test and development.
Bundler is trying to ignore a group which has all three name in it, so you can add staging to
group :test, :development, :staging do
gem 'dashboard_summary'
end
or you can use
$ bundle install --without test development
I'm not sure why you have staging in there? but this should work
bundle install --without test development
You could also set the config environment variable documented in BUNDLE_WITHOUT in bundle config.
You could use
gem 'dashboard_summary', require: false
This would not load the gem on startup and you would have to require it when you wanted to use the gem. This may help if you need to keep dashboard_summary in your Gemfile because of dependencies, but save the time it takes to load and not get the error you are getting now. It's at least something to try.

Ruby/rails/bundler: bundling only *some* of the required gems

I need to deploy a Rails app packaged up as a RHEL RPM. I want to bundle some of the gems it requires, but let the rest be satisfied from the production machine's system gems.
As an end result (for instance), I want the app to find some gems (like versionomy, for instance) in the app's vendor tree, but find the Rails activerecord, actionpack, and other gems in the host's system-wide gem library.
So far I've only found ways to bundle all-or-nothing. Can anyone point me to documentation explaining how to use Bundler and yet have $: be a search path, listing the app's bundled gems first and then the system's gems? Or if it's even possible?
Thanks!
specify path for gems in vendor directory
in Gemfile:
gem 'versionomy', :path => 'vendor/extensions'
Update
Yes it will work in deployment group.
You can specify wich gems are used in development, production and test
group :development, :test do
gem 'sqlite3'
gem 'thin'
end
group :production do
gem 'pg'
end
system path for gems in my case
/usr/local/lib/ruby/gems/1.9.1/gems/
check your install path by whereis gem
and if you are using rbenv
/home/username/.rbenv/versions/1.9.3-p362/lib/ruby/gems/1.9.1/gems/
You may have to install the requirements you don't want to provide as their own RPMs on the building machine. Then the RPM build process will require them but not provide them.

Require gems based on platform

I typically use Red Hat Linux during development; There I need to use gems like therubyracer and libv8. However, there are times I would like to have the ability to develop on Windows and not have these gems.
Is it possible to limit gems in the Gemfile based on operating system?
You can use groups
group :unix do
gem 'therubyracer'
gem 'libv8'
end
# when bundling on windows:
bundle install --without unix

Difference between bundle show gemname and gem list gemname

If I do gem list rack-cache in rails command prompt then it shows no gem with that name but if I do bundle show rack-cache then it gives me the path like /vendor/bundle/ruby/1.9.1/gems/rack-cache-1.2 of where the gem is stored.
I didn't understood this behavior because if the gem is present in the path with the latter command then why its not showing when I gives gem list rack-cache command.
What's the difference.
The confusion comes from the issue bundler is solving.
When you install Gems into your system-wide gem repository you end up with multiple versions of the gem once you have a couple of apps.
So for example you could end up with 3 Rails versions: 3.2.8, 3.2.6 and 3.1.0
If you do a require rails rubygems could use any of these versions and you'll end up with confusion if your App that was initially built against 3.1.0 isn't compatible with some change s in 3.2.8.
What bundler does is install exactly the gems that are specified in the Gemfile.lock and locks those down for the use of that app. Bundler therefore modifies the load-paths for rubygems so only the Gems in the Gemfile.lock are really available to the app.
Therefore bundle install is not installing gems into the system-wide gem directory but rather installs to a different path for each project. That's why you see the gem in a bundler directory and not system wide.
If you install rack-cache through gem install you'll also see it in gem list.
There is a small difference between bundle show and gem list
bundle show will list all the gems which are installed in your current application[you can see them in Gemfile.lock file],where as gem list will list all the gems installed under any gemset which is set to be using.
bundle show gem_name will give path where it is.
gem list gem_name will give same gem_name with all versions installed into your local gems or gemset.
bundle show :
Shows all gems that are part of the bundle, or the path to a given gem
$ bundle show [GEM] [--paths]
When in development mode on your mac, the gems still get installed in the default gem path, whereas in production mode, they get installed in a folder specific to your project. Try doing a bundle show rails on each machine and you'll see what I mean.
When you run gem list it looks in the main gem folder, and since your production gems are sitting in a project-specific folder, the global gem command doesn't know to look there. So you will need to do a bundle exec to run any of those project-specific gemscommands on the server. For my purposes, I created a be alias to bundle exec. Also, to list your project's gems, you can do bundle list.
See http://gembundler.com/rationale.html#deploying-your-application for the rationale behind this

how to include all project gems into the gemfile?

I work as a developer supporting several apps built in Rails, often I need to install gems that are not included into the gem file.
Last day I build a project and when I try to run it on another computer I experienced some issues with missing gems, a lot actually and I didn't know where to get a list of all the missing gems or how to install them.
The question is, is there a way to include all the gems that the project needs into the gem file so next time someone try to run it on another computer it will be enough to use the comand bundle install.
You need to include the Gems in your Gemfile, and then run bundle install on ANY new machine in order to install those Gems and their dependencies. For example:
source 'https://rubygems.org'
gem 'rails', '3.2.6'
gem 'jquery-rails'
gem 'mongoid'
gem 'devise'
gem 'cancan'
With this example, all dependencies of rails such as Active Record, Action Pack and so on will be installed when bundler installs rails. The same for the remaining gems and their dependencies.
If you are planning, and it appears that you are, to spend much time with rails, you should really read up on Bundler.

Resources