Why is this ruby script echoing the path to the executable? - ruby

Here's a Ruby file at /path/to/test/test.rb:
# /path/to/test/test.rb
puts 'foobar'
Here's what happens when I run it:
$ cd /path/to/test/
$ ruby test.rb
foobar
So far, so good. But:
$ cd ..
$ ruby test/test.rb
/path/to/test/ # <=== wtf?
foobar
Why does Ruby print the path to the script when I run it outside the current folder? The problem occurs only with Ruby scripts, and occurs whether or not I run it with $ ruby test.rb or make it executable with a shebang.
This is definitely nonstandard behavior caused by something in my Ruby environment, but I can't imagine what it is. I have Rails and a number of other gems installed. Any idea what might cause this?

I believe this is due to CDPATH being set in your environment. rbenv cd's while shimming Ruby and when resolving the relative path to the script file, and this causes some paths to be echoed to the terminal. In the past I've had some luck working around this issue by not exporting CDPATH in my .bash_profile (i.e. just setting it, without the export keyword), but it seems that this is not sufficient in all cases. In fact, in the current master branch tip of rbenv (which has not yet been released), they unset CDPATH at the top of the file, so it seems as though they're aware of this problem and hope to address it in the next release.
If you want this fix today, instead of waiting for the next release, you can obtain it by uninstalling rbenv through Brew (brew uninstall rbenv), and reinstalling it through Git. You will first need to rename your current ~/.rbenv directory (e.g. mv ~/.rbenv ~/.rbenv.bak), and after reinstalling rbenv, you may want to migrate your installed rubies and gems (instead of reinstalling them):
mkdir -p ~/.rbenv/versions
mv ~/.rbenv.bak/versions/* ~/.rbenv/versions/
Hope this helps!

Related

The ghost of RVM is haunting me

I recently installed the Ruby Version Manager (RVM) and uninstalled it again, using this "scorched earth" script:
#!/bin/bash
/usr/bin/sudo rm -rf $HOME/.rvm $HOME/.rvmrc /etc/rvmrc
/etc/profile.d/rvm.sh /usr/local/rvm /usr/local/bin/rvm
/usr/bin/sudo /usr/sbin/groupdel rvm
/bin/echo "RVM is removed. Please check all .bashrc|.bash_profile|.profile|.zshrc for RVM source lines and delete or comment out if this was a Per-User installation."`
(I found this script here. I also tried more milquetoast approaches such as rvm implode and rm -rf ~/.rvm, etc.)
Now
$ which rvm
returns nothing, but rvm still seems to be there in some form, because when I type
$ rvm implode
I get a reaction, specifically:
cat: /Users/lolan/.rvm/VERSION: No such file or directory
Warning! PATH is not properly set up, '/Users/lolan/.rvm/gems/ruby-2.3.1/bin' is not available. Usually this is caused by shell initialization files. Search for 'PATH=...' entries. You can also re-add RVM to your profile by running: 'rvm get stable --auto-dotfiles'. To fix it temporarily in this shell session run: 'rvm use ruby-2.3.1'. To ignore this error add rvm_silence_path_mismatch_check_flag=1 to your ~/.rvmrc file.
-bash: /Users/lolan/.rvm/scripts/base: No such file or directory
-bash: /Users/lolan/.rvm/scripts/functions/implode: No such file or directory
Are you SURE you wish for rvm to implode?
This will recursively remove /Users/lolan/.rvm and other rvm traces?
(anything other than 'yes' will cancel) >
Psychologist intervened, cancelling implosion, crisis avoided :)
(This time I typed return when it prompted me for 'yes'. Other times I typed 'yes'.)
Basically, I'm mystified how $ which rvm returns nothing, but $ rvm implode doesn't return "command not found". This goes contrary to what I think I understand about the command line...
Anyway, how do I really kill RVM, together with its psychologist and all? :)
PS: I'm on macOS 10.12.
==============
UPDATE: It seems that despite having gone through all the standards steps for removing RVM (see above) and despite refreshing the shell (à la source .bash_profile, source .bashrc, source .profile), the shell was still keeping some memory, somehow, of RVM, that went away when I started a brand new shell.
I'd still like to understand better how/what the shell was keeping around, because keeping bits and pieces of script folders (after the script folder in question has been deleted!?!?) seems dangerous and counterintuitive to me.
That's because rvm is in a hidden directory in your home directory and not in your PATH. which searches for an executable or script in the directories listed in the environment variable PATH using the same algorithm as bash. If it doesn't find it then it won't be returned.
If you want to know how to remove RVM there is already an answer for that. The easiest way is: rm -rf ~/.rvm

RVM and Gemfile - not always loading correct ruby, only when 'cd .. & cd myproject'

TL;DR: Every time I open a new iterm2 tab, rvm goes back to default version, it doesn't use the Gemfile ruby version
My Gemfile has
source 'https://rubygems.org'
ruby '2.0.0'
and I use rvm 1.25.14.
RVM is smart and reads the ruby version in gemfile, except for this edge case
Doing
# NOTE: iterm2
$ cd myproject
$ ruby -v
> ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-darwin12.5.0]
but cmd+t, creating a new tab, staying in that directoy,
$ pwd
>../myproject
$ ruby -v
> ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-darwin12.3.0]
ruby 1.9.3 is my default, which is fine. What am I missing in my bash (or .zshrc ) ? to make this work?
#FILE .zshrc
#...stuff
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
PATH=$PATH:$HOME/.rvm/bin # Add RVM to PATH for scripting
Using cmd+d, splitting the terminal vertically, has the same problem. rvm goes to default, ignoring Gemfile. Thanks for helping guys !
This should be shell- and terminal-agnostic (unfortunately I can't test it on iterm2 since I don't have any Mac machine):
Add cd ${PWD} to your .zshrc and this should force RVM to load current gemset.
Just add cd . in .zlogin after the RVM script.
Use RVM's Built-In Ability to Reload Configuration Files in the Current Directory
RVM leverages the cd command, so while there may be a specific solution for your situation the more general solution is to use direnv, dotenv, or similar to ensure that you're triggering RVM properly when changing directories.
In my personal experience, one of the two placed into your project's .envrc or similar will resolve many issues, and highly recommend direnv with or without its standard library's ruby layout or use commands. For example:
read in the current directory's .ruby-* or .rvmrc files
rvm use .
Reload RVM, which will re-read various dotfiles if the relevant ~/.rvmrc variables have been exported (see dotfile settings in next section).
rvm reload
The first option is best IMHO, and seems to "just work" on all my Bourne-compatible shells, but the other should work too.
Some Key ~/.rvmrc Dotfile Settings
With either of the solutions above, you may need some of the following items set in your global ~/.rvmrc file:
export rvm_gemset_create_on_use_flag=1
export rvm_install_on_use_flag=1
export rvm_project_rvmrc_default=1
Which ones you really need will somewhat depend on how you expect RVM to behave under any given set of circumstances. However, I've found that using RVM's ability to reload its settings (rather than relying on the cd hooks, and calling that functionality directly to be much more reliable. Your mileage may vary.
See Also
https://rvm.io/workflow/rvmrc
https://rvm.io/workflow/projects
I seems that for a local open terminal rvm don't load its scripts. Add the code to the end of .bashrc, it then should:
if [ -z "$MY_RUBY_HOME" ]; then
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
fi

shebang for multiple versions

In my large collection of Ruby scripts, I do start my scripts with the common shebang:
#!/usr/bin/env ruby
Now I am finding some scripts that do need certain Ruby version, and no, they are no Rails apps that can be deployed under a specific Ruby version. They are just single file scripts that can be launched from the command line and fail to work with the system version.
Is there any way to write a shebang that sets the environment with rbenv/rvm before running the following code of the file?
You don't necessarily need to set up any environment. All you need is the path to the ruby binary you want to run and everything else will follow.
Here's an example on how you could set it up:
Create a folder ~/bin. This will hold pointers (symlinks) to all your personal ruby binaries.
Update your shell PATH so that ~/bin is included in the search path for executables.
Symlink any ruby binary you need in your ~/bin to the actual ruby binary.
For example in my ~/bin I have:
ruby18 -> /opt/ruby18/bin/ruby
ruby19 -> /opt/ruby19/bin/ruby
ruby20 -> /opt/ruby20/bin/ruby
Now let's say you have a script which needs 1.9 to run. Then all you need to do is:
#!/usr/bin/env ruby19
This will work if you have installed your gems into the default gem directory for each ruby executable. If you have installed gems somewhere else then it gets more complicated and you would need to modify GEM_PATH before you run your script.
If you don't want to get fancy with ~/bin then just hardcode your shebang line instead to point directly to the ruby binary:
#!/opt/ruby19/bin/ruby
...or the equivalent rbenv/rvm path.
Having symlinks in your ~/bin though will allow you to more easily update your bin pointers if let's say you compile a new patch of ruby 1.9, and you want to place it in another folder like /opt/ruby19-p123. Then you just need to update the symlink in ~/bin and all your scripts will run the new patched version.
rbenv will look for the .ruby-version file set by (for example)
$ rbenv local 1.9.3-p448
Create a simple file, check
#!/usr/bin/env ruby
puts RUBY_VERSION
Make it executable
$ chmod +x check
Run it
$ ./check
Output
1.9.3
That said, this is not a per-file setting. If there's a way to alter rbenv's behavior using the shebang, that would probably be a better fit.

the correct Ruby version when opening a terminal

Each time I open a terminal my Ruby version is wrong. I am obliged to execute by hand the following command:
source /usr/local/rvm/scripts/rvm
I read that RVM doesn't modify .bashrc or .bash_profile but I note that my .bashrc has at the end:
PATH=$PATH:$HOME/.rvm/bin
Not only I didn't insert this myself but the path to rvm is wrong !
I changed by:
PATH=$PATH:/usr/local/rvm/bin
I reopened a terminal but the Ruby version is always wrong !
rvm does modify your .bash_profile / .bashrc -- that's one of its weaknesses. In particular, it adds (is supposed to add) this line to load rvm as a shell function:
# Load RVM into a shell session as a function
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
I had a similar issue with the wrong ruby version running even after I changed the global default in rvm--ensuring this line was at the end of my .bash_profile fixed it. In any case, that line's supposed to be there for rvm to work properly.
You can make an .rvmrc file in the root directory of your application.
It runs whatever is inside on opening the root direct, so I think you can just copy this
PATH=$PATH:/usr/local/rvm/bin
and things should be good. You'll get a warning, but it's safe to ignore (or has been in my experience). I think you might be better off going with this, which I've found helpful to keep rubies/gemsets straight across applications.
#.rvmrc
rvm [ruby]#[gemset] #for example rvm 2.0.0-p247#my_gemset
Why gemsets/rubies get switched/reset in the first place, I really don't know and it is annoying, but this seems to fix it.
read more here
Depending on your setup it could not be loading for several reasons.
For instance, when you open a shell (depending on the OS distribution) bash files are read in various orders, although here is what the standard looks like: ( I believe Ubuntu is slightly different so you might want to check if thats your distro).
# for interactive login shells (when you login to a terminal)
/etc/profile
/home/<user>/.bash_profile
/home/<user>/.bash_login # if there is no .bash_profile
/home/<user>/.profile # if there is no .bash_login
# for interactive non-login shells (i.e. opening up a new tab)
/etc/bash.bashrc
/home/<user>/.bashrc
What happens when you directly source your .bashrc? Does it then find rvm? If so, then its just a matter of making sure your .bash_profile sources .bashrc aka:
# in .bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
If this isn't the cause you could dive into the rvm documentation or switch to rbenv which IMHO is a much simpler solution.
RVM should handle this automatically but this code is wrong.
PATH=$PATH:/usr/local/rvm/bin
RVM's path should be first. Your bash is acting as you wish actually. It uses the 'system wide' ruby first because you tell your shell to do so. Change this to:
PATH=/usr/local/rvm/bin:$PATH
then source ~/.bashrc and it will work as you wish, calling rvm ruby when you login.

TextMate, rvm and TM_RUBY

In the TextMate RVM instructions the text it says to set TM_RUBY to /Users/wayne/.rvm/bin/textmate_ruby and in the image it shows it set to rvm-auto-ruby. I decided to set it to rvm-auto-ruby thinking that it would use RVM's default Ruby version.
When running Command R in the RSpec.bundle having TM_RUBY set to rvm-auto-ruby will result in a load error. When you set it to textmate_ruby it works.
The only problem here is that TextMate doesn't always use the default version of Ruby since it's hardcoded in that file.
/Users/jspooner/.rvm/bin/textmate_ruby:
#!/usr/bin/env bash
if [[ -s "/Users/jspooner/.rvm/environments/ruby-1.9.2-head" ]] ; then
source "/Users/jspooner/.rvm/environments/ruby-1.9.2-head"
exec ruby "$#"
else
echo "ERROR: Missing RVM environment file: '/Users/jspooner/.rvm/environments/ruby-1.9.2-head'" >&2
exit 1
fi
So two questions:
What should TM_RUBY=rvm-auto-ruby actually do?
Is there a way to have TextMate use the RVM default?
Setting TM_RUBY to your-path/rvm-auto-ruby
http://rvm.io/integration/textmate/
should load whatever ruby and gemset is indicated in the .rvmrc file located in the project and if none default to rvm default. I just got this working and it is very smooth. I did need to get the latest version of rvm
rvm get head
to make it work and restart Textmate. Hope that helps.
See your other, similar, question Rspec bundle is broken in TextMate and rvm.
To help others chasing this same issue, the solution seems to be at: RVM / Textmate doesnt recognize .rvmrc Options.
Basically you replace the ~/.rvm/bin/textmate_ruby soft link with a file. This is what I did:
cd ~/.rvm/bin
mv textmate_ruby old.textmate_ruby
Create a shell script called textmate_ruby in the same directory to replace the soft-link, using the following contents:
!/usr/bin/env sh
source ~/.rvm/scripts/rvm
cd .
exec ruby "$#"
chmod +x textmate_ruby
Before doing this change I'd see my system Ruby's version (1.8.7) displayed if I did CMD+R to run the following script in TextMate:
puts RUBY_VERSION
Evaluating the script using CMD+CNTRL+SHIFT+E gave me 1.9.2.
After switching to use that script both point to Ruby 1.9.2, so at least there's some consistency now. I don't see TextMate tracking my currently set RVM Ruby version yet; Instead it's using the default version set in RVM: rvm use 1.9.2 --default. This is still a step forward because I can control which Ruby TextMate uses by adjusting my --default.
If you decide you want to revert later, just rename, or delete, the script and reverse step 2 above.

Resources