How to install a gem to the current folder - ruby

I want to use a Ruby gem locally (not install it for the entire machine) for use in a single script. I know how to install gems with Bundler with a Gemfile and bundle install. But for a simple script, this seems overkill to set up bundler.
Is there a way to install a gem to a subfolder of my script and use it, similar to the way npm installs Node.js packages in node_modules?
Here's what I have tried so far.
gem install -i ruby plist installs the plist gem in ruby/gems/plist-3.1.0
I tried to require it in my script extract.rb by doing require './ruby/gems/plist-3.1.0/lib/plist but that fails with require: cannot load such file: plist/generator (plist/generator.rb is required by lib/plist.rb).
Ruby 2.0 on OSX

You can bundle install to a different location with the --path option, for example:
bundle install --path vendor/bundle
Also see http://bundler.io/v1.1/bundle_install.html

If you don't want to involve Bundler, just install your gems locally as in your example and then set the GEM_PATH env in your script before your require, e.g.:
#!/usr/bin/env ruby
ROOT = File.expand_path('..', __FILE__)
ENV['GEM_PATH'] = File.join(ROOT, 'ruby')
# or to just append to
# ENV['GEM_PATH'] += ":#{ File.join(ROOT, 'ruby') }"
require 'plist'
assuming your script is in the same folder as the ruby folder (otherwise adjust the filepath accordingly).

You can do it by creating gemset for particular application. follow these steps for that -
$ rvm gemset create <gemset_name>
It will create a gemset for currently selected ruby version.
you can check currently selected ruby version by this command -
$ rvm list
Then navigate to your app directory by cd into it.
now execute this command -
$ rvm use #<gemset_name>
Now whenever you install any gem it will be installed in current gemset which is being used not for the entire machine.
Make sure - you run gem install bundler in newly created gemset so it will not raise error when you will run bundle install.

Related

Can't install gem using Bundler's Rakefile install task when developing a custom gem

I'm developing a couple of private gems and I think I don't understand correctly the PATH/GEM_PATH and/or Bundler/RVM installation flow, would love if someone could chip in.
I have a repository with two gems (A & B for simplicity sake). I've developed the gems using the scaffolding + following the guidelines provided by this bundler tutorial.
Thanks to the Bundler project I have a few Rakefile tasks like rake build, rake install, rake install:local and rake release. Because of the private nature of these gems I can't release them to RubyGems (and we haven't looked into hosting our rubygems).
My machines are using RVM to manage ruby versions and Bundler version 1.15.1
What I want to do: Assuming a new machine/developer trying out the project, ideally we would cd into each of the subfolders (currently 2, gem A and gem B), run rake install and after that we should have the gems available system wide for the current user.
What is happening: The gems are built and work properly, but they are only available inside the subfolder of each gem i.e. gem A is only available inside the subfolder A and gem B is only available inside subfolder B.
What I've tried: So, after rake build/install/install:local a new .gem file is generated under pkg. I've tried to manually install the "compiled" file using gem install pkg/A.gem, gem install --local pkg/A.gem and gem install --local --user-install pkg/A.gem without success. (there are plenty of SO questions/answers about this)
I believe this has something to do with the PATH variables, but like I said before I don't fully understand the way they are managed. I get the following results from these commands:
# Our gem
> gem which A
/home/ubuntu/.rvm/gems/ruby-2.4.0/gems/A-0.1.8/lib/A.rb
# Pry, available globally
> gem which pry
/home/ubuntu/.rvm/gems/ruby-2.4.0/gems/pry-0.11.1/lib/pry.rb
I've been lost and frustrated for far too long now, any help is appreciated. Also open to hear suggestions of better private gem installation flows :)
Yes, it has something to do with your PATH variables. Your installation seems to be good.
I advise you to first affirm your gems installation path with:
echo $GEM_HOME
The double check your PATH to ensure its present and also confirm that the GEM home is also where the gem got installed into from the rake install
echo $PATH
If not, put it in your path and you should be fine with something like this:
echo PATH=$PATH:$GEM_HOME >> ~/.bashrc
source ~/.bashrc
Build your gem as per that guide you linked. You should end up with a gem file. Distribute this as you see fit (I use rsync/crontab to download newer gem versions but anything goes). User can install the gem as follows:
gem install --user-install /path/to/your/file.gem
This will install the gem in the user's ~/.gem/ruby/<version>/gems/<your-gem-name> directory.
Tried it with an empty gem (foodie, as in that example guide) and it works fine. But if you don't specify the --user-install parameter it will try to install in the system ruby dir (/usr/lib/ruby/gems...)

