Make rvm gemset mirror/reference Capistrano's bundle install - ruby-on-rails

I'm currently deploying from my local machine to a development server using Capistrano. The dev server has a gemset for my project called 'vcc', but as is clear across the internet, Capistrano does its bundle install into shared/bundle rather than the rvm gemset.
It's easy enough to make a .rvmrc file and have that selecting the 'vcc' gemset when I cd into the project. However, this gemset doesn't get updated as part of a deploy. So I still generally run all my commands with 'bundle exec', which selects the 'shared/bundle' rather than the rvm gemset.
What I want to do is have the rvm gemset remain updated so that when I cd into the project I don't have to run bundle exec before everything. I'm not sure what the best way to do this is. My only idea was to create a symlink in the 'vcc' gemset directory that points to the 'shared/bundle' directory. I read somehwere that rvm should be self contained though and will not follow symlinks out of the /rvm directory?
I've seen that it's possible to make Capistrano deploy to your gemset, but it's not recommended. I'm fine with letting Capistrano handle gems and rvm handle ruby, I just want to get rid of "bundle exec." Maybe there's an easier way that doesn't have anything to do with configuring Capistrano or rvm?

Actually it is not recommended to use vendored gems, there are few issues with it and you will be safer using a gemset instead.
rvm-capistrano already suggests you disable the vendored gems here https://github.com/wayneeseguin/rvm-capistrano#disabling-bundle---deployment-when-using-gemsets :
set :bundle_dir, ''
set :bundle_flags, '--system --quiet'
This way gems will be installed in gemset and everything will work fine.

Related

Proper way to set up Rails app on local machine using existing Github repo and RVM

I've tried looking around the internet for a solution to this but to no avail. Every single time I try to set up a new app on my local machine I run into a ridiculous amount of issues with RVM. I decided its finally time I learn to do this right.
Basically I have been given permission to a Rails project in Github and I want to get it running properly on my local machine.
Generally speaking, what I have been doing in the past is this:
$ git clone git#github.com/projectpath
$ ls projectpath
$ bundle install
$ rake db:setup
And cross my fingers. Sometimes it works, other times I have to use RVM to change rubies and redo bundle install. Today, everything is breaking and I keep running into problems like this:
$ rails -v
Rails is not currently installed on this system. To get the latest version, simply type:
$ sudo gem install rails
You can then rerun your "rails" command.
I have a feeling that I am not setting up these apps correctly and also not using RVM as its supposed to be used - basically I believe that my fundamental understanding of RVM is wrong. I would very greatly appreciate it if someone could outline the proper way to do set up a new app using a remote Github repo, as well as explain the proper way to use RVM to get this new app running. Thanks in advance!
I think your life would be easier if you used RVM's gemsets. One gemset per rails application. This keeps everything nice and isolated from each other.
So... something like this...
# install bundler in the global gemset as you want it available everywhere.
$ rvm use #global
$ gem install bundler
# create a project specific rvmrc/gemset.
$ cd /folder/containing/your/github/repo
$ echo "rvm use #myapp" > .rvmrc
$ cd into/rails/root/for/your/app
$ bundle install
At this point you're installing the gems into the 'myapp' gemset, totally isolated from your other gems. There's a new file name for .rvmrc, but I can never remember what it is. .ruby-version or something.
You may also need to create the gemset before it can be used. See the RVM docs for how to make that happen automatically.
Do these cloned projects have files named
.ruby-version
and
.ruby-gemset
in the top level directory? Those files instruct rvm (and other versioning systems) to use a particular ruby version and gemset combo. It could be sometimes you cd into a cloned directory that references the name of a gemset you've already created, in which case bundle and rake work, and sometimes it references a gemset you don't have, in which case you get mysterious blowups.

Using RVM Gemsets & Bundler & RubyMine

