crashtech/torque-postgresql

Ruby 3.0.2 error: when concating to relation with default scope

Closed this issue · 5 comments

Hi,

Trying to upgrade to ruby 3.0.2 and I am getting an error when I am trying to concat to has_many with default-scope when torque is installed:

Reproduce script:

# 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"
  gem "torque-postgresql"
  gem "pg"
end

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

ActiveRecord::Base.establish_connection(
  adapter:  "postgresql",
  database: "test",
  encoding: "unicode",
  host:     "localhost",
  port:     "5432",
  password: "12345",
  username: "test")

ActiveRecord::Schema.define do
  drop_table "projects"
  drop_table "managers"

  create_table "projects" do |t|
    t.string "title"
    t.timestamps
  end

  create_table "managers" do |t|
    t.string "name"
    t.integer :project_id
    t.integer "position"
    t.timestamps
  end
end

class Manager < ActiveRecord::Base
  belongs_to :project
end

class Project < ActiveRecord::Base
  # If we remove the "order" here the test will pass
  has_many :managers, -> { order(position: :asc) }
end


class BugTest < Minitest::Test
  def test_concat
    project = Project.create!
    project.managers << Manager.new
    project.save
  end
end

Output (removes lines of gem install)

ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-darwin20]
/Users/yosi/.rvm/gems/ruby-3.0.2/gems/torque-postgresql-2.2.0/lib/torque/postgresql/attributes/builder/enum.rb:119: warning: assigned but unused variable - type
/Users/yosi/.rvm/gems/ruby-3.0.2/gems/torque-postgresql-2.2.0/lib/torque/postgresql/attributes/builder/period.rb:47: warning: method redefined; discarding old threshold
-- drop_table("projects")
   -> 0.0188s
-- drop_table("managers")
   -> 0.0016s
-- create_table("projects")
   -> 0.0063s
-- create_table("managers")
   -> 0.0056s
Run options: --seed 36840

# Running:

E

Error:
BugTest#test_concat:
ArgumentError: wrong number of arguments (given 2, expected 1)
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/relation.rb:27:in `initialize'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/torque-postgresql-2.2.0/lib/torque/postgresql/relation.rb:121:in `initialize'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/relation/delegation.rb:118:in `new'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/relation/delegation.rb:118:in `create'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/reflection.rb:285:in `build_scope'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association_scope.rb:165:in `eval_scope'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association_scope.rb:129:in `block (2 levels) in add_constraints'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association_scope.rb:128:in `each'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association_scope.rb:128:in `block in add_constraints'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association_scope.rb:125:in `reverse_each'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association_scope.rb:125:in `add_constraints'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association_scope.rb:29:in `scope'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association_scope.rb:7:in `scope'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/association.rb:244:in `association_scope'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_association.rb:282:in `add_to_target'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_association.rb:437:in `block in concat_records'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_association.rb:435:in `each'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_association.rb:435:in `concat_records'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/has_many_association.rb:130:in `concat_records'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_association.rb:120:in `block in concat'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_association.rb:135:in `block in transaction'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/database_statements.rb:320:in `block in transaction'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activesupport-6.1.4.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activesupport-6.1.4.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activesupport-6.1.4.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activesupport-6.1.4.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activesupport-6.1.4.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/connection_adapters/abstract/database_statements.rb:320:in `transaction'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/transactions.rb:209:in `transaction'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_association.rb:134:in `transaction'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_association.rb:120:in `concat'
    /Users/yosi/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.1/lib/active_record/associations/collection_proxy.rb:1027:in `<<'
    repro.rb:58:in `test_concat'

I did monkey patch for now to fix it -

::Torque::PostgreSQL::Relation::Initializer.class_eval do
  def initialize(
    klass,
    table: klass.arel_table,
    predicate_builder: klass.predicate_builder,
    values: {}
  )
    super

    if klass.define_attribute_methods &&
         klass.superclass != ActiveRecord::Base &&
         !klass.superclass.abstract_class?
      klass.superclass.send(:relation)
    end
  end
end

The important change is initialize method signature, @crashtech if you want I can submit PR for that

@crashtech Can you please give it a look?

Hey, sorry for the delay, I was moving to a new place and keeping up with my work. Hard times.
I'll push a fix for this tomorrow, but just so you know, the thing is that there is no need to specify the signature of the method, a simple def initialize(klass, *, **) will fix the problem.

@yosiat it should be fixed now in the version 2.2.1

@crashtech hope everything is well with moving to new place!

Thanks for the fix and explanation I always learn from your PRs :)