Previewing Rails 7 upcoming changes

24th August 2021 – 849 words

Rails 7 is taking up speed. There is no beta out yet, but a lot of features, especially in ActiveRecord are available, if one want’s to wade through the Changelogs.

To view all the changes per framework gem, just access the main branch’s CHANGELOG.md:

Too many? … Most of those changes are very specific and maybe not interesting for all audiences, and ActionText, ActionMailbox is not used by us. I collected the most interesting changes for me below.

Active Record

  • Attribute level database encryption The most relevant feature in the bunch, this will make it so much easier to be more secure “by default”. See the new guide
  • Post.where(...).in_order_of(1, 2, 3) why would you need that? For example if you get the ordering from another source, like Redis inline calculations, Elasticsearch Results. You want to load the same models from the DB and keep the order from Elasticsearch.
  • Tagging of SQL queries to make it easier to find the culprit in the slowlog: config.active_record.query_log_tags_enabled = true. Controller & action name are already used as the default tags.
  • Nulls First/Nulls Last can be specified, unfortunately only in the internal Arel, not in Relation AFAICS: User.arel_table[:first_name].desc.nulls_last and nulls_first
  • MyModel.enumerate_columns_in_select_statements = true per Model
    • Normally if you make Post.first you will generate a select * from. With this flag, AR will use the column names: select title, description from posts
  • Enum: removing the underscore from prefix, suffix, default: enum state: [], _prefix: :state, _suffix: :foo -> prefix: suffix
  • Load Async: Another maybe major feature: You are now able to parallelize the SQL loading, best on controller level, by appending .load_aync the query: @posts = Post.load_async I need to fiddle around with this feature and try to find limitations/thread limits etc.
  • relation.excluding(post, another_post) replaces the common pattern of finding sibling objects without one self:
      class Post
        def simliar_posts
          user.posts.excluding(self)
        end
    
  • timstamptz now supported as a column type - I have one app, where I only use structure.sql because of this. Happy to be able to go back to schema.rb
  • relation.where().invert_where nice convenience
  • relation.where.associated(:user) all records that have an association, shorthand for where.not(user_id: nil)
  • relation.where.missing(:user) opposite of above

Active Storage

  • Predefined variants
      has_one_attached :avatar do |attachable|
        attachable.variant :thumb, resize: "100x100"
        attachable.variant :medium, resize: "300x300", monochrome: true
      end
      ...
      user.avatar.variant(:thumb)
    
    • nice! I used model methods that made the commonly used variants, e.g. company logo. Can remove that now.
  • vips is the new default, but mini_magick can still be used. To opt-in with old apps:
    • config.active_storage.variant_processor = :vips.
  • Analyzer improved: will determine if the file has audio and/or video data and prefills: metadata[:audio] and metadata[:video]
  • Previewing video files: FFMpeg args configurable under config.active_storage.video_preview_arguments.
  • Audio analyzer added: duration + bitrate extracted
  • blob expiration can be set individually per call::
    • rails_blob_path(user.avatar, disposition: "attachment", expires_in: 30.minutes)

Active Support

  • Added a faster and more compact ActiveSupport::Cache serialization format.
    • Opt-in: config.active_support.cache_format_version = 7.0, it is backwards compatible
  • Improved test parallelization - only in effect if testing more than one file etc.
    • as RSpec user I look with envy to the easier parallelization features over at Test::Unit…
  • rails app:update doesn’t overwrite en.yml, routes.rb, puma.rb, storage.yml
    • Nice! Always a nuisance when using that very very helpful task
  • Quick benchmark: Rails.benchmark("some info") { ... }
    • I guess that’s just an alias for Benchmark.measure { ... }, but good to have it available

How long until Rails 7 is released/RC is published?

Of course, no one except the core team knows this. To make an educated guess, these are the days between each releases (from Rubygems):

Version jump days
4.0.0 -> 4.1.0.beta1 176
4.1.0 -> 4.2.0.beta1 134
4.2.0 -> 5.0.0.beta1 363
5.0.0 -> 5.1.0.beta1 301
5.1.0 -> 5.2.0.beta1 214
5.2.0 -> 6.0.0.beta1 284
6.0.0 -> 6.1.0.rc1 444

The “minor” jumps between 4.0 -> 4.1 -> 4.2 etc. took an average of 273 days from release of the previous minor upgrade to the first beta/rc or release.

6.1.0 was released on 9th December 2020, adding 258 days would put the release on September 2021! Hopefully not taking 444 days as Rails 6.1 took… that would put the release on February 2021. 😉