Ruby 3.4.0 Released: What’s New, Improved, and Breaking
Ruby 3.4.0 was released on December 25, 2024, bringing exciting new features, performance improvements, and some breaking changes. Here’s a practical guide of what’s new and what you should know before upgrading to this version.
Highlights
- New
itblock parameter reference: Cleaner, more readable blocks usingitinstead of the original_1. - Language and core changes: Easier keyword argument handling, string literal warnings, reserved names, and updates to core classes.
- Standard library updates: RubyGems, Bundler, JSON, Tempfile, and more get useful updates.
- Compatibility and miscellaneous changes: New error message formats, hash and float handling, block and performance warnings, and deprecated features removed.
- Prism is now the default parser: Ruby’s parser is now
Prism, making it possible for better tooling and error messages. - Socket library upgrade: Happy Eyeballs v2 means faster, more reliable network connections out of the box.
- YJIT and Modular GC: Advanced performance and memory improvements for those using Ruby’s JIT or experimenting with garbage collection.
New Features
it Block Parameter Reference
Ruby 3.4 introduces the it block parameter, making one liner blocks more readable when you only need a single argument.
For example:
numbers = [10, 15, 20, 25]
doubled = numbers.map { it * 2 }
# => [20, 30, 40, 50]
words = %w[cat elephant dog]
long_words = words.select { it.length > 3 }
# => ["elephant"]
users = [User.new("Ana"), User.new("Bob")]
names = users.map { it.name }
# => ["Ana", "Bob"]
squares = [1, 2, 3].map { it * it }
# => [1, 4, 9]
Remember that previously, you had to use numbered parameters like _1:
[1, 2, 3].each { puts _1 }
With it, your intent is clearer and your code is easier to read, especially when you use simple blocks.
Inspiration from Other Languages
The idea of a default block parameter like it isn’t from Ruby.
Languages such as Kotlin and Groovy use it as the implicit name for a single lambda or closure parameter:
- Kotlin:
list.filter { it > 0 } - Groovy:
list.each { println it }
Other languages use similar concepts but with some differences:
- Scala: Uses
_as a placeholder for parameters:list.map(_ * 2) - Clojure: Uses
%for anonymous function parameters:(map #(* % 2) [1 2 3])
Language and Core Changes
- String literals: Mutating string literals without a
frozen_string_literalcomment now triggers a deprecation warning. This change is part of Ruby’s ongoing effort to make frozen string literals the default in future versions. For more details, see Ruby 3.4: New Defaults and What They Mean for Your Code .str = "hello" str << " world" # triggers warning unless frozen_string_literal is set -
Keyword splatting: You can now use
**nilto pass no keyword arguments. This fixes a long standing previous bug,**nilwould raise an error, but now it correctly passes an empty keyword hash, making code more reliable and predictable.def foo(**kwargs) kwargs end foo(**nil) # => {} - Block passing/indexing: Passing blocks or keyword arguments in index operations is no longer allowed. For example:
arr = [1, 2, 3] # Previously allowed, now raises an error: arr[0, &:to_s] # ArgumentError in Ruby 3.4 hash = {a: 1} # Passing keywords in index: hash[:a, foo: :bar] # ArgumentError in Ruby 3.4 - Reserved toplevel name:
::Rubyis now reserved.
Core Class Updates
- Exception:
set_backtraceaccepts new formats. - GC: New configuration options.
- Ractor: More features for Ruby’s concurrency model.
- Range:
Range#sizeraises an error for non-iterable ranges.(1..Float::INFINITY).size # raises TypeError
Standard Library Updates
- RubyGems: New
--attestationforgem pushboosts signature security and fixes default gem tagging. Details. - Bundler:
bundle lock --add-checksumsadds lockfile checksums; JRuby warnings withbundler/setupand-ware fixed. - JSON: Parsing is about 1.5x faster!
require 'json' JSON.parse('{"a":1}') # now faster - Tempfile: New
anonymous: trueoption for easier cleanup.Tempfile.create(anonymous: true) # file is removed immediately - win32/sspi.rb: Extracted to a separate gem.
Several bundled gems have been included by default.
Compatibility Issues
- Error messages and backtraces: Formatting has changed for clarity.
- Hash#inspect: Now uses modern symbol key syntax and spaces around
=>.{user: 1}.inspect # => "{user: 1}" {"user" => 1}.inspect # => '{"user" => 1}' - Float/String#to_f: Now accepts decimal strings with omitted decimal parts.
"1.".to_f # => 1.0 "1.E-1".to_f # => 0.1 -
Refinement#refined_class: Removed.
- Standard library: Deprecated constants and methods removed in Net::HTTP, Timeout, URI, and DidYouMean.
Miscellaneous Changes
- Block warnings: Passing a block to a method that does not use it now triggers a warning in verbose mode.
- Performance warnings: Redefining core methods triggers a warning.
Other Features
Prism: The New Default Parser
Ruby 3.4 switches its default parser from the legacy parse.y to the new Prism parser. The main motivation for this change is to modernize Ruby’s parsing system, making it easier to maintain and extend. Prism is written in modern C++ and designed for better performance, improved error messages, and easier integration with tools like editors and language servers.
By adopting Prism, the Ruby core team aims to:
- Simplify future language changes and syntax improvements
- Provide more accurate and helpful error reporting
- Enable better tooling for developers (e.g., syntax highlighting, code analysis)
- Reduce technical debt from the older parser codebase
For most users, this change is invisible, but it prepare for a more robust and flexible Ruby ecosystem.
Socket Library: Happy Eyeballs v2
Ruby’s socket library is used for network communication—connecting to servers, sending and receiving data, and building networked applications. If you’ve ever used TCPSocket, Socket.tcp, or similar classes, you’ve used the socket library.
In Ruby 3.4, the socket library now features Happy Eyeballs Version 2 (RFC 8305), a modern algorithm for faster and more reliable network connections. This means Ruby will try both IPv6 and IPv4 in parallel, reducing connection delays and improving connectivity.
For most developers, this improvement is automatic and requires no configuration, but it’s a big win for anyone building networked Ruby apps.
Example: Faster TCP Connections
require 'socket'
# Connect to a server using TCPSocket
socket = TCPSocket.new('example.com', 80)
socket.puts "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
puts socket.read
socket.close
With Happy Eyeballs v2, Ruby will quickly try both IPv6 and IPv4 addresses, reducing connection delays if one protocol is slow or unavailable. This means your networked Ruby applications will connect faster and more reliably, especially in environments with mixed IPv6/IPv4 support.
YJIT: Performance and Features
YJIT, Ruby’s JIT compiler, gets several upgrades:
- Unified memory limit (
--yjit-mem-size) - Compilation logs (
--yjit-log) - More Ruby methods optimized for speed
- Lower memory usage and better stats
Modular Garbage Collector
Ruby’s garbage collector is now customizable. You can swap in alternative GC implementations, including an experimental one based on MMTk (requires Rust). This is mostly for advanced users and future experimentation.
Should You Upgrade?
Ruby 3.4.0 is a solid release with performance improvements, new features, and some breaking changes. Review the compatibility details and test your code before upgrading, especially if you rely on deprecated features or custom C extensions.
Has your team been struggling with an upgrade? We can help .
Want to know what’s next for Ruby? Check out the official Ruby roadmap .
References
- Ruby 3.4.0 Release Announcement
- Ruby Prism Parser
- Happy Eyeballs RFC 8305
- Kotlin Lambdas and
it - Groovy Closures and
it - Scala Anonymous Functions
- Clojure Anonymous Functions