PG::Coder.new(hash) is deprecated. Please use keyword arguments instead – Ruby-on-rails

by
Ali Hasan
postgresql ruby-on-rails

The Problem:

The PG::Coder.new(hash) method is deprecated since version 1.5.2 of the Ruby pg gem. When updating to this version, a warning is displayed in the console. The deprecation message suggests using keyword arguments instead, but no specific guidance or examples are provided.

The Solutions:

Solution 1: Using Keyword Arguments

The updated solution uses keyword arguments to pass the hash to the PG::TextDecoder::TimestampUtc class. Here’s the modified code:

decoder_class = ActiveRecord.default_timezone == :utc ?
  PG::TextDecoder::TimestampUtc :
  PG::TextDecoder::TimestampWithoutTimeZone

@timestamp_decoder = decoder_class.new(to_h: @timestamp_decoder.to_h)
@connection.type_map_for_results.add_coder (@timestamp_decoder)

By using keyword arguments, the code becomes more readable and explicit, making it clear which arguments are being passed to the class.

Solution 2: Update Rails and Postgres Adapter

To resolve the deprecation warning "PG::Coder.new(hash) is deprecated. Please use keyword arguments instead," it is necessary to upgrade the Rails environment from 7.0.4 to 7.0.6, which includes the updated postgres_adapter. Upgrading only Postgres is insufficient to address the issue.

Solution 3: Monkeypatching in Rails

For Rails 6.1.x users, monkeypatching the offending method in Rails is a workaround. Create a `my_monkeypatch.rb` file in `config/initializers` with the following content:

module ActiveRecord
  module ConnectionAdapters
    class PostgreSQLAdapter < AbstractAdapter
      def update_typemap_for_default_timezone
        if @default_timezone != ActiveRecord::Base.default_timezone && @timestamp_decoder
          decoder_class = ActiveRecord::Base.default_timezone == :utc ?
            PG::TextDecoder::TimestampUtc :
            PG::TextDecoder::TimestampWithoutTimeZone

          @timestamp_decoder = decoder_class.new(**@timestamp_decoder.to_h)
          @connection.type_map_for_results.add_coder(@timestamp_decoder)
          @default_timezone = ActiveRecord::Base.default_timezone
        end
      end
    end
  end
end

Remember to run `bin/spring stop` to apply the changes. If the warning appears during testing, require the monkeypatch file from `test/test_helper.rb` by adding the following line:

require_relative '../config/initializers/my_monkeypatch.rb'

Q&A

How to fix PG::Coder.new(hash) is deprecated issue

Upgrading Rails 7.0.4 to 7.0.6 should make the warning go away.

Fix "PG::Coder.new(hash) is deprecated" issue in Rails 6.1.x

Monkeypatch the method in Rails by creating a "my_monkeypatch.rb" file in "config/initializers".

Video Explanation:

The following video, titled "How Ruby 3.0's changes in keyword arguments breaks your old code", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

The way positional and keyword parameters are interpreted change from Ruby 2.7 to 3.0, which can break a lot of legacy code.