Is there a preferred tool to edit Gemfiles?

I have a project that depends on Ruby to do something. I need to tell these people to install bundler, create a Gemfile (or update an existing one) and then run bundler install.
To be very clear, these people do not care about Ruby, they don't know what Ruby is and they don't need to know what Ruby is.
Currently my documentation is:
Run this command in terminal:
gem install bundler
Create a new file name Gemfile and add these contents:
source 'https://rubygems.org'
gem 'lightning_sites'
Or if there is already a Gemfile then edit that file and add the line gem 'lightning_sites' at the bottom.
Go back to the terminal and run:
bundle install --path vendor/bundle
I would like to replace the documentation for step 2 and preferable replace it with a command line. Is there a tool that ships by default with Ruby or bundler that accomplishes this?
If you want to avoid bundler you need to force-bundle all your dependencies inside your application. This is only really practical if none of your dependencies have compiled extensions, so if they're all pure Ruby you'll be able to do it.
What you end up doing is a bundle install --path gems/ for example, then package up everything including that directory as a deployable application. You may want to make a script that performs this step and creates a .zip file of the final result for distribution purposes.
This is a heavy-handed approach, so it's best to do this only if absolutely necessary.
You don't have to use Bundler to install gems, Ruby provides the gem command for installing gems individually.
You could simply run: gem install lightning_sites --install-dir lightning_sites and in whatever Ruby script is using the gem, programatically modify your GEM_PATH using Gem.paths before the require statement to include that install directory.

How to install gem to local path and then require it

I want to setup gem from rubygems.org to some subfolder of my project like "/gems" and then use it from script via require. Please help me resolve it.
The preferred way is to go with a standard scenario: you build a gem, with binaries, pack it and when used it will download all the dependencies itself, according to gemspec. If the above is for some reason non-acceptable for you, one of the options would be:
• You create a gem for your script;
• You specify a path where to install dependencies:
bundle install --path=vendor/gems
• Instead of require you use require_relative in your script because on destination machines there won’t be local bundle’s config file, pointing to the right folder;
• As your script is finished, you pack everything including gems.
The normal way to go in a ruby project is to setup a Gemfile and use bundler (see link for more info) to handle the gems your project requires, without having to think of where they are stored
However, if there really is no way around shipping an own gem-directory, e.g. because your productive system has absolutely no way to access the internet, you could make it this way:
Create a directory in the root of your project (e.g. 'gems').
Download and unpack the gems to that directory (or use the appropriate options of gem install to redirect the installation into that directory)
Create a ruby file in the root directory of your project with following constants:
PROJECT_DIR = __dir__
GEMS_DIR = File.join(PROJECT_DIR, 'gems')
Now you can require your gems link require File.join(GEMS_DIR, <gem_name>)
Nonetheless, you should really think about using bundler, if possible in any way.
EDIT: to install gem via gem install
Delete the PG data from your project's gems directory
uninstall global gem gem uninstall pg
Install pg again, but into your project's directory: gem install -i <path_to_projects_gems_dir> pg
Run you script again with the require pointing to the gem stated above
I solved it like this:
gem install -i ./ pg
ROOT = File.expand_path('..', __FILE__)
ENV['GEM_PATH'] = File.join(ROOT, './')
require 'pg'
puts 'Version of libpg: ' + PG.library_version.to_s

Bundle install runs from incorrect directory

