Ruby 2.5

Released at: Dec 25, 2017 (NEWS file)

Dec 25, 2017 (NEWS file) Status (as of Aug 23, 2020): Security maintenance, latest is 2.5.8

Security maintenance, latest is 2.5.8 This document first published: Jun 6, 2019

Jun 6, 2019 Last change to this document: Aug 23, 2020

Highlights

Language

Top-level constant look-up is removed.

Foo::Bar doesn’t fallback to ::Bar anymore, when Foo::Bar is not found

Reason: The behavior was considered to be bringing more problems and bugs than benefits for a long time, and always issued a warning.

The behavior was considered to be bringing more problems and bugs than benefits for a long time, and always issued a warning. Discussion: Feature #11547

Feature #11547 Code: Hash :: String # Ruby 2.4: # (irb):1: warning: toplevel constant String referenced by Hash::String # => String # Ruby 2.5: # NameError (uninitialized constant Hash::String)

rescue / else / ensure are allowed inside blocks

Reason: for consistency with other something / end constructs (class and method bodies), which allowed rescue without wrapping in additional begin / end

for consistency with other / constructs (class and method bodies), which allowed without wrapping in additional / Discussion: Feature #12906

Feature #12906 Code: ( 0 .. 5 ). map do | val | puts 100 / val rescue ZeroDivisionError puts '<undividable>' end # prints: # <undividable> # 100 # 50 # 33 # 25 # 20

Notice: The syntax is not available for {} blocks, even multiline ones.

Refinements work in string interpolations

Reason: Step in a consistent effort to make refinements more useful and consistent, working everywhere regular methods work

Step in a consistent effort to make refinements more useful and consistent, working everywhere regular methods work Discussion: Feature #13812 (Japanese)

Feature #13812 (Japanese) Code: module Ref refine Time do def to_s " #{ hour } : #{ min } at #{ month } / #{ day } / #{ year } " end end end using Ref puts "Now is #{ Time . now } " # Ruby 2.4: "Now is 2019-05-27 17:49:27 +0300" -- default to_s # Ruby 2.5: "Now is 17:51 at 5/27/2019" -- refined to_s

Follow-up: Ruby 2.6 added more features making refinements available in various contexts.

Core classes and modules

Kernel

Note that methods defined in Kernel are typically available on any object, that’s why these changes are important.

Reason: Chaining singular value processing the same way Enumerable allows chaining of sequence processing methods.

Chaining singular value processing the same way allows chaining of sequence processing methods. Discussion: Feature #6721

Feature #6721 Code: [ BASE_URL , path ]. join ( '/' ) . yield_self { | url | open ( url ). read } . yield_self { | body | JSON . parse ( body , symbolyze_names: true ) } . dig ( :data , :items ) . yield_self { | items | File . write ( 'response.yml' , items . to_yaml ) }

Follow-up: Ruby 2.6 renamed (aliased) unfortunate method name to #then

pp standard library is now automatically required on the first call to Kernel#pp

#warn : uplevel: keyword argument

When uplevel: N provided to Kernel#warn , the warning message includes the file and line of the call N steps up in the callstack.

Reason: It is sometimes hard to understand exactly what code caused a warning. This feature helps identify the offending caller.

It is sometimes hard to understand exactly what code caused a warning. This feature helps identify the offending caller. Discussion: Feature #12882

Feature #12882 Documentation: Kernel#warn (it became somewhat documented at Ruby 2.6, but the feature itself has been available since 2.5)

(it became somewhat documented at Ruby 2.6, but the feature itself has been available since 2.5) Code: def that_bad_function warn ( 'do not call me' ) warn ( 'I am talking to YOU' , uplevel: 1 ) warn ( 'and tell all your clients!' , uplevel: 2 ) end def try_using_it that_bad_function # line 8 end try_using_it # line 11 # Prints: # do not call me # test.rb:8: warning: I am talking to YOU # test.rb:11: warning: and tell all your clients!

#warn : call Warning.warn

Ruby 2.4 introduced redefinable Warning.warn method, which allowed to control how warnings are handled. But warn method wasn’t calling it, so initially only warnings issued from C code could’ve been handled. 2.5 fixes it. (Was not mentioned in NEWS-2.5.0)

Discussion: Feature #12299, comment #14-15

Feature #12299, comment #14-15 Documentation: —

