Specify project ruby version independent of whether I use `rvm` or `rbenv`? - ruby

Not wanting to commit to e.g. .rvmrc for specifying the ruby version.

If your project is using a Gemfile you can set it there too:
ruby '1.9.3'
This is of course 'per project' and not global. Heroku uses it that way.

In the top-level directory of your project, create a file named .ruby-version containing only the version of ruby you want to use, e.g.
2.1.0
You can sometimes also specify system (known example: MacOS).

Related

error Your Ruby version is 2.6.8, but your Gemfile specified 2.7.5

This happens when I run npx react-native init AwesomeProject.
When I check the system ruby version with ruby -v, it is already 2.7.5. ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-darwin21]. Anyone has any idea for this problem?
Sounds like you’re using rvm to manage Ruby versions.
You need to install and run the correct version, not delete the current.
Something like
rvm install 2.7.5
rvm use 2.7.5
The Gemfile Isn't (Directly) Your Issue
The Gemfile is irrelevant to solving this issue. It's just triggering it because your in-project Ruby version isn't matching what RubyGems (via the Gemfile or Gemfile.lock) expects as a constraint. It could be a minimum version, an exact version, an approximate version, and so forth. There are a lot of ways to specify version constraints in a project, and the Gemfile is just where the constraint-related exception is being raised by Bundler.
You could possibly make the problem go away simply by removing the requirement for a later version of Ruby from the Gemfile or gemspec, removing the Gemfile.lock, and re-running Bundler. However, if your code relies on features in a later version this will just create other problems for you. You really ought to uncover what's changing your Ruby environment within the project directory.
Dotfiles
There are a lot of reasons this could happen, but if your system Ruby is 2.7.5, then you need to check your project directory for various dotfiles like:
.ruby-version
.rvmrc
~/.rvmrc
.envrc
.env
or various other files that affect your shell environment or whatever Ruby version manager you're using. Most Ruby version managers respect .ruby-version, but some version managers use other files, including defaults or shims that may be set elsewhere. IDE's also often have their own project-specific configuration files, too, and they can sometimes be set to override the project's standard settings.
Also, make sure to check your Gemfile.lock and *.gemspec in addition to the Gemfile itself, in case something is being specified there or constrained by some other dependency.
Inspecting Environment Variables
You should also look at the Ruby- and RubyGems-related environment variables from your project directory to see how various values are set within the project. For example:
printenv | grep -E '^(RUBY|GEM)' | sort
Shebang Lines
In addition, you should check your shebang lines in any executable Ruby or shell scripts you're relying on to see whether a specific non-system Ruby is being invoked. For example:
grep -Enr '^#.*ruby' *.rb | grep -F '.rb:1:'
will find all the shebang lines that properly appear on the first line of a Ruby file. This will either point to a specific Ruby like #!/usr/bin/ruby or might be using a PATH lookup with #!/usr/bin/env ruby.
Shell scripts might be harder to inspect, as there may be calls to other executables or even an exec command, so you'll need to be more liberal with your grepping if you are looking for an interpreter call further down than the shebang line.
Checking PATH Order
In the case of #!/usr/bin/env ruby, you should inspect your PATH environment variable to see why the Ruby you want isn't being called first. Using which -a ruby (if supported by your OS) will show you all rubies in your PATH in the order they would be invoked by the shell. It's possible that you're simply calling an unexpected Ruby version that comes first in the PATH.

Setting ruby version separately with different app on Mac

I have just started working on a ruby project and I notice that I have to specify the ruby version to use globally. For instance, I am using chruby to change the ruby version to use and I can set it directly at this file called .zshrc.
But if I have a multiple apps with different ruby version, then how do I handle it? It doesn't make sense if I keep changing the version to use at .zshrc file every time I want to run the other app.
Since it's a shared project so I cannot just change the version used in the app. Thank you.
In chruby, this feature is called "Auto-switching".
If you want chruby to auto-switch the current version of Ruby when you cd between your different projects, simply load auto.sh in ~/.bashrc or ~/.zshrc:
..
chruby will check the current and parent directories for a .ruby-version file.
https://github.com/postmodern/chruby#auto-switching

Use local version of module from Github instead of installed

I am working on a project written in Ruby, which depends on another module using require modulename. I can change the required module to add the features I need, but I don't want to modify my installed version. I've downloaded the module from git, but I don't know how to point my project to this local version.
Assuming the required module is a gem, you can use the path: option in Gemfile to define a local version of a gem. So in Gemfile:
gem 'modulename', path: 'relative/path/to/modulename'
However, remember to remove the path: option before committing any changes to your git repository as you don't want that going into production.

Should I check in `.ruby-gemset` and/or `.ruby-version`?

