brainspec / enumerize

Enumerated attributes with I18n and ActiveRecord/Mongoid support
MIT License
1.72k stars 190 forks source link

Model with `has_many :through` and `default_scope` fails when assing new relation #419

Closed dervish86 closed 1 year ago

dervish86 commented 1 year ago

Greetings! We are attempting to upgrade to the latest version of enumerize (2.6.0), but we've encountered an error: ArgumentError: unknown keyword :some_keyword. It appears that the current version is not compatible with Ruby 2.7. However, when I ran the script on Ruby 3.0, it worked without any issues.

Steps to reproduce

require 'bundler/inline'

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

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

  gem 'rails'
  gem 'sqlite3'
  gem 'enumerize', '2.6.0'
end

require 'active_record'
require 'minitest/autorun'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')

ActiveRecord::Schema.define do
  create_table :physicians do |t|
    t.string :name
    t.timestamps
  end

  create_table :patients do |t|
    t.string :name
    t.timestamps
  end

  create_table :appointments do |t|
    t.belongs_to :physician
    t.belongs_to :patient
    t.datetime :appointment_date
    t.timestamps
  end
end

class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, through: :appointments
end

class Appointment < ActiveRecord::Base
  extend Enumerize

  default_scope { where(appointment_date: nil) }

  belongs_to :physician
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  has_many :appointments
  has_many :physicians, through: :appointments
end

class BugTest < Minitest::Test
  def test_bug
    physician = Physician.create
    patient = Patient.new

    patient.physicians << physician

    assert_includes patient.physicians, physician
  end
end

Actual behavior

Error:
BugTest#test_bug:
ArgumentError: unknown keyword: :physician

System configuration

Ruby 2.7.7 Rails 7.0.4.2, 6.1.7.2

dervish86 commented 1 year ago

І think we can simplify the issue: If we will add a new test to https://github.com/brainspec/enumerize/blob/master/test/base_test.rb the test fail on ruby 2.7

class BaseTest < MiniTest::Spec
  #...
  it 'allows initializing object without keyword arguments' do
    parent_klass = Class.new do
      attr_reader :arguments

      def initialize(arguments)
        @arguments = arguments
      end
    end

    klass = Class.new(parent_klass) do
      extend Enumerize

      def initialize(arguments)
        super
      end
    end

    params = {'string_key' => 1, symbol_key: 2}

    object = klass.new(params)

    expect(object.arguments).must_equal params
  end
end

I guess the issue might be fixed by replacing https://github.com/brainspec/enumerize/blob/6fa98bfb049f6c761ce7f37f4fdc8a32c22b4502/lib/enumerize/base.rb#L52 with

def initialize(...)
nashby commented 1 year ago

@dervish86 Hey! I just merged a fix (basically your proposed changes), please take a look!

dervish86 commented 1 year ago

@nashby thank you for resolving the issue! I can confirm that we are no longer seeing the error 🎉

nashby commented 1 year ago

2.6.1 has been released with a fix!