— Code: def Warning . warn ( msg ) puts ".warn called with: #{ msg . inspect } " end warn 'foo' , 'bar' # Ruby 2.4 prints: # foo # bar # Ruby 2.5 prints: # .warn called with: "foo

bar

"

Notes: Kernel#warn accepts multiple arguments, and joins them with "

" to pass to Warning#warn as a single string.

Module : methods for defining methods and accessors became public

Reason: The methods affected are frequently used in metaprogramming, which prior to 2.5 required reopening classes/modules or using send

The methods affected are frequently used in metaprogramming, which prior to 2.5 required reopening classes/modules or using Discussion: Feature #14132, Feature #14133

Feature #14132, Feature #14133 Affected methods: #attr , #attr_accessor , #attr_reader #attr_writer , #define_method , #alias_method , #undef_method , #remove_method .

, , , , , , . Code: Array . define_method ( :half_size ) { size . to_f / 2 } # => :half_size [ 1 , 2 , 3 ]. half_size # => 1.5

Reason: Method object can be used in a lot of contexts where the Proc can be used, and this one context (case equality) was lacking.

object can be used in a lot of contexts where the can be used, and this one context (case equality) was lacking. Discussion: Feature #14142

Feature #14142 Documentation: Method#===

Code: require 'prime' case 137 when Prime . method ( :prime? ) puts 'prime' else puts 'not!' end # prints 'prime' in Ruby 2.5+, 'not' in Ruby 2.4

Integer

#pow : modulo argument

Reason: Modular exponentiation is a useful concept, especially in cryptography, and can be vastly ineffective if performed as to sequential operations.

Modular exponentiation is a useful concept, especially in cryptography, and can be vastly ineffective if performed as to sequential operations. Discussion: Feature #12508, Feature #11003

Feature #12508, Feature #11003 Documentation: Integer#pow

Code: 2120078484650058507891187874713297895455 . pow ( 5478118174010360425845660566650432540723 , 5263488859030795548286226023720904036518 ) # => 4481650795473624846969600733813414725093

Reason: It is noted that testing values against bitmasks in Ruby is a bit non-atomic: first, calculate value & flags , and then compare result with zero (no common flags / at least one common flag), or original value (all common flags); the new methods should make the tests clearer

It is noted that testing values against bitmasks in Ruby is a bit non-atomic: first, calculate , and then compare result with zero (no common flags / at least one common flag), or original value (all common flags); the new methods should make the tests clearer Discussion: Feature #12753

Feature #12753 Documentation: Integer#allbits? , Integer#anybits? , Integer#nobits?

, , Code: CARNIVOROUS = 0b001 MAMMAL = 0b010 TERRASTRIAL = 0b100 lizard = 0b101 lizard . allbits? ( CARNIVOROUS | MAMMAL ) # => false lizard . anybits? ( CARNIVOROUS | MAMMAL ) # => true lizard . nobits? ( CARNIVOROUS | MAMMAL ) # => false

Reason: Math.sqrt(x).to_i for large numbers loses precision, so Integer.sqrt implements effective and precise integer square root algorithm

for large numbers loses precision, so implements effective and precise integer square root algorithm Discussion: Feature #13219

Feature #13219 Documentation: Integer.sqrt

Code: Integer . sqrt ( 10 ** 33 ) # => 31622776601683793 Integer . sqrt ( 10 ** 33 ) ** 2 # => 999999999999999979762122758866849 Math . sqrt ( 10 ** 33 ). to_i # => 31622776601683792 Math . sqrt ( 10 ** 33 ). to_i ** 2 # => 999999999999999916516569555499264

String

Discussion: Feature #12694, Feature #13665

Feature #12694, Feature #13665 Documentation: String#delete_prefix , String#delete_suffix

, Code: 'foo' . delete_prefix ( 'fo' ) # => 'o' 'bar' . delete_suffix ( 'r' ) # => 'ba' # Notice that bang-meethods return nil if they've deleted nothing: 'foo' . delete_prefix! ( 'ba' ) # => nil # This allows to use the methods in ifs: descr = RUBY_DESCRIPTION . dup # => "ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]" if descr . delete_prefix! ( 'ruby ' ) puts "We are running on MRI #{ descr } " # => "We are running on MRI 2.5.1p57 ...." end

#each_grapheme_cluster and #grapheme_clusters

Reason: In modern Unicode, lots of on-screen characters (graphemes) are represented by several characters, which are logically combined into “grapheme clusters”; now Ruby has a proper way to work with those concepts.