I've just updated RVM, and in place of the old .rvmrc, it auto-created .ruby-gemset and .ruby-version.
I've always had .rvmrc files with contents like rvm use --create default#project_name. However, .ruby-version contains the specific Ruby version I'm running rather than default. I'm hesitant to check this in.
Also, I heard someone say on a podcast that one shouldn't check in .ruby-gemset because others may have their own preferences about how to name gemsets.
When should or shouldn't I check in .ruby-gemset and/or .ruby-version?
Specifically:
What are some of the tradeoffs?
How does the type of project affect the decision (for example, applications vs gems)?
If they should be checked in, how does the type of project affect what should go in these files?
Citations from from the creators of tools like rvm, rbenv, etc would be appreciated in an answer.
For standard projects
Check in .ruby-version if your project depends on a ruby like ruby-2.0.0.
Check in .ruby-gemset only if your team agreed on it.
Add .rvmrc to .gitignore so anyone can override .ruby-* files settings with .rvmrc.
For gems
Check in .ruby-version with ruby-1.8.7 only if your project still targets ruby 1.8.7, otherwise check it in only if your gem requires it.
Do not check in .ruby-gemset.
Checking in .rvmrc, .ruby-version or .ruby-gemset?
FOR:
Your project has different branches (say a RubyGems project supporting Ruby 1.8, 1.9 and 2.0 versions). Its better to check in this file, so that your developers don't have to keep on editing these files when they switch branches. The same doesn't apply for an application though, where you'll mostly be working on only one Ruby version.
Same case as above, but say you are running a CI server (say TeamCity/Jenkins/...) which automatically just runs rake spec for every check-in. You don't want to create separate build pipelines for each branch, just for the sake of having a separate rvm use ... for each branch. You just want the Ruby version selected automatically depending on the branch
You have tight control over the environment and all the developers. You either don't need or dictate that they use the same ruby and gemset
You are using Phusion Passenger or Capistrano, which automatically read .rvmrc files and chooses the right ruby for deployment/hosting
Also refer RVM Best Practices
AGAINST:
You can compile your own Ruby in RVM, with some experimental patches, and give it a custom name.
e.g. rvm install 1.9.3 --patch railsexpress,falcon --name ruby-1.9.3-perf
In the above example, I've installed Ruby 1.9.3 with some great speed up patches (btw they are awesome), but rather than calling it 1.9.3, I'm calling it my own name. I would say rvm use ruby-1.9.3-perf whenever I need this. In this case, if the project has its own .ruby-version, then it messes up my environment. In my project, these patches are standard and we actively recommend those. But how developers name the resultant compiled Ruby is up to them
Similarly, people use different gemsets. Some don't use gemsets at all. Some share the same gemset with different (but similar) ruby projects. Given this, again a single .ruby-gemset also doesn't work for everybody
Your project has an obscure ruby version which just says 1.9.3. Your developers first installed the latest Ruby 1.9.3-p329. But they later just update RVM/Rbenv (since they're working on other projects). Their .rvmrc or .ruby-version just breaks, since the latest version of Ruby registered in RVM/Rbenv just changed from ruby-1.9.3-p329 to .ruby-1.9.3-p362, and it will say ruby-1.9.3-p362 not installed. This scenario tends to happen often.
As long as you specify a proper full name for your Ruby version (including patch level), you should be OK. Let's say your project's .ruby-version says ruby-1.9.3-p329. Its easy to compile your own Ruby with all these patches, and still just custom name it ruby-1.9.3-329 just so that the config files will pick up this ruby instead of the standard ruby.
I would include .ruby-version - you and anyone else working on the project, along with your servers, should be using the same version of Ruby.
.ruby-gemset.... up to you, I think.

How to develop a gem in staging environment?

I am trying to hack through a forked gem (buildr). As such I cloned it from github and began to butcher the code. The official gem is installed on my system (under /usr/lib/ruby.../gems/buildr...). There is an executable which I need to use in my dev process - buildr.
Now I want the buildr executable and the library to point to my forked repo and not the default gem installation. This would be for this gem only. As such, the changes I make against the forked repo is usable directly for testing and so forth.
I would guess I need to load my library prior to the system gem loading. Can somebody recommend the best way to do so?
I did something similar for work when the Spreadsheet gem broke backward compatibility. I put the previous versions code in it's own module and just renamed the gem my-spreadsheet and installed that (I really wanted some of the features of the new gem but I also didn't want to rewrite all my previous code at that point).
If it's just a binary you want to override you could always do some PATH magic, setting the directory of your binary first and thus make sure you always override. But personally I'd prefer making my own copy with a new name and installing that.
you could bump the version in the gemspec for your fork. Then when you install your version of the gem, it will use your (newer) version by default.
change buildr.gemspec
#...
spec.version = '1.3.4.dev'
#...
Then
$ gem build buildr.gemspec
$ sudo gem install buildr-1.3.4.dev.gem
and it should work.

Resources