Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
R

ruby-next

> 编程语言
Open source

Ruby Next makes modern Ruby code run in older versions and alternative implementations

799 stars0 likes2 views
WebsiteGitHub

About

Ruby Next makes modern Ruby code run in older versions and alternative implementations

Ruby Next

Ruby Next is a transpiler and a collection of polyfills for supporting the latest and upcoming Ruby features (APIs and syntax) in older versions and alternative implementations. For example, you can use pattern matching and Kernel#then in Ruby 2.5 or [mruby][].

Who might be interested in Ruby Next?

  • Ruby gems maintainers who want to write code using the latest Ruby version but still support older ones.
  • Application developers who want to give new features a try without waiting for the final release (or, more often, for the first patch).
  • Users of non-MRI implementations such as [mruby][], [JRuby][], [TruffleRuby][], [Natalie][], [Opal][], [RubyMotion][], [Artichoke][], [Prism][].
  • Ruby syntax enthusiasts who want to experiment with custom syntax extensions ‍‍.

Ruby Next also aims to help the community to assess new, experimental, MRI features by making it easier to play with them. That's why Ruby Next implements the master features as fast as possible.

See also a companion library (extracted from Ruby Next) that provides code loading hooks for your needs—[require-hooks][require-hooks].

Read more about the motivation behind the Ruby Next in this post: Ruby Next: Make all Rubies quack alike.

Ruby Next is built by Evil Martians, an American design and engineering consultancy for developer tools, AI, and cybersecurity startups.

Posts

  • Ruby Next: Make all Rubies quack alike

Talks

  • Ruby Mixology 101: adding shots of PHP, Elixir, and more (RubyKaigi 2024)
  • Ruby Next: Make old Rubies quack like a new one (RubyConf 2019)

Examples

  • Ruby gems
    • action_policy
    • anyway_config
    • graphql-fragment_cache
  • Rails applications
    • anycable_rails_demo
  • mruby
    • ACLI

Please, submit a PR to add your project to the list!

Table of contents

  • Overview
  • Quick start
  • Polyfills
  • Transpiling
    • Modes
    • CLI
    • Using in gems
    • Runtime usage
    • ruby -ruby-next
    • Logging & Debugging
  • RuboCop
  • Using with IRB
  • Using with Pry
  • Using with EOL Rubies
  • Proposed & edge features
  • Custom syntax rewriters
  • Known limitations

Overview

Ruby Next consists of two parts: core and language.

Core provides polyfills for Ruby core classes APIs via Refinements (default strategy) or core extensions (optionally or for refinement-less environments).

Language is responsible for transpiling edge Ruby syntax into older versions. It could be done programmatically or via CLI. It also could be done in runtime.