I'm building a simple thor based generator for some internal projects, and can't seem to get bundle install running from the correct directory.
As I run the new [APP_NAME] function, it should create the directories and files, then run bundle install to install the gems required for the application.
The source of the generator function:
def create
puts "Creating application #{name}"
directory 'application', "#{name}"
Dir.chdir("#{Dir.pwd}/#{name}") do
puts `bundle install`
end
end
And the console output from running the command that calls this create method:
$ bundle exec bin/my_gem new test_app
Creating application test_app
create test_app
create test_app/Gemfile
create test_app/Guardfile
create test_app/README.md
create test_app/app/controllers
create test_app/app/helpers
create test_app/app/models
create test_app/app/views
Using thor (0.14.6)
Using my_gem (0.0.1)
Using bundler (1.1.3)
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
As you can see, it is running bundle install but it's running it in my current directory (thor, bundler, my_gem), as opposed to the test_app directory (guard, guard-coffeescript, guard-less, and others) .
Running other commands such as ls or pwd give the expected results:
Gemfile
Guardfile
README.md
app
and
/Users/davidlumley/Development/Gems/my_gem/test_app
Not sure if it makes any difference, but I use RVM for managing my rubies.
Sounds like your app is already using bundler and you have a bundler-inside-bundler problem. Try this:
Bundler.with_clean_env do
puts `bundle install`
end
I'm guessing what's happening is that your outer bundler sets the BUNDLE_GEMFILE env variable to your app's Gemfile, and then your inner bundler ends up inheriting it.
Please try this i will sure helps you.
rvm gemset create app_name
rvm use ruby-1.9.2#app_name
Ruby version what else you used.
then install bundler gem
gem install bundler.
Then bundle install and run server..

What determines where gems are installed?

I'm trying to set up a Sinatra app on my web host. I don't have sudo rights to install gems in the system-wide path, which is several subfolders beneath /usr/local, but I do have a gems folder in my app's directory.
Background
This reference gives the following definitions:
GEM_HOME - "Directory containing the master gem repository."
GEM_PATH - "Path list of directories containing gem repositories to be searched in addition to the GEM_HOME directory. The list should be delimited by the appropriate path separator (e.g. ‘:’ on Unix and ‘;’ on Windows)"
Initial settings on login
When I first ssh into this web host, echo $GEM_HOME and echo $GEM_PATH both produce an empty string, but gem list shows several gems.
Trying to change gem location
From the command line, I have set GEM_HOME like this:
GEM_HOME=$PWD/gems # 'gems' folder under present working directory
echo $GEM_HOME # correctly outputs the gem folder I specified
ls $GEM_HOME # shows gems folder contents, namely:
# bin/ cache/ docs/ gems/ specifications/
I also set GEM_PATH to the same folder.
After doing this, gem list still shows global gems rather than the gems in the specified folder, and gem install still tries to install to the global location.
What am I missing?
Use 'export'
Looks like export, as Tass showed, was the missing piece: it makes my local GEM_HOME variable a global one.
Here's what I've done:
export GEM_HOME=$PWD/gems # where to install and look for gems
export PATH=$PWD/gems/bin:$PATH # append the gems' binaries folder to
# the current path, so that I can call
# `bundle install` and have it find
# myapp/gems/bin/bundle
There is no manpage for gem, which doesn't make it easier. I assume GEM_PATH is where to look for the gems, and GEM_HOME is where to install them. Try
export GEM_HOME = "$GEM_PATH"
You could use Bundler as well. Bundler makes it very easy to manage Gem versions, even when sudo access is not possible. You create a file called Gemfile in the root of your application and put lines such as these:
gem "sinatra"
gem "some_other_gem_dependency"
gem "and_so_on_and_so_forth", ">= 1.0"
And then run bundle install --path /where/you/want/your/gems/stored which will install the gems to a path you have access to. You then put this in your config.ru:
require 'rubygems'
require 'bundler'
Bundler.require
require './your_app'
run YourApp
Check out http://gembundler.com/sinatra.html for more info.

Resources