In modern Unicode, lots of on-screen characters (graphemes) are represented by several characters, which are logically combined into “grapheme clusters”; now Ruby has a proper way to work with those concepts. Discussion: Feature #13780

Feature #13780 Documentation: String#each_grapheme_cluster , String#grapheme_clusters

, Code: "🏳️‍🌈" . length # => 4 "🏳️‍🌈" . chars # => ["🏳", "️", "‍", "🌈"] "🏳️‍🌈" . grapheme_clusters # => ["🏳️‍🌈"] "🏳️‍🌈" . each_grapheme_cluster . map { | s | CGI . escape ( s ) } # => ["%F0%9F%8F%B3%EF%B8%8F%E2%80%8D%F0%9F%8C%88"]

The inverse of String#dump which escapes all non-printable and special characters.

Discussion: Feature #12275

Feature #12275 Documentation: String#undump

Code: p <<~ STR This is "fine". Or is it? STR # Prints "This is \"fine\".

Or is it?

" # ^ Now, this is dumped string, including quotes around. # How to get back to "nice" string? puts '"This is \"fine\".

Or is it?

"' . undump # Prints # This is "fine". # Or is it?

#casecmp and #casecmp? return nil for non-string arguments

Previously, those methods raised TypeError on arguments that can’t be coerced to String , now they just return nil

Reason: The behavior made consistent with == and <=> , as the methods are case-agnostic versions of those operators: when you compare incomparable things, you just get no result at all.

The behavior made consistent with and , as the methods are case-agnostic versions of those operators: when you compare incomparable things, you just get no result at all. Discussion: Feature #13312

Feature #13312 Documentation: String#casecmp , String#casecmp?

, Code: "Foo" . casecmp? ( :foo ) # Ruby 2.4: TypeError: no implicit conversion of Symbol into String # Ruby 2.5: nil

#start_with? accepts a regexp

string.start_with?(/foo/) is an equivalent of string.match?(/\Afoo/)

Discussion: Feature #13712

Feature #13712 Documentation: String#start_with? (introduced in 2.5, but documented in 2.6)

String#-@ optimized for memory preserving

String#- (freezing the string) is optimized to deduplicate frozen object

Discussion: Feature #13077, Feature #13295

Feature #13077, Feature #13295 Documentation: String#-@

Code: str = String . new ( 'not frozen' ) 10 . times . map { - str }. map ( & :object_id ) # Ruby 2.4: 10 different ids => 10 different frozen string objects # Ruby 2.5: 10 same ids => always the same frozen object 5 . times . map { - 'test' }. map ( & :object_id ) # Ruby 2.4: 5 different ids => 5 different frozen string objects # Ruby 2.5: 5 same ids => always the same frozen object

Regexp : absence operator

The underlying Onigmo Regexp library was updated, which brought new operator: (?~foo) means “match any string that do not ends with foo ”

Documentation: —

— Code: # Classic example of usefulness: matching C comments: code = <<~ C /* This is a comment. It ends here: */ // And not here: */ C code . scan ( %r{/ \* .+ \* /}m ) # => ["/* This is a comment.

It ends here: */

// And not here: */"] code . scan ( %r{/ \* (?~ \* /) \* /} ) # => ["/* This is a comment.

It ends here: */"]

Struct with keyword arguments

Struct can be created with keyword_init: true , and then its instance will require keyword arguments to initialize

Discussion: Feature #11925

Feature #11925 Documentation: Struct.new

Code: Person = Struct . new ( :first , :last , :age ) ModernPerson = Struct . new ( :first , :last , :age , keyword_init: true ) Person . new ( 'Bob' , 'Jones' , 40 ) # => #<struct Person first="Bob", last="Jones", age=40> ModernPerson . new ( first: 'Meredith' , last: 'Williams' , age: 28 ) # => #<struct ModernPerson first="Meredith", last="Williams", age=28> ModernPerson . new ( 'Meredith' , 'Williams' , 28 ) # ArgumentError (wrong number of arguments (given 3, expected 0))

Time.at : units

Time.at second argument was meant to be microseconds, but in 2.5+ it can be micro-, milli- or nano-seconds, specified by third argument: :millisecond , :usec or :microsecond (default), :nanosecond

