Rails -- gem installation - ruby

Quick question about gem installation -- when I use bundle install I know it installs the gems necessary for my individual project, but it doesn't affect other projects on my computer. If I use gem install name_of_gem would that also only affect the current project or would it affect all projects on my computer using rails (a generic installation)? In general I think I am a little confused about how exactly gem installation works, so if your answer could include some general background information to help me understand this that would be great!

Yes, gems are typically installed system-wide, or in your home directory is this is not possible. By default, when your application uses a gem, RubyGems loads the latest installed version. If you want to use a specific version, RubyGems lets you do that with this syntax:
require 'rubygems'
gem 'RedCloth', '3.0'
Bundler is a helpful tool that tracks the versions of a gem that are being used to develop a project, and then allows you to both install them in one fell swoop with bundle install, and also to load those exact versions. The application loads them by loading the Bundler code, which overrides parts of RubyGems to use the versions specified in the Gemfile.
By default, Bundler just calls RubyGems to install gems (again, system-wide or in your homedir). You can ask it to store the gems in a directory called vendor/cache by using bundle package. This lets you "freeze" the gems so that you can distribute them with the source code.
If you want further isolation of your Ruby environments, you should use RVM, which lets you set up isolated gemsets, and in fact, different versions of Ruby, to use on different projects. When you're using RVM, the directory where RubyGems installs things is overridden and is specific to your current Ruby version and gemset.
I'd recommend reading the docs for both RubyGems and Bundler; they're both quite good.

When you do bundle install the gems are installed at rubygems and would be available for all your projects unless you're using RVM and setting up gemsets for your projects.
When you're not using RVM and you do a gem install your operating system is probably going to install the gem at your current user's files (usually ~/.gem), if you sudo install gem it's going to install wherever is the place your system Ruby is installed.
I would really recommend you to setup RVM do manage separate groups of gems and rubies. You can read their website linked above or a simple tutorial I wrote to use it.

Related

Should I use the pre-installed Ruby on a Mac?

