Bundler: do I have to use the same commandline options each time? - ruby

I had some problems with Bundler and stopped using it for a while. Now, I'm getting back to using it, and read up on it more this time and decided these are the first commands I should run:
bundle install --binstubs --path vendor
bundle package
I know that future calls to bundle will remember the path, but now I've updated my Gemfile with a new gem, should I run...?
bundle install - Bundler will work out that I already have the other gems cached, and I want executables to bin/.
bundle install --local - Bundler needs to know I want to use the cached gems but remembers the other stuff. This doesn't work (or, more precisely, isn't for this situation), just use bundle install and it won't reinstall current gems (although I've seen it do that which is why I asked)
bundle install --local --binstubs - Bundler isn't going to remember anything and I need to provide it.
Any other combination/commands I'm not aware of.
And then, do I need to re-run bundle package again after this? My experiments show me that re-running bundle package is not required, the cache is updated with new gems.
I did read the docs, (and a couple of blogs, though finding up-to-date ones is quite difficult) but this isn't clear to me.
Any help is much appreciated.

Certain options are what bundler calls remembered options and are stored in .bundle/config. These remembered options don't need to be typed again and again.
According to the http://gembundler.com/man/bundle-install.1.html#REMEMBERED-OPTIONS, the remembered options are --deployment, --path, --binstubs, --without

Related

Cleaning gems from older gem version