Reason: It was noted that when you have nanoseconds value (available as Time#nsec ) and want to pass it to .at , it is inconvenient to divide it by 1000 .

It was noted that when you have nanoseconds value (available as ) and want to pass it to , it is inconvenient to divide it by . Discussion: Feature #13919

Feature #13919 Documentation: Time.at

Code: nanoseconds = 123456789 # The only way previously to create time with nsec value Time . at ( 946684800 , nanoseconds / 1000.0 ). nsec # => 123456789 # New way Time . at ( 946684800 , nanoseconds , :nanosecond ). nsec # => 123456789 # Also convenient for some contexts: .123 seconds Time . at ( 946684800 , 123 , :millisecond ). usec # => 123000

Collections

Enumerable#any? , #all? , #none? , and #one? accept patterns

Any argument that responds to #=== may now be passed (akin to grep )

Discussion: Feature #11286

Feature #11286 Documentation: Enumerable#all? , Enumerable#any? , Enumerable#none? , Enumerable#one?

, , , Code: [ 1 , 2 , nil ]. all? ( Numeric ) # => false [ 'America' , 'Europe' , 'Africa' , 'Asia' ]. any? ( /^E/ ) # => true ( 1 .. 20 ). one? ( 20 .. 30 ) # => true require 'set' [ :foo , :bar , :baz ]. none? ( Set [ :foo , :test ]) # => false

Array#append and #prepend

Just aliases for #push and #unshift

Reason: The old methods are symmetric with #pop and #shift , respectively, but asymmetric with each other and (especially #unshift ) hard to guess and remember

The old methods are symmetric with and , respectively, but asymmetric with each other and (especially ) hard to guess and remember Discussion: Feature #12746

Feature #12746 Documentation: Array#append , Array#prepend

, Code: ary = [ 1 , 2 , 3 ] ary . append ( 4 ) # => [1, 2, 3, 4] ary . prepend ( 0 ) # => [0, 1, 2, 3, 4] ary # => [0, 1, 2, 3, 4]

Hash#transform_keys and #transform_keys!

Discussion: Feature #13583

Feature #13583 Documentation: Hash#transform_keys , Hash#transform_keys!

, Code: { a: 1 , b: 2 }. transform_keys { | sym | sym . to_s . capitalize } # => {"A"=>1, "B"=>2} { a: 1 , b: 2 }. transform_keys ( & :to_s ) # => {"a"=>1, "b"=>2} { a: 1 , b: 2 }. transform_keys ( & :length ) # non-unique - the last value is taken # => {1=>2} { a: 1 , b: 2 }. transform_keys # without block - returns enumerator # => #<Enumerator: {:a=>1, :b=>2}:transform_keys> # The latter can be useful when modified by .with_index { a: 1 , b: 2 }. transform_keys . with_index ( 1 ) { | k , i | " #{ i } : #{ k } " } # => {"1: a"=>1, "2: b"=>2}

Follow-up: Since Ruby 2.5.1, the behavior of transform_keys! (bang version) is changed: Ruby 2.5.0 changes the hash as it goes (the same behavior as the old ActiveSupport method of the same name), whereas Ruby 2.5.1 first calculates the new hash and then replaces the old one: # Ruby 2.5.0, Ruby 2.4 with ActiveSupport h = { 1 => :hello , 2 => 'world' } h . transform_keys! ( & :succ ) # first, 2 => :hello replaces 2 => 'world', then the same key is processed again # => {3=>:hello} # Ruby 2.5.1 h = { 1 => :hello , 2 => 'world' } h . transform_keys! ( & :succ ) # => {2=>:hello, 3=>"world"} Discussion: Bug #14380

Discussion: Feature #13563

Feature #13563 Documentation: Hash#slice

Code: h = { a: 100 , b: 200 , c: 300 } h . slice ( :a ) #=> {:a=>100} h . slice ( :b , :c , :d ) #=> {:b=>200, :c=>300}

Follow-up: Funnily enough, what started at #8499 as discussing of importing #slice / #slice! / #except and #except! from ActiveSupport, ended up in a several tickets: #slice (current one, accepted for 2.5), #slice! (#15863, rejected by Matz, “no real-life use-case”), and #except (#15822, recent ticket, not merged as of May 2019)

Exceptions

Backtrace and error message in reverse order

New behavior is activated if STDERR is TTY

Discussion: Feature #8661

Feature #8661 Code: $ cat test.rb {a: 1}.fetch(:b) $ ruby test.rb # Ruby 2.4: test.rb:1:in `fetch': key not found: :b (KeyError) from test.rb:1:in `<main>' # Ruby 2.5: Traceback (most recent call last): 1: from test.rb:1:in `<main>' test.rb:1:in `fetch': key not found: :b (KeyError)

Follow-up: Feature is tagged “experimental” in Ruby 2.5, but as of Ruby 2.7-preview1 it is still active, so should be considered stable.

Exception#full_message provides the same string Ruby will print if exception is not caught.

Discussion: Feature #14141

Feature #14141 Documentation: Exception#full_message

Code: # test.rb begin { a: 1 }. fetch ( :b ) rescue => e puts e . full_message end # `ruby test.rb` prints: # Traceback (most recent call last): # 1: from test.rb:2:in `<main>' # test.rb:2:in `fetch': key not found: :b (KeyError) # # `ruby test.rb 2>err.log` prints: # test.rb:2:in `fetch': key not found: :b (KeyError) # from test.rb:2:in `<main>

Notice: The format is different depending of whether STDERR is TTY or not (even if you printing the returned string to STDOUT or just storing it in the variable)

The format is different depending of whether is TTY or not (even if you printing the returned string to or just storing it in the variable) Follow-up: Ruby 2.6 added options for #full_message for enforcing desired format regardless of whether STDERR is TTY

KeyError#receiver and #key

Discussion: Feature #12063

Feature #12063 Documentation: KeyError

Code: begin { a: 1 }. fetch ( :b ) rescue => e p e . receiver # => {:a=>1} p e . key # => :b end

Follow-up: Since Ruby 2.6, receiver: and key: could also be passed when creating KeyError in your code (as of Ruby 2.5, only C code could’ve create “proper” KeyError )

New class: FrozenError

Discussion: Feature #13224

Feature #13224 Documentation: FrozenError

Code: a = [ 1 , 2 , 3 ]. freeze a << 4 # Ruby 2.4: RuntimeError: can't modify frozen Array # Ruby 2.5: FrozenError (can't modify frozen Array)

Don’t hide coercion errors

Previously, some Numeric and Range methods caught errors when the provided values were incompatible, and thrown their own. This was hard to debug, so now the original error is thrown instead.

Discussion: Feature #7688

Feature #7688 Affected methods: Numeric#step , #< , #> , #>= , #<= (when other.coerce method fails), Range#initialize (when <=> method of range’s ends fail)

, , , , (when method fails), (when method of range’s ends fail) Code: class MyString def initialize ( str ) @str = str end def < => ( other ) # This will fail: we forgot to define attr_reader :str str <=> other . str end include Comparable end 'bar' .. MyString . new ( 'foo' ) # Ruby 2.4: test.rb:13:in `<main>': bad value for range (ArgumentError) # Ruby 2.5: test.rb:7:in `<=>': undefined local variable or method `str' for #<MyString:0x0000556d024e7b08 @str="bar"> (NameError)

Filesystem and IO

IO#pread and #pwrite

Two atomic methods utilize corresponding system calls to read or write file at specified offset, instead of #seek + #read / #write

Reason:

Discussion: Feature #4532

Feature #4532 Documentation: IO#pread , IO#pwrite

, Code: File . write ( 'tmp.txt' , 'test me please' ) f = File . open ( 'tmp.txt' ) f . pread ( 2 , 5 ) # => "me" f . pos # => 0, unchanged

IO#write accepts multiple arguments

Discussion: Feature #9323

Feature #9323 Documentation: IO#write

Code: $stdout . write ( 'test ' , 'me ' , 'please' ) # Prints: test me please

Notice: Standard library classes that inherit or mimic IO interface were also updated: StringIO#write , Zlib::GZipWriter#write

File.open better supports newline: option

Somewhat obscurely present IO.new / IO.read / File.open and similar methods options for converting newlines now properly switches file reading to text mode.

Discussion: Bug #13350

Bug #13350 Documentation: — (it is almost documented by referring from IO.new docs to String#encode docs, where at least longer form newline_universal: true is mentioned)

— (it is almost documented by referring from docs to docs, where at least longer form is mentioned) Code: File . write ( "crlf.txt" , "a

b

c" , newline: :crlf ) # option to convert newlines to Windows format File . binread ( 'crlf.txt' ) # => "a\r

b\r

c" -- what it really wrote File . read ( 'crlf.txt' , newline: :universal ) # Ruby 2.4: # => "a\r

b\r

c" -- newline option is ignored unless encodings passed too # Ruby 2.5: # => "a

b

c" -- newline option is respected, file read in text mode & newlines converted

File#path raises when opened with File::Constants::TMPFILE option.

The constant TMPFILE is documented as “Create an unnamed temporary file”, but before Ruby 2.5, it was still possible to request this file’s path.

Discussion: Feature #13568

Feature #13568 Documentation: File#path

Code: f = File . open ( '/tmp' , File :: RDWR | File :: TMPFILE ) f . path # Ruby 2.4: => "/tmp" -- what??? # Ruby 2.5: IOError (File is unnamed (TMPFILE?))

Same as utime , but for symlinks sets modification time of link itself, not the referred object

Dir.children and .each_child

Dir.glob : base: argument

Discussion: Feature #13056

Feature #13056 Documentation: Dir.glob

Code: Dir . glob ( '*' ) # => ["_layouts", "README.md", "err.log", "_data", "_src", "_site", "Contributing.md", "_config.yml", "2.6.md", "js", "404.html", "images", "Gemfile", "css", "Gemfile.lock"] Dir . glob ( '*' , base: '_src' ) # => ["2.5.md", "script", "tmp", "2.6.md"]

Process.last_status as an alias of $?

Much akin to Hash#fetch , allows to fetch thread-local variable or provide default value

Discussion: Feature #13009

Feature #13009 Documentation: Thread#fetch (feature is present since Ruby 2.5, but explanations added later)

(feature is present since Ruby 2.5, but explanations added later) Code: threads = [ Thread . new { Thread . current [ :name ] = "first" }, Thread . new {}] threads . each ( & :join ) threads . map { | t | t . fetch ( :name , '<not set>' ) } # => ["first", "<not set>"] threads . last . fetch ( :name ) # KeyError (key not found: :name) threads . last . fetch ( :name ) { | key | " #{ key } not set at #{ Time . now } " } # => "name not set at 2019-05-30 16:50:44 +0300"

RubyVM::InstructionSequence new methods

Misc

Random.raw_seed renamed to Random.urandom . Discussion: Bug #9569.

renamed to . Discussion: Bug #9569. Data is deprecated. It was a base class for C extensions, and it’s not necessary to expose in Ruby level. Feature #3072

Standard library

Data types

BigDecimal is now behaving more consistently with core numeric classes: BigDecimal.new is deprecated in favor of Kernel#BigDecimal() , and #clone and #dup methods return the same instance.

is now behaving more consistently with core numeric classes: is deprecated in favor of , and and methods return the same instance. Matrix : Matrix.combine and Matrix#combine . Discussion: Feature #10903 Matrix#hadamard_product (aliased as #entrywise_product )

:

Set

Set#to_s is an alias of #inspect . Discussion: Feature #13676 puts Set [ :foo , :bar ] # Ruby 2.4: #<Set:0x00005614c9069e68> # Ruby 2.5: #<Set: {:foo, :bar}>

is an alias of . Discussion: Feature #13676 Set#=== is an alias of #include? . Discussion: Feature #13801. This allows the use Sets in case and grep : case RUBY_VERSION when Set [ '2.5.0' , '2.5.1' , '2.5.2' , '2.5.3' ] # ... end [ :open , :work , :pause , :close , :open , :break ]. grep ( Set [ :open , :close ]) # => [:open, :close, :open]

is an alias of . Discussion: Feature #13801. This allows the use Sets in and : Set#reset (discussion: Feature #6589) allows to ensure set’s internal state consistency after modifying a mutable element of the set: processes = Set [[ :open ], [ :work ]] processes . first << :close processes # => #<Set: {[:open, :close], [:work]}> processes . include? ([ :open , :close ]) # => false processes . reset processes . include? ([ :open , :close ]) # => true

Text processing

StringScanner : methods #size , #captures , #values_at to introspect latest match, consistent with those of MatchData . Discussion: Feature #836 scanner = StringScanner . new ( 'y = x^2' ) scanner . scan ( /(\w+)\s*=\s*/ ) # => "y = " scanner . size # number of captures, including entire matched string # => 2 scanner . values_at ( 0 , 1 ) # 0 is "entire matched sequence", 1 is "first capture" # => ["y = ", "y"] scanner . captures # only captures # => ["y"]

: methods , , to introspect latest match, consistent with those of . Discussion: Feature #836 ERB#result_with_hash added to allow passing local variables via hash instead of Binding object. Discussion: Feature #8631 require 'erb' ERB . new ( 'x = <%= x %>' ). result_with_hash ( x: 11 ) # => "x = 11"

Network and Web

open-uri : URI.open method defined as an alias to open-uri’s Kernel#open . open-uri’s Kernel#open will be deprecated in future. Follow-up: Deprecation of Kernel#open and docs for URI.open were added in Ruby 2.7.

New no_proxy argument to Net::HTTP.new , allows to specify list of hosts that should be contacted directly, bypassing the proxy. Discussion: Feature #11195

argument to , allows to specify list of hosts that should be contacted directly, bypassing the proxy. Discussion: Feature #11195 Net::HTTP#proxy_user and Net::HTTP#proxy_pass now can be fetched from ENV['http_proxy'] if it contains them and if OS provides multiuser safe environment (read: Unix-based OS). Bug #12921: ENV [ 'http_proxy' ] = 'https://me:secret@proxy.server' http = Net :: HTTP . new ( 'https://google.com' ) http . proxy_user # => "me" http . proxy_pass # => "secret"

and now can be fetched from if it contains them and if OS provides multiuser safe environment (read: Unix-based OS). Bug #12921: Net::HTTP#min_version and Net::HTTP#max_version allow to specify min/max SSL version to use. Docs of methods with same names in OpenSSL library provide some explanations. Discussion: Feature #9450

and allow to specify min/max SSL version to use. Docs of methods with same names in OpenSSL library provide some explanations. Discussion: Feature #9450 Net::HTTP::STATUS_CODES constant (no docs) is added as HTTP Status Code Repository. Discussion: Misc #12935 require 'net/http/status' Net :: HTTP :: STATUS_CODES . fetch ( 417 ) # => "Expectation Failed"

WEBrick

Support for Proc (or any other callable) objects as body responses (no docs). Discussion: Feature #855: require 'webrick' server = WEBrick :: HTTPServer . new :Port => 8000 trap 'INT' do server . shutdown end server . mount_proc '/' do | req , res | res . chunked = true # or set headers['content-length'] explicitly res . body = proc { | out | out << Time . now . to_s } end server . start

(or any other callable) objects as body responses (no docs). Discussion: Feature #855: Server Name Indication support via :ServerName option for Webrick::HTTPServer.new . Discussion: Feature #13729

Ruby development and introspection

Coverage: support branch coverage and method coverage measurement. Discussion: Feature #13901

Binding#irb (which is available, if not documented, since Ruby 2.4, meaning “start IRB session in the current scope”), now automatically requires irb . Discussion: Bug #13099

(which is available, if not documented, since Ruby 2.4, meaning “start IRB session in the current scope”), now automatically requires . Discussion: Bug #13099 RbConfig::LIMITS is added to provide the limits of C types: require 'rbconfig/sizeof' RbConfig :: LIMITS [ 'FIXNUM_MAX' ] # => 4611686018427387903

is added to provide the limits of C types: Ripper::Filter#state to tell the state of scanner. Discussion Feature #13686

Misc

Pathname#glob Discussion: Feature #7360: require 'pathname' Pathname . new ( '.' ). glob ( '*.md' ) # => [#<Pathname:2.5.md>, #<Pathname:README.md>, #<Pathname:Contributing.md>, #<Pathname:2.6.md>]

Discussion: Feature #7360: SecureRandom.alphanumeric

mathn.rb removed from stdlib. Feature #10169. It was a library that patched some core classes to make Ruby’s math more “natural” (by providing Rational and Complex operations where necessary), but it was decided that side-effects of its implicit inclusion were too sudden, and explicit usage of Rational and Complex became much more natural in later Ruby versions.

Psych 3.0.2: No changelog available.

3.0.2: No changelog available. RDoc 6.0.1: Changelog is outdated.

6.0.1: Changelog is outdated. Rubygems 2.7.3: Changelog

2.7.3: Changelog IPAddr 1.2.1: Changelog

1.2.1: Changelog OpenSSL 2.1: Changelog.

Libraries promoted to default gems

stdgems.org project has a nice explanations of default and bundled gems concepts, as well as a list of currently gemified libraries.

“For the rest of us” this means libraries development extracted into separate GitHub repositories, and they are just packaged with main Ruby before release. It means you can do issue/PR to any of them independently, without going through more tough development process of the core Ruby.

Libraries extracted in 2.5:

Follow-up: 14 more libraries gemified in 2.6