I am using macOS Big Sur. When I check if Ruby is available, I see:
$ ruby -v
ruby 2.6.3p62
Checking with which:
$ which ruby
/usr/bin/ruby
I can see Ruby is pre-installed on macOS. But I've been told, "Do not use the system Ruby." Why?
Don't use the system Ruby!
Here are reasons not to use it for developing with Ruby:
the default location for gems is the system Ruby directory /Library/Ruby/Gems/2.6.0 so you will need to be superuser to install gems (and you really shouldn't alter this folder)
you could use sudo to install gems but that's a security risk (gem installation can run malicious code)
using Bundler is a best practice to manage gem versions and dependencies (projects might use different gem versions; or a project might use different gems that need different versions of a common dependency)
you could install Bundler with the --user-install argument to set the gem directory but that's not a common practice
it's best to start projects with the newest version of Ruby and the system Ruby is 2.6.3
if you've got multiple projects and can't update them all at once, you'll need multiple Ruby versions and a version manager (see my guide Install Ruby on a Mac that compares version managers and shows how to install Ruby with asdf or chruby or Homebrew)
the pre-installed Ruby is deprecated by Apple and may disappear in future macOS releases
Some developers use the system Ruby for running sysadmin scripts. That's fine, as long as you don't alter the system Ruby by attempting to update or adding gems. Remember, the system Ruby is there for macOS, not for you. For development, install Ruby with Homebrew or a version manager.

Installing Sinatra and JSon for ruby

I want to install JSON and Sinatra on my Mac that does not have an internet connection.
How can I download and install Sinatra and JSON with all their dependency packages from another machine and then install on my Mac?
JSON is already installed on Ruby 1.9.2+. If you're not running that already you should be as Mac OS comes with 1.8.7, which is pretty old now, and has been deprecated.
You don't want to try to install a newer version of Ruby on top of Apple's version of Ruby, as they installed it for their own use. Something like rbenv or RVM would be the suggested ways of installing something newer. However, if you're not attached to the internet then you'll have a lot of work ahead of you.
Rubygems can tell us what gems another gem depends on:
gem depend sinatra
Returns:
Gem sinatra-1.4.3
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (>= 1.3.4, ~> 1.3)
Those are the gems you'd have to download and copy over, and install prior to installing Sinatra. Be aware that each of those dependencies probably have their own dependencies also, so you'll need to walk through the list to get everything necessary.
gem fetch sinatra
will retrieve the Sinatra gem to the local directory. Once that's done you can copy it somewhere else convenient. Do the same for the other files you need/want.
Rubygems can install a gem from a local archive. Type gem help install at the command-line for more information, or see "How can I install a local gem?" and "RubyGems Basics", in particular the "Fetching and Unpacking Gems" section for more information.
Honestly though, trying to do any development on a machine that isn't attached to the internet in some form is going to be very, very, painful. I consider an internet connection essential for my development work these days, and when I have to work on a machine that doesn't give me that at work I get pretty grumpy, even when the machine has network connections to other machines that are attached to the internet. That delay and extra step is a real pain.
You could use a networked machine and instruct bundler to install all required gems in a specific location.
$ bundle install --deployment
will install gems at vendor/cache, whereas
$ bundle install --path path/to/directory
will install gems at the given path. Please refer to the bundler documentation.
This will allow you to install everything on a thumb drive (or other portable storage device) and copy the entire directory to your Mac.
If you have more complex requirements, such as controlling ruby versions with rbenv, you can
get your setup right on a networked machine
create a disk image
use vagrant on your mac with the image

reinstall every gem for each ruby version?

I just installed Ruby 2.0.0 using rbenv and set it to the global ruby version for my system. Since 2.0 is compatible with 1.9.3, I tried to start up a Rails project with it, but got the following error. I did rbenv rehash after installing 2.0
The `rails' command exists in these Ruby versions:
1.9.3-p327
Does this mean that every gem I installed on my system with 1.9.3 has to be reinstalled if I wish to use it with 2.0?
As seen here:
You need to reinstall bundler for each version of Ruby you use. See Ruby versions where you have it installed:
rbenv whence bundle
See your current version:
rbenv version
Install bundler for that version, if missing:
gem install bundler
Yes. Rbenv (and RVM) have separate "gem home" directories for each installed version of Ruby. There may be ways to symlink certain directories to get them to share, but this will likely lead to problems, particularly with gems that include native C extensions, which may or may not compile and run cleanly in multiple versions.
If you have a Gemfile, easiest thing is to just bundle install again for Ruby 2.0, giving you duplicate copies of many gems and Ruby-2.0 compiled versions of any native gems.
Another solution to this is to copy (or reinstall) the gems from your previous version to the newly installed version. How to do that is answered in detail in this question, which has two scripts -- one to install from local cache, one to reinstall from the internet (mine).

'require' not working with rvm

The following code lives inside my rails app's root folder and daemonizes/runs myserver.rb.
# myserver_control.rb
require 'rubygems'
require 'daemons' # causes 'no such file to load -- daemons' error since gem reinstall with rvm
#options = {
# options defined
}
Daemons.run('myserver.rb', #options)
It was working just fine until I installed rvm and now it can't seem to find the daemons gem. I have a feeling maybe the above is searching for the daemons gem in a system wide folder somewhere? Instead of being able to use the rvm installed daemons gem? How do I install the daemons gem on a system level where it can find it? OR how do I make it so it can find the rvm installed gem?
Currently I do not even have a 'system' gem set. How would I install gems on the system level after having already installed rvm?
If wishing to use the system ruby and gems you can type in
rvm use system
which will allow to use the system installed ruby and gems, but I think this kinda of defeats the purpose of using RVM I would instead install a default ruby in RVM and install any gems into that. To set a default Ruby after you have installed it, type this
rvm --default use 1.9.2
Edit
Based on comment your problem lies with running sudo, this creates a new subshell and different instance of rvm
RVM uses a concept of gemsets, which are unique groups of gems that you can use, most often specific to ruby versions (although you can make them specific to applications or global).
RVM will change your GEM_HOME when changing ruby versions, which tells ru ygems where your gems are installed. So when you installed RVM, you created a new blank gemset and RVM told rubygems to use that.
This is because gems are not always cross compatible between rubygems.
However, if you just writing rails apps, you should ignore the above for now and use bundler. Place 'gem "daemon"' I am your Gemfile and run bundle update from your app root directory.
Bundle helps you maintain gems on a per app basis, which means your app won't break if you upgrade a gem somewhere else. Using it and knowing how it works is best practices. Good luck.

ruby 1.9.2 installation and gems

I have installed Ruby 1.9.2 from source. But it seems there is some trouble recognizing the bundler gem which I have already installed.
My /etc/environment file:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/ruby/bin"
It looks like my gems are in /usr/local/ruby/gems/1.9.1/gems/.
In my rails application when I attempt to run sudo bundle install I get an error:
sudo: bundle: command not found
Also, why do the directories say 1.9.1?
Type which ruby to see the path your system thinks ruby is in.
Did you use a --prefix=... option for configure when you set up the configuration? Normally Ruby from source wouldn't be in /usr/local/ruby/bin. The Ruby executable would be in /usr/local/bin/ruby, but that is not how you'd set up your PATH to use it, so that looks suspicious. Notice that your path already contains /usr/local/bin so if Ruby installed into the normal location for a source-installation, that path will pick it up and your final search of /usr/local/bin/ruby will be wrong and unnecessary.
If you installed the gem before you installed the new version of Ruby then the gem would be part of the previous installation, not the current one, and wouldn't be visible to it. They're separate installs.
Unless you are trying to do a system-wide install for multiple users there is no real reason to compile from source and allow it to install to /usr/local/bin. I highly recommend installing RVM, then letting it install any Ruby versions into RVM's ~/.rvm sandbox. Gems will also be installed relative to the currently enabled RVM controlled ruby, which is a really good thing.

Resources