I use RVM to manage Ruby versions.
In my project I use Bundler to manage gems for the project.
RVM also have gemsets.
Gem in gemset don't have a connection with Bundler's gem. ← Is this correct?
I came to this conclusion because gem files stored in different locations:
RVM gemset: ~/.rvm/gems/ruby-2.0.0-p247#myApp
Bundler: [my_app_dir]/vendor/bundle/gems
So app uses Bundler gems, not RVM gemset gems.
But when I add gem to my Gemfile, RubyMine IDE shows me warning, that this gem is not in RVM gemset. So I add this gem to RVM gemset also (just to get rid of this warning).
So the questions are:
Is there any good reason to add gems in both places (RVM Gemset and Gemfile)?
If no, then why RubyMine warning me about this?
Is there any good reason to add gems in both places (RVM Gemset and Gemfile)?
The gemset is incidental, the Gemfile is absolutely the place to declare your dependencies. Where you store those gems is up to you.
It sounds like Bundler is configured to store them in a project-local path, but you're expecting them to be in a gemset. Bundler got that configuration by running bundle install --path vendor/bundle/gems at some point. It stores that configuration in its project configuration file at project_dir/.bundle/config:
BUNDLE_PATH: vendor/bundle/gems
I'm unfamiliar with Rubymine, but if you run the Rails server using Bundler (i.e. bundle exec rails server) you can ignore that warning. Bundler will correctly load the gems listed in the Gemfile.
If you want to use a gemset instead of the Bundler cache, you can just remove that line from the Bundler configuration file and reinstall your gems with bundle install.
If no, then why RubyMine warning me about this?
My guess is that Rubymine is not reading the Bundler project configuration (in project_path/.bundle/config) and does not understand where the gems are installed.
You (or if you are working in a team, somebody of your team) has once done a bundle install and specified a installation-folder. In your case vendor/bundle/gems. Bundle remembers this setting and all next invocations of the bundle command will use the same path.
There is a good reason to do it that way: your application-folder will contain all requirements and will be easier to redistribute (for instance).
Now if you want that bundle installs your gems in the normal locations, you can do the following:
run bundle install --system which will use the default location
alternatively: bundle stores it settings in a config file, I think .bundle/config and you can
check that one as well. Normally it is not needed, since bundle install --system will set that
correctly again.
then you can safely remove the vendor/bundle/gems folder
No, something's wrong, you shouldn't have anything under vendor/bundle, it should all be under ~/.rvm/gems/ruby-2.0.0-p247#myApp and perhaps ~/.rvm/gems/ruby-2.0.0-p247#global assuming your .rvmrc (or.ruby-version) is setup correctly.
What does "gem env" look like? Also "bundle env"?
So this just took me 3 days, since nothing else I was finding here was helping. I also run multiple projects through RubyMine at the same time (and different versions) so setting my GEM_PATH and launching from command-line doesn't work for me. I use IntelliJ with RM plugin, this should work on RM standalone.
Bundler seems to install custom gems, or gems from custom repos, in a different directory than gems from rubygems, or github.
/Users/YOURUSER/.rvm/environments/ruby-{version}\#yourgemset/bundler/gems
One thing I wasn't able to fix is in the GEMFILE, I have some custom git_sources, and rubymine highlights those and gives me the warning that it cannot find the gem in my bundle (you can ignore this warning; unless the gem doesn't install at all):
gem 'somegem', custom_git:'gituser/repo'
is highlighted and warning is "Gem x cannot be found... in SDK'
However Bundler installed it, and ruby is able to load it.
# TLDR: Steps to have RUBYMine find extra gems, and show up in external libs
vim ~/.rvm/environments/ruby-{your-verion-here}\#{your-gemset}
add the bundler gems path to GEM_PATH entry
export GEM_PATH='/Users/YOURUSER/.rvm/gems/ruby-{version}#yourgemset/bundler/gems:{the rest}'
save the file
Restart RubyMine/IntelliJ, reopen your project (if not open automatically)
Open the Project Structure dialog > Platform SDKs > Choose the GEMSET you're working with
add /Users/YOURUSER/.rvm/environments/ruby-{version}\#yourgemset/bundler/gems to your classpath
Hit OK, then REOPEN the Project Structure Dialog > Project Settings > Project
Your project will likely have no SDK So select the one you're using again and hit OKAY
RM/IJ will now reindex files
You're done, any broken/missing inspection links should now be fixed. And you should be able to introspect into your gems.
In the above instructions that when you run bundle install (from terminal or RM) it works successfully, and that you have RVM correctly setup, and gemset already created
I hope this helps! Let me know if I should clarify anything (happy NYE)

How can I keep my Ruby Gems the same on several servers?

I have several servers for development, staging, testing and production and want to keep my Ruby version and Gem versions in sync between the different machines -- what's the best way to do this?
If you're using Rails 3, you can just use the Gemfile, and bundler, and when you do a "bundle update" on whatever machine you're on, it will automatically install the correct versions of Gems for that user account.
You should use RVM to manage your Ruby versions and to keep the Gems for different Ruby versions separate from each other.
You should also create a "gemset" for your Rails application, to make sure that the Gems installed there are not modified from another Rails application you might use or develop on the same machine.
http://beginrescueend.com/
http://railscasts.com/episodes/200-rails-3-beta-and-rvm
rvm is the best option to manage ruby versions
However I am not sure if you really want to change ruby version often.
bundler & Gemfile is great way to handle gem versions
Track you Gemfile && Gemfile.lock files in git(or other cvs) tree, and run bundle install on change
You can also, in the event you have more gems in a gemset than just what's in your Gemfile, do a
rvm gemset export gemsetname.gems
And then on the other machine you would do a
rvm gemset import gemsetname.gems
You can even do it as
rvm x.x.x#mygemset exec rvm gemset export mygemset.gems
so you don't have to go directly into your gemset. And then on the new machine,
rvm --create use x.x.x#mygemset && rvm gemset import mygemset.gems
which will create and then populate your mygemset gem set.