Currently, Ruby Next supports Ruby versions 2.3+, including JRuby 9.2.8+ and TruffleRuby 20.1+ (with some limitations). Support for older versions (


## Using only polyfills

First, install a gem:

```ruby
# Gemfile
gem "ruby-next-core"

# gemspec
spec.add_dependency "ruby-next-core", "~> 1.0"

NOTE: we use a different gem for distribution, ruby-next-core, to provide a zero-dependency, polyfills-only version.

Then, all you need is to load Ruby Next:

ruby
require "ruby-next"

And activate the refinement in every file where you want to use it*:

ruby
using RubyNext

Ruby Next only refines core classes if necessary; thus, this line wouldn't have any effect in edge Ruby.

NOTE: Even if the runtime already contains a monkey-patch with the backported functionality, we consider the method as dirty and activate the refinement for it. Thus, you always have predictable behaviour. That's why we recommend using refinements for gem development.

Alternatively, you can go with monkey-patches. Just add this line:

ruby
require "ruby-next/core_ext"

…


```sh
# or install globally
gem install ruby-next

[The list of supported syntax features.][features_syntax]

Transpiler modes

Since v1.0, Ruby Next only support the rewrite mode, i.e., the code transformations are applied directly to the original source code. This allows us to keep formatting as close as possible to the original code.

The main benefit of the rewrite mode is that it preserves the original code line numbers and layout, which is especially useful in debugging.

The legacy AST mode (regenerating source code from the modified abstract syntax tree) is deprecated (though still supported).

CLI

Ruby Next ships with the command-line interface (ruby-next) which provides the following functionality:

ruby-next nextify

This command allows you to transpile a file or directory into older Rubies (see, for example, the "Integrating into a gem development" section above).

It has the following interface:

…

The behaviour depends on whether you transpile a single file or a directory:

  • When transpiling a directory, the .rbnext subfolder is created within the target folder with subfolders for each supported Ruby versions (e.g., .rbnext/2.7, .rbnext/3.1, .rbnext/3.4, etc.). If you want to create only a single version (the smallest), you can also pass --single-version flag. In that case, no version directory is created (i.e., transpiled files go into .rbnext).

  • When transpiling a file and providing the output path as a file path, only a single version is created. For example:

bash
$ ruby-next nextify my_ruby.rb -o my_ruby_next.rb -V
Ruby Next core strategy: refine
Generated: my_ruby_next.rb

ruby-next core_ext

This command could be used to generate a Ruby file with a configurable set of core extensions.

Use this command if you want to backport new Ruby features to Ruby implementations not compatible with RubyGems.

It has the following interface:

bash
$ ruby-next core_ext
Usage: ruby-next core_ext [options]
    -o, --output=OUTPUT              Specify output file or stdout (default: ./core_ext.rb)
    -l, --list                       List all available extensions
        --min-version=VERSION        Specify the minimum Ruby version to support
    -n, --name=NAME                  Filter extensions by name
    -h, --help                       Print help
    -V                               Turn on verbose mode
        --dry-run                    Print verbose output without generating files

The most common use-case is to backport the APIs required by pattern matching. You can do this, for example, by including only monkey-patches containing the "deconstruct" in their names:

bash
ruby-next core_ext -n deconstruct -o pattern_matching_core_ext.rb

To list all available (are matching if --min-version or --name specified) monkey-patches, use the -l switch:

bash
$ ruby-next core_ext -l --name=filter --name=deconstruct
2.6 extensions:
  - ArrayFilter
  - EnumerableFilter
  - HashFilter

2.7 extensions:
  - ArrayDeconstruct
  - EnumerableFilterMap
  - EnumeratorLazyFilterMap
  - HashDeconstructKeys
  - StructDeconstruct

...

CLI configuration file

You can define CLI options in the .rbnextrc file located in the root of your project to avoid adding them every time you run ruby-next.

Configuration file is a YAML with commands as keys and options as multiline strings:

yaml
# ./.rbnextrc

nextify: |
  --min-version=2.7
  --edge

NOTE: The nextify section is also used by auto-transpiling when installing the gem from source and by runtime transpiling.

Integrating into a gem development

We recommend pre-transpiling source code to work with older versions before releasing it.

This is how you can do that with Ruby Next:

  • Write source code using the modern/edge Ruby syntax.

  • Generate transpiled code by calling ruby-next nextify ./lib (e.g., before releasing or pushing to VCS).

This will produce lib/.rbnext folder containing the transpiled files, lib/.rbnext/2.6, lib/.rbnext/2.7. The version in the path indicates which Ruby version is required for the original functionality. Only the source files containing new syntax are added to this folder.

NOTE: Do not edit these files manually, either run linters/type checkers/whatever against these files.

  • Add the following code to your gem's entrypoint (the file that is required first and contains other require-s):
ruby
require "ruby-next/language/setup"

RubyNext::Language.setup_gem_load_path

The setup_gem_load_path does the following:

  • Resolves the current ruby version.
  • Checks whether there are directories corresponding to the current and earlier* Ruby versions within the .rbnext folder.
  • Add the path to this directory to the $LOAD_PATH before the path to the gem's directory.

That's why need an entrypoint: all the subsequent require calls will load the transpiled files instead of the original ones due to the way feature resolving works in Ruby (scanning the $LOAD_PATH and halting as soon as the matching file is found).

NOTE: require_relative should be avoided due to the way we hijack the features loading mechanism.

If you're using runtime mode a long with setup_gem_load_path (e.g., in tests), the transpiled files are ignored (i.e., we do not modify $LOAD_PATH).

* Ruby Next avoids storing duplicates; instead, only the code for the earlier version is created and is assumed to be used with other versions. For example, if the transpiled code is the same for Ruby 2.5 and Ruby 2.6, only the .rbnext/2.7/path/to/file.rb is kept. That's why multiple entries are added to the $LOAD_PATH (.rbnext/2.6, .rbnext/2.7, and .rbnext/3.0 in the specified order for Ruby 2.5, and .rbnext/2.7 and .rbnext/3.0 for Ruby 2.6).

Transpiled files vs. VCS vs. installing from source

It's a best practice to not keep generated files in repositories. In case of Ruby Next, it's a lib/.rbnext folder.

We recommend adding this folder only to the gem package (i.e., it should be added to your spec.files) and ignore it in your VCS (e.g., echo ".rbnext/" >> .gitignore). That would make transpiled files available in releases without polluting your repository.

What if someone decides to install your gem from the VCS source? They would likely face some syntax errors due to the missing transpiled files.

To solve this problem, Ruby Next tries to transpile the source code when you call #setup_gem_load_path. It does this by calling bundle exec ruby-next nextify -o . We make the following assumptions:

  • We are in the Bundler context (since that's the most common way of installing gems from source).
  • Our Gemfile contains ruby-next gem.
  • We use .rbnextrc for transpiling options.

If the command fails we warn the end user.

This feature, auto-transpiling, is disabled by default (will likely be enabled in future versions). You can enable it by calling RubyNext::Language.setup_gem_load_path(transpile: true).

Dependency-less setup

If you want to avoid adding ruby-next-core to your gem's dependencies, you can tweak the $LOAD_PATH yourself. It's much easier to do if you go with a single transpiled version per source file (i.e., use --single-version or specify particular rewriter

Issues· 5 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Rubyhacktoberfestrubytranspiler

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言