This is cool! A frequent problem I've had with bundler is when the Gemfile lists a newer version of a gem (stringio) but the older version has already been activated. If you can get rid of such errors I would be so happy! Also I've had to frequently update bundler too often when updating a Rails site.
This looks like a really nice improvement to the Ruby ecosystem. Great job and thank you to those involved.
I've definitely felt the awkwardness of gems being so compartmentalized by project that using system level dev tools that I like to have available for all my projects feel out of place within my project's Bundler-centric world.
It looks cool but I feel this kind of tool is only useful if Ruby is the only language you use. I have to manage several runtimes for most projects. I've used asdf for years and recently switched to mise: these tools already download pre compiled binaries for Ruby, plus pretty much any other language runtime.
It's likely that you get better per language features for something specific to the language though. We end up in exactly the same kind of frustration, that for some random project you need this specific tool that does dependency management of the specific runtime. asdf and mise both respect a .tool-versions file, I'd rather see things go more in that direction with some kind of standard.
It's fun to see package management improvements move full circle—lessons from Ruby package management contributed to Rust, Rust is helping improve package management for Python, and now Python package management is inspiring improvements for Ruby!
"Not a version manager, or a dependency manager, but both of those things and more. I’m currently calling this category a “language manager”, but if you have a better name idea, let me know!"
One thing I love about Ruby is it never devolved into ?VM hell like Python did. Yes, there are a bunch of ruby version managers, but there's only one bundler no matter how you get get ruby installed. I like some ideas here, but I'm also afraid this could be step one toward that python nightmare.
> We expect to be able to silently run equivalents of both rvm install and bundle install at the beginning of every bundle exec,
Do I understand right it doesn't use bundler code for resolving gem requirements dependency tree, but uses it's own code meant to be compatible? Hmmm.
And also producing the `Gemfile.lock`, which has had kind of a lot of churn in bundler, which bundler has had to work to keep from breaking for people even when it's assumed they're all using (different versions of) bundler.
Has anyone ever actually had anything break from a Ruby version update? I know Matz basically never does breaking changes, last I remember is the 1.8.7 -> 1.9.2 update...
I've only ever just straight up downloaded the source and installed it myself, never had any issues with Ruby updates...
uv has been the greatest development in the python ecosystem in the last decade.
super excited about rv! PLEASE, enable sponsorship on github.com or elsewhere. I want to donate $$$!!!
He he. If this article isn't proof that people don't really want "do just one thing and do it well" (besides the million flags of ls and find), nothing is :-)
As a long-time Rubyist and recent Python dabbler (due to pytorch) this is exciting! Uv and uvx certainly are great improvements in the Python ecosystem, but still have some quirks that I wonder how they will handle with rv:
- By default uv is creating isolated environments in the project directory and will download all dependencies over the network. For small stuff this isn't too bad, but re-downloading 700mb pytorch each time you clone a repo gets annoying very fast. Of course there are trade-offs with running updates less frequently (and uv has flags such as --offline and --refresh to avoid or force online access) but more sensible default behavior would be nice so that uv (and rv) keep you on the happy path during developing. Maybe updates could be run in the background by default.
- Also because the environments aren't shared in any way, each project directory consume a lot of disk space (10x checkouts = 10x pytorch on disk). More sensible caching across environments would be nice (links?).
- I am wondering if rv will support version operators such as rv install "~> 3.4.4" to get ruby ">= 3.4.4, < 3.5.0", which I think would help ensure everyone is running Ruby versions with security patches applied.
- uv includes the pip sub-command (similar to using gem install rather than bundle add) but because the environments are isolated this feels rather weird and I haven't really understood in which cases you should not just use "uv add" to update your project dependencies.
- Uv tries hard to support migration from legacy Python projects which don't have a pyproject.toml, but the Python eco-system is too fragmented for this to always work. I hope rv can avoid adding new config files, but really stick to the existing Gemfile approach.
- If a Python package includes a script with a different name than the package then the syntax is a bit annoying ('uvx --from package script' but not 'uvx script --from package' because this would get passed to the script). Uv already uses square brackets for optional project dependencies (e.g. 'uvx --from huggingface_hub[cli] hf') but since Ruby doesn't have these, maybe this would be an option for rv.
I'm sure rv is great, but am I the only one who needs one such tool not only for Ruby, but also Python, JavaScript, and Java, at least, and finds it weird to run 4+ of those?
I think it's probably for the best to have a different tool for each language/platform. Not every language or platform matches feature for feature in that the options will already be different for each language, and you're likely to have such a "universal" tool come up short in support of one language or another.
I really appreciate cargo a lot for what it brings, even if it's calling different tools under the covers. Similarly, I appreciate deno in that it brings all the tooling and the runtime in a single executable (box). I've migrated most of my scripting to TypeScript using deno at this point because of that distributive ease. Even if the shebang itself is a bit sloppy.
Aside, would be cool to have a VS Code extension that would to file type detection based on a shebang at the top of the file. Making it easier to do extensionless script files with language support.
On the one hand, it's nice to see Ruby and the Ruby tooling system getting some love.
On the other, I'm not sure if this is really needed. Most of this stuff already works fine in Ruby with Bundler. Did you know that Bundler already has a really nice syntax for inline requirements for single-file scripts?[0] Seems like a lot of people forgot. Installing Ruby hasn't generally been much of a hassle either AFAIK. Bundler also doesn't seem to have the Python venv problem - it works fine for keeping a bunch of gem versions around in the same Ruby install and only activating the specified ones. I think Gemfile and Gemfile.lock is what Python always wished they had. I guess more speed never hurt, but it never felt like bundler was painfully slow for me, even on huge codebases. So is there really a big win here?
Though I guess plenty of Python gurus probably feel the same way about the uv craze when their existing tooling works well enough for them.
I go between different languages a lot so having a command line interface that is consistent with the one I use in Python (uv) would definitely be appreciated. I mostly use Ruby for single-file scripts with no dependencies, which means I don't do projects often enough to remember how to use bundle/gem/rvm/whatever. It seems to me like `rv` is not quite ready to fully replace them just yet but I'm excited to see where the project goes.
I'm also excited about `rv tool` because I've been having to re-install rubocop and ruby-lsp gems every time the minor version of the system Ruby is updated. It's just a few commands every year (and I'm sure it's a skill issue) but having things "just work" with a single `rvx rubocop` command will be sweet.
What is the real problem being solved here? For all the issues that bundler still has, rv doesn't seem to address most of them. Bundler has been fast enough for a while now, how fast does this need to be? And do we now have to know rust to contribute?
If indirect is salty that the rubygems/bundler didn't turn out yet to be what he wanted, I wonder whether a simpler and faster alternative to bundler written in RUBY wouldn't be the answer, with incremental merges into bundler. Gel was mostly there, even if most never knew about it, but at least it got the bundler ppl to merge the pub grub resolver.
not being dismissive of the effort or other tools and languages, not trying to convince anyone
After decades of Java (ant/maven), then Scala (sbt), then JS (npm), then TS, switching to Go (Make) some years ago made many problems go away.
The tooling (test, ...) inside the main tool (Rust still a little better I think), now tools/versions inside go.mod, the result of my work being a binary I can run with systemd, embedding files into the binary, all of that removed a lot of dep management issues, building issues, bundling issues, and the need for e.g. Docker for many use cases (which I feel many people only use to package .jar files or gems into something that can run in production).
Seems rv wants the same, "Our end goal is a completely new kind of management tool, [...] Not a version manager, or a dependency manager, but both of those things and more. I’m currently calling this category a “language manager”"
32 comments
[ 25.1 ms ] story [ 469 ms ] threadI've definitely felt the awkwardness of gems being so compartmentalized by project that using system level dev tools that I like to have available for all my projects feel out of place within my project's Bundler-centric world.
It's likely that you get better per language features for something specific to the language though. We end up in exactly the same kind of frustration, that for some random project you need this specific tool that does dependency management of the specific runtime. asdf and mise both respect a .tool-versions file, I'd rather see things go more in that direction with some kind of standard.
Language Orchestrator?
Do I understand right it doesn't use bundler code for resolving gem requirements dependency tree, but uses it's own code meant to be compatible? Hmmm.
And also producing the `Gemfile.lock`, which has had kind of a lot of churn in bundler, which bundler has had to work to keep from breaking for people even when it's assumed they're all using (different versions of) bundler.
I've only ever just straight up downloaded the source and installed it myself, never had any issues with Ruby updates...
As an idea: add advantages compared to rvm, rbenv, etc. Or a comparison table
> Ruby Versions: Ruby 3.4.1 and up
It turns out that this is only for the latest ruby versions :(
But I will follow the development!
- By default uv is creating isolated environments in the project directory and will download all dependencies over the network. For small stuff this isn't too bad, but re-downloading 700mb pytorch each time you clone a repo gets annoying very fast. Of course there are trade-offs with running updates less frequently (and uv has flags such as --offline and --refresh to avoid or force online access) but more sensible default behavior would be nice so that uv (and rv) keep you on the happy path during developing. Maybe updates could be run in the background by default.
- Also because the environments aren't shared in any way, each project directory consume a lot of disk space (10x checkouts = 10x pytorch on disk). More sensible caching across environments would be nice (links?).
- Using uv to turn Python files into standalone/self-contained scripts is really great (https://peps.python.org/pep-0723/) and I hope rv can mirror this capability well. Because the lock file isn't included in the script header it requires some configuration options to make runs repeatable (e.g. https://docs.astral.sh/uv/guides/scripts/#improving-reproduc...).
- I am wondering if rv will support version operators such as rv install "~> 3.4.4" to get ruby ">= 3.4.4, < 3.5.0", which I think would help ensure everyone is running Ruby versions with security patches applied.
- uv includes the pip sub-command (similar to using gem install rather than bundle add) but because the environments are isolated this feels rather weird and I haven't really understood in which cases you should not just use "uv add" to update your project dependencies.
- Uv tries hard to support migration from legacy Python projects which don't have a pyproject.toml, but the Python eco-system is too fragmented for this to always work. I hope rv can avoid adding new config files, but really stick to the existing Gemfile approach.
- If a Python package includes a script with a different name than the package then the syntax is a bit annoying ('uvx --from package script' but not 'uvx script --from package' because this would get passed to the script). Uv already uses square brackets for optional project dependencies (e.g. 'uvx --from huggingface_hub[cli] hf') but since Ruby doesn't have these, maybe this would be an option for rv.
I put my hope in mise-en-place - https://mise.jdx.dev
What do people think? One tool per language, or one to rule them all?
I really appreciate cargo a lot for what it brings, even if it's calling different tools under the covers. Similarly, I appreciate deno in that it brings all the tooling and the runtime in a single executable (box). I've migrated most of my scripting to TypeScript using deno at this point because of that distributive ease. Even if the shebang itself is a bit sloppy.
Aside, would be cool to have a VS Code extension that would to file type detection based on a shebang at the top of the file. Making it easier to do extensionless script files with language support.
On the other, I'm not sure if this is really needed. Most of this stuff already works fine in Ruby with Bundler. Did you know that Bundler already has a really nice syntax for inline requirements for single-file scripts?[0] Seems like a lot of people forgot. Installing Ruby hasn't generally been much of a hassle either AFAIK. Bundler also doesn't seem to have the Python venv problem - it works fine for keeping a bunch of gem versions around in the same Ruby install and only activating the specified ones. I think Gemfile and Gemfile.lock is what Python always wished they had. I guess more speed never hurt, but it never felt like bundler was painfully slow for me, even on huge codebases. So is there really a big win here?
Though I guess plenty of Python gurus probably feel the same way about the uv craze when their existing tooling works well enough for them.
[0] https://bundler.io/guides/bundler_in_a_single_file_ruby_scri...
I'm also excited about `rv tool` because I've been having to re-install rubocop and ruby-lsp gems every time the minor version of the system Ruby is updated. It's just a few commands every year (and I'm sure it's a skill issue) but having things "just work" with a single `rvx rubocop` command will be sweet.
https://github.com/regularfry/rv
(Kidding! Looks interesting.)
If indirect is salty that the rubygems/bundler didn't turn out yet to be what he wanted, I wonder whether a simpler and faster alternative to bundler written in RUBY wouldn't be the answer, with incremental merges into bundler. Gel was mostly there, even if most never knew about it, but at least it got the bundler ppl to merge the pub grub resolver.
After decades of Java (ant/maven), then Scala (sbt), then JS (npm), then TS, switching to Go (Make) some years ago made many problems go away.
The tooling (test, ...) inside the main tool (Rust still a little better I think), now tools/versions inside go.mod, the result of my work being a binary I can run with systemd, embedding files into the binary, all of that removed a lot of dep management issues, building issues, bundling issues, and the need for e.g. Docker for many use cases (which I feel many people only use to package .jar files or gems into something that can run in production).
Seems rv wants the same, "Our end goal is a completely new kind of management tool, [...] Not a version manager, or a dependency manager, but both of those things and more. I’m currently calling this category a “language manager”"