What are the benefits & drawbacks of installing things into the #global gemset in RVM?

What are the benefits & drawbacks of installing things into the #global gemset in RVM?
Let's say I want to install different versions of rails on the same server. I then want the ability to install multiple ruby apps on the same server, with the least duplication of files to save on disk space. However, I still want to avoid dependency problems, gem conflict issues and other problems.
Let's also assume that each app has extra gems it needs that I only want in it's local project gemset.
Would I be better off:
Installing both Rails 3 and Rails 2 gems into the #global gemset
...And use project-local gemsets for their gems...
Installing Rails 3 into a #rails3 gemset, and Rails 2 into a #rails2 set... then cloning for each project I need?
For example:
rvm use ree#rails3 && rvm gemset export rails3.gems
rvm use ree#rails2 && rvm gemset export rails2.gems
rvm use --create ree#project1-on-rails3 && rvm gemset import rails3.gems
Install more project-local gems here...
rvm use --create ree#project2-on-rails2 && rvm gemset import rails2.gems
Install more project-local gems here...
Something else entirely...
NOTE: I wrote this whole response assuming that you are using Bundler to manage your gem dependencies. I realize that some people don't, and you didn't mention Bundler in your question. If you aren't using Bundler, I would point out that it probably is the best way to conserve disk space (only if you bundle install --system, though!). If you are using exported gemsets to manage dependencies, I think your scheme sounds reasonable, but I have no experience with it.
Both Rails 3, and Rails 2 with Bundler will set their load path appropriately such that they will not load any gems (or any versions of any gems) that are not in the Gemfile.lock. There's not really any way that I've experienced to have a "gem dependency problem" on the server. It is important that you run bundle install on your development machine whenever you modify the Gemfile, and that you check your Gemfile.lock into source control, as described on the Bundler homepage.
I spent some time digging into the use-cases of gemsets back in January. The reasons I found to use separate gemsets for each project were:
Your shell environment is the same as your application environment (scripts run correctly without bundle exec).
You can easily browse and grep through the source code of all your dependencies, by navigating to the gemset install directory.
It prevents some reported ‘heisenbugs’, according to the author of RVM. I have experienced something like this where a gem executable wasn't available and bundle exec didn't seem to help.
I don't think any of these benefits are very compelling on the server, so if you are aiming to conserve disk space, I'm not sure why you would use gemsets at all.
Actually, the only reason I've used rvm at all on the server was because it was a convenient way to build ruby from source (we needed a version that wasn't available in the native package manager).

Can't access Rails console for app deployed on Passenger using Capistrano & RVM

After finally managing to get my Rails app working, I've got stuck with a slightly perplexing problem. I've deployed my Rails 3.0.5 app to a Ubuntu 10.10 server with Capistrano, RVM and Nginx. All is working nicely and I can confirm Rails is working as I'm getting data from the database and meaningful log messages.
The problem is that on the server, I can't access the console. When I try
rails c
It says "The program 'rails' is currently not installed. To run 'rails' please ask your administrator to install the package 'rails'"
However it is installed otherwise my application wouldn't work! I've only got two RVM gemsets installed, the global one and one called "rails305". Trying
rvm gemset use rails305
then
gem list
doesn't show any of the gems that my app needs, however they must be installed because 1) the app wouldn't work without them and 2) in my Capistrano deploy script, bundler installs them (to that gemset). So the problem is obviously something to do with RVM but I can't work out what it is... anyone any ideas?
It looks like Capistrano uses bundler so you might want to try
bundle exec rails c
from the deployment directory.
See the Bundler deployment page for more information.
Bundler by default doesn't install gems into the default rvm environment when deployed via capistrano, it installs to the "shared/bundle" directory instead, to try and accommodate production installation environments that aren't using RVM. If you are using RVM in production, and want to just have bundler install to your default ruby/gemset (which is terribly useful if you are going to be logging into the production, running rake scripts, console, etc), add the following options to your config/deploy.rb:
set :bundle_dir, ""
set :bundle_flags, ""
This will remove the "--deployment" (and "--quiet", which you may or may not want to keep) and --path flags which cause bundler to try and package everything up nicely, so bundler will now install to the user's RVM environment; making your server environment work a lot more like your dev environment (which can be good or bad depending on what your needs are).

Resources