Skip to content

RuntimeError: can't add a new key into hash during iteration #50154

Closed
@vill

Description

The alias_attribute method does not work after upgrading Rails from version 7.0.8 to version 7.1.2. Perhaps everything went bad after this request.

Steps to reproduce

Rails 7.0.8 - This works

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  # Activate the gem you are reporting the issue against.
  gem "activerecord", "~> 7.0.8"
  gem "sqlite3"
end

require "active_record"
require "minitest/autorun"
require "logger"

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :balance_transactions, force: true do |t|
    t.string :type, null: false
    t.string :old_field
  end
end

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

class BalanceTransaction < ApplicationRecord
  alias_attribute :new_field, :old_field
end

class BalanceTransaction
  class TopUp < BalanceTransaction
    self.abstract_class = true

    # Common validations, etc.
  end
end

class BalanceTransaction
  module Type
    class CashTopUp < BalanceTransaction::TopUp
    end
  end
end

class BugTest < Minitest::Test
  def test_association_stuff
    balance_transaction = BalanceTransaction::Type::CashTopUp.create!

    assert_equal 1, BalanceTransaction::Type::CashTopUp.count
  end
end

Rails 7.1.2 - This doesn't work

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  # Activate the gem you are reporting the issue against.
  gem "activerecord", "~> 7.1.2"
  gem "sqlite3"
end

require "active_record"
require "minitest/autorun"
require "logger"

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :balance_transactions, force: true do |t|
    t.string :type, null: false
    t.string :old_field
  end
end

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

class BalanceTransaction < ApplicationRecord
  alias_attribute :new_field, :old_field
end

class BalanceTransaction
  class TopUp < BalanceTransaction
    self.abstract_class = true

    # Common validations, etc.
  end
end

class BalanceTransaction
  module Type
    class CashTopUp < BalanceTransaction::TopUp
    end
  end
end

class BugTest < Minitest::Test
  def test_association_stuff
    balance_transaction = BalanceTransaction::Type::CashTopUp.create!

    assert_equal 1, BalanceTransaction::Type::CashTopUp.count
  end
end

Rails 7.1.2 - This works

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  # Activate the gem you are reporting the issue against.
  gem "activerecord", "~> 7.1.2"
  gem "sqlite3"
end

require "active_record"
require "minitest/autorun"
require "logger"

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :balance_transactions, force: true do |t|
    t.string :type, null: false
    t.string :old_field
  end
end

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

class BalanceTransaction < ApplicationRecord
  alias_attribute :new_field, :old_field
end

class BalanceTransaction
  class TopUp < BalanceTransaction
    self.abstract_class = true

    # Common validations, etc.
  end
end

class BalanceTransaction
  module Type
    class CashTopUp < BalanceTransaction::TopUp
    end
  end
end

class BugTest < Minitest::Test
  def test_association_stuff
    BalanceTransaction.new # <---- After this everything starts working

    balance_transaction = BalanceTransaction::Type::CashTopUp.create!

    assert_equal 1, BalanceTransaction::Type::CashTopUp.count
  end
end

Rails 7.1.2 - This works

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  # Activate the gem you are reporting the issue against.
  gem "activerecord", "~> 7.1.2"
  gem "sqlite3"
end

require "active_record"
require "minitest/autorun"
require "logger"

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :balance_transactions, force: true do |t|
    t.string :type, null: false
    t.string :old_field
  end
end

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

class BalanceTransaction < ApplicationRecord
end

class BalanceTransaction
  class TopUp < BalanceTransaction
    self.abstract_class = true

    alias_attribute :new_field, :old_field # <--- Alias declaration moved here

    # Common validations, etc.
  end
end

class BalanceTransaction
  module Type
    class CashTopUp < BalanceTransaction::TopUp
    end
  end
end

class BugTest < Minitest::Test
  def test_association_stuff
    balance_transaction = BalanceTransaction::Type::CashTopUp.create!

    assert_equal 1, BalanceTransaction::Type::CashTopUp.count
  end
end

Expected behavior

The alias_attribute method should create aliases without errors.

Actual behavior

RuntimeError: can't add a new key into hash during iteration
    /usr/local/bundle/gems/activemodel-7.1.2/lib/active_model/attribute_methods.rb:376:in `block in aliases_by_attribute_name'

System configuration

Rails version: 7.1.2

Ruby version: 3.2.2

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions