in future versions of Ruby! Also there are many implementation issues. GOOD=good #<Thread:0x00007ffc6b942310 run> terminated with exception (report_on_exception is true): constants_with_ractor.rb:6:in `block in <main>': can not access non-shareable objects in constant Object::BAD by non-main Ractor. (Ractor::IsolationError) <internal:ractor>:694:in `take': thrown by remote Ractor. (Ractor::RemoteError) from constants_with_ractor.rb:9:in `<main>' constants_with_ractor.rb:6:in `block in <main>': can not access non-shareable objects in constant Object::BAD by non-main Ractor. (Ractor::IsolationError) Ractor
in future versions of Ruby! Also there are many implementation issues. GOOD=good #<Thread:0x00007ffc6b942310 run> terminated with exception (report_on_exception is true): constants_with_ractor.rb:6:in `block in <main>': can not access non-shareable objects in constant Object::BAD by non-main Ractor. (Ractor::IsolationError) <internal:ractor>:694:in `take': thrown by remote Ractor. (Ractor::RemoteError) from constants_with_ractor.rb:9:in `<main>' constants_with_ractor.rb:6:in `block in <main>': can not access non-shareable objects in constant Object::BAD by non-main Ractor. (Ractor::IsolationError) Ractor
in future versions of Ruby! Also there are many implementation issues. GOOD=good #<Thread:0x00007ffc6b942310 run> terminated with exception (report_on_exception is true): constants_with_ractor.rb:6:in `block in <main>': can not access non-shareable objects in constant Object::BAD by non-main Ractor. (Ractor::IsolationError) <internal:ractor>:694:in `take': thrown by remote Ractor. (Ractor::RemoteError) from constants_with_ractor.rb:9:in `<main>' constants_with_ractor.rb:6:in `block in <main>': can not access non-shareable objects in constant Object::BAD by non-main Ractor. (Ractor::IsolationError) Ractor
threads? • “The lack of GVL allows them to fully use more cores. So in cases where Ruby can't easily use all your cores, Ractors can be better than threads.” Noah Gibbs
objects (frozen objects only refer to shareable objects) • Class/module objects • Special shareable objects (Ractor objects, and so on) • Unshareable objects: Everything else
flow: 1 object = "a string" 2 3 case object 4 when String 5 puts "object is a String" 6 else 7 puts "object is not a String" 8 end $ ruby case_when.rb object is a String
uses pattern matching: 1 # example based on https://docs.ruby-lang. 2 org/en/3.0.0/doc/syntax/pattern_matching_rdoc. 3 html 4 5 def connect(config) 6 case config 7 in db: {user:} # matches subhash and puts 8 matched value in variable user 9 puts "Connect with user '#{user}'" 10 in connection: {username: } 11 puts "Connect with connection and user '#{username}'" 12 else 13 puts "Unrecognized structure of config" 14 end 15 end 16 17 connect(db: {user: 'admin', password: ‘abc123'}) $ ruby case_in.rb Connect with user 'admin'
“one-liner”: 1 first_name = "John" 2 3 if {first_name: first_name} in {first_name: "John"} 4 5 puts "First name is John!" 6 end 7 8 if {first_name: first_name} in {first_name: "Bob"} 9 10 puts "First name is Bob!" 11 else 12 puts "First name is not Bob!" 13 end if_in.rb:3: warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! if_in.rb:7: warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! First name is John! First name is not Bob!
do 2 IO.puts("The animal is: #{animal}") 3 end 4 5 def process(%{"plant" => plant}) do 6 IO.puts("The plant is: #{plant}") 7 end 8 9 def process(%{"person" => person}) do 10 IO.puts("The person is: #{person}") 11 end •
have non-blocking fibers 4 5 Fiber.set_scheduler Scheduler.new 6 7 %w[2.6 2.7 3.0].each do |version| 8 Fiber.schedule do # Runs block of code in a separate Fiber 9 10 t = Time.now 11 # ... 16 Net::HTTP.get('rubyreferences.github.io', "/rubychanges/#{version}.html") 19 puts '%s: finished in %.3f' % [version, 20 Time.now - t] 21 end 22 end 23 end.join # At the END of the thread code, Scheduler will be called to dispatch 24 25 # all waiting fibers in a non-blocking manner 26 27 28 puts 'Total: finished in %.3f' % (Time.now - 29 start) 30 31 # Prints: 32 # 2.6: finished in 0.139 33 # 2.7: finished in 0.141 34 # 3.0: finished in 0.143 35 # Total: finished in 0.146
only a keyword argument 2 def foo(k: 1) 3 p k 4 end 5 6 h = { k: 42 } 7 8 # This method call passes a positional Hash argument 9 # In Ruby 2.7: The Hash is automatically converted to a keyword argument 10 # In Ruby 3.0: This call raises an ArgumentError 11 foo(h) 12 # => demo.rb:11: warning: Using the last argument as keyword parameters is 13 deprecated; maybe ** should be added to the call 14 # demo.rb:2: warning: The called method `foo' is defined here 15 # 42 16 17 # If you want to keep the behavior in Ruby 3.0, use double splat 18 foo(**h) #=> 42
better performance than in 2.6. Also, you will see a bunch of deprecation warnings re: positional and keyword arguments. • Fix deprecation warnings re: positional arguments. • Proactively check that your dependencies work with Ruby 3.0. Maybe your first OSS contribution? • Backtraces in Ruby 3.0 behave like in Ruby 2.4: an error message and the line number where the exception occurs are printed first, and its callers are printed later
your database to reduce the number of rows on each database server, but maintain the same schema across "shards". This is commonly called “multi-tenant" sharding.
true 3 4 has_many :projects 5 end 6 7 dev = Developer.first 8 dev.projects.first 9 # raises ActiveRecord::StrictLoadingViolationError Exception: Developer is 10 # marked as strict_loading and Project cannot be lazily loaded. 11 12 dev = Developer.includes(:projects).first 13 dev.projects.first 14 # this works
inheritance in Django, but instead of actual inheritance, this approach uses delegation to form the hierarchy and share responsibilities.” DHH • “It’s like ‘single-table inheritance’ but without inheritance (it uses delegation instead) and with multiple tables.” Ernesto
class Message < ApplicationRecord 3 include Entryable 4 has_rich_text :content 5 end 6 7 # Schema: comments[ id, content ] 8 class Comment < ApplicationRecord 9 include Entryable 10 end
be configured in `config/ storage.yml` with a new key `public: true | false` to indicate whether a service holds public blobs or private blobs. Public services will always return a permanent URL. • You can now configure different services for different attachments. More granular control for services per attachment.
a service 2 # which differs from the globally configured one, 3 # pass the +:service+ option. For instance: 4 class User < ActiveRecord::Base 5 has_one_attached :avatar, service: :s3 6 end
is an empty array. (https://github.com/rails/rails/ pull/37266) • Speed up queries when Rails knows that all values in the query are integers. (https:// github.com/rails/rails/pull/39009)
that appear in our app we want to be sure that the deprecations are never re-introduced. This will be very useful in future Ruby/Rails upgrade projects.
deprecation warnings in the Rails 6.0 test and production logs • Proactively check that our dependencies work with Rails 6.1: Maybe your first OSS contribution? Check your Gemfile.lock for incompatibilities by using RailsBump • Focus on “Removals” in the Rails 6.1 release notes. Most notable: Remove deprecated ActiveRecord::Base#update_attributes and ActiveRecord::Base#update_attributes!