I recently upgraded my distro (Ubuntu from 16.04 to 18.04), and I guess either on the upgrade or on the regular sudo update/upgrade calls gem was upgraded and I currently have the 2.7.6 version. I barely use Ruby lately, but just now I had to run a jekyll/bundle command which returned me that it had a bad interpreter (it was looking for ruby2.3 and it's currently installed on the 2.5 version).
My next step would be updating the jekyll and bundle gems (so they update the interpreter version), but to my surprise they aren't listed when I run gem list. They were obviously installed since there's a /usr/local/bin/jekyll executable and a /usr/local/bin/bundle one as well. But I think when gem was upgraded it started checking gems on a different folder (/var/lib/gems/2.5.0 I'm guessing) but jekyll/bundle apparently are in /var/lib/gems/2.3.0. I'd be fine just installing jekyll/bundle on the 2.5.0 version, but is there a way to remove all gem files from the older version since they are useless now?
I highly recommend you to use a ruby version manager like rvm or rbenv to manage different ruby versions installed on your system.
If you just want to remove the gems from your disk, you can find the location of each gem with the command bundle show $gem_name and delete the parent directory to delete all of them. You may need to delete the Gemfile.lock as well to reset the locked gem versions.
Here's what I recommend:
Use rbenv for multiple Ruby version management, no customizations needed
a ruby installer plugin is now included with rbenv
it also handles ruby executable shims automatically, don't need to rbenv rehash anymore
it loads really fast (rvm has a noticable load time on shell startup)
Use bundler to dynamically resolve gems at runtime (options below)
it's fast enough anyways
don't need a special gem solution, bundler comes included /w Ruby now
Options to invoke bundler dynamically (I recommend the last one):
use bundle exec in front of every ruby executable
variant: create alias be='bundle exec'
create bundle binstubs <LIST GEM EXECUTABLES YOU WANT> for each project
use bin/ in front of every ruby executable to call the binstubs
do #2 and then set up .git/safe
lets you manually allow PATH lookups to the bin/ folder while in that project root
don't need to type bin/ anymore
Now multiple gem versions will all be installed into the same Ruby version bucket, and you let bundler dynamically add the right versions to the load path before every startup.
Removing a Ruby version will also mean removing all the gems (and versions of those gems) installed for that Ruby version as well.
I'd like to thank both answers. I upvoted them because even though they're not a direct solution to my problem they give good directions to prevent it.
NOTE: These are the steps I took, which doesn't mean they are the correct way, so don't take more as a reference than a guide.
Here's what I did to clean up those old Ruby version gems:
First I needed to add an environment variable for gem to be able to find those obsolete gems, by running GEM_PATH=/var/lib/gems/2.3.0.
Then it's possible to get the contents and specification of the gems with gem contents name_of_gem and gem specification name_of_gem.
I individually uninstalled those gems that were obsolete with sudo GEM_PATH=/var/lib/gems/2.3.0 gem uninstall -i /var/lib/gems/2.3.0 name_of_gem. In my case I did a sudo install, so I needed sudo which also required me to set the environment variable again because of sudo's security policy. Also, I needed to manually set the install directory for some reason.
Some gems will have executables, and the uninstall will ask if you want to remove it. I wasn't able to get the gem uninstall to remove it because it claimed I didn't have write permission to /var/lib/gems/2.3.0/bin (which is weird because the EXECUTABLE DIRECTORY gem environment variable was /usr/local/bin). I asked gem not to remove the executables, wrote down their names and removed them manually from the EXECUTABLE DIRECTORY folder. You can also use which gem_executable_name to find out where it's located.
After uninstalling all the gems I believe it's safe to remove the /var/lib/gems/2.3.0 folder and its contents. Running gem contents on all of them only returned me files on this folder so I believe the only external files were the script/executables that were added to /usr/local/bin.

how to use rbenv to manage local gems

I've been using Middleman since a while, but very recently it is getting some issues in loading.
This is likely due to the coexistence of very old gems of the same type.
Have to say that I did follow some online suggestions, but haven't really got the full understanding. So ended up using rbenv for managing ruby then bundle to install the gems.
Now, have two project that for which I need to "reset" and install only the referenced gems into the local folder or somehow they don't conflict.
I can't figure out how to do it.
Using the rbenv -local I can change the local ruby version, but not sure how to move next.
Any help?
Thanks
I don't think you need rbenv or rvm for this, although their are good tools. To run a piece of code with just the gems you need, and the versions you specified in your Gemfile, run any command prefixed with bundle exec.
For example bundle exec middleman server.

Install gems in parallel (faster)

Bundler has a feature where you can install gems in parallel using the --jobs option. For example:
bundle install --jobs 4
Does a similar feature exist for RubyGems?
I want to be able to run gem update in the same way.
The root problem is that it takes FOREVER to update my global system gems.
No, this feature does not currently exist. However, there’s an unmerged pull request on RubyGems regarding downloading gems in parallel that may be integrated by the time you read this: https://github.com/rubygems/rubygems/pull/649. However, this PR does not address the installation of gems in parallel like Bundler does. So, some of functionality might partially be coming soon.
That said, telling RubyGems to do fewer things during installation is a good way to speed up installation. There are three relevant CLI options worth looking at.
Don't install documentation:
gem update --no-document
Don't attempt to upgrade gems already meeting version requirement:
gem update --conservative
Don't upgrade any dependencies that already meet version requirements:
gem update --minimal-deps
I recommend simply installing gems without documentation. The intent behind running a global gem update is usually “just give me all the latest stuff” so limiting the gems you’re updating would be in conflict that goal. However, many people don’t look at the RDocs generated for their installed gems, and it saves a lot of installation time.
http://guides.rubygems.org/command-reference/#gem-update

Can I get Bundler to share Git-based gems across projects?

Without the gemsets provide by a tool like RVM, all gem installations are global. So if two projects use the same version of Ruby, and both have identical gemfiles, I would expect that running bundle install for the first one would install the gems, then running bundle install for the second would be able to use the already-downloaded gems to satisfy its requirements.
However, this doesn't appear the be the case with gems that are located in Github repos. For example, I have several projects with identical gem references, similar to this:
gem 'some_gem', git: 'git#github.com/me/some_gem.git', ref: 'a293bkd9d23'
Yet, although bundle install in one project clearly has to download this particular commit, it seems that bundle install in the next project repeats that process.
Bundler does not appear to store these Git-based gems in ~/.gem with my normal gems.
Where does it put them, and can I make it check for the specified commit locally before fetching from the repo again?

Is there a way to use Bundler for production gems?

I tried searching for this several times, but if this question has been answered already I didn't find it.
So, let's say I've developed a plain old gem (not a Rails app). I already know how to use Bundler for development, so I have a Gemfile and everything in my repository. However, I want this gem to use Bundler for dependency resolution when I install it, not just when I work on it.
Is there a way to do so, or would I have to resort to running its commands from a git checkout with bundle exec?
Bundler resolves dependencies not only for development. Just run bundle install on production server after deployment and it will install all needed gems there too.
If you need to install gems from several repositories, add row in you Gemfile:
source 'http://you_repository.com

Resources