composite-primary-keys / composite_primary_keys

Composite Primary Keys support for Active Record
1.03k stars 350 forks source link

After update to rails 7.0.2: NoMethodError: undefined method record_changed? #571

Closed Tiikara closed 2 years ago

Tiikara commented 2 years ago

Steps to reproduce

This error encountered on model.update(attrs) after update rails from 7.0.1 to 7.0.2. On 7.0.1 works perfectly.

Expected behavior

Should successfull update

Actual behavior

NoMethodError: undefined method `record_changed?' for #<Invoice id: 1393, contractor_id: 9618, storage_id: 2676, price_type_id: nil, shipment_id: nil, shipment_number: "", quantity: nil, purchase_sum: nil, sum: nil, invoice_date: nil, invoice_code: "">
Did you mean?  _record_changed?

  0) InvoicesController base rest controller test PATCH update should pass simple request
     Failure/Error: if model.update(attrs)

     NoMethodError:
       undefined method `record_changed?' for #<Invoice id: 1393, contractor_id: 9618, storage_id: 2676, price_type_id: nil, shipment_id: nil, shipment_number: "", quantity: nil, purchase_sum: nil, sum: nil, invoice_date: nil, invoice_code: "">
       Did you mean?  _record_changed?
# D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activemodel-7.0.2/lib/active_model/attribute_methods.rb:458:in `method_missing'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/bundler/gems/composite_primary_keys-2e16732c38d7/lib/composite_primary_keys/autosave_association.rb:17:in `save_has_one_association'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/autosave_association.rb:198:in `block in add_autosave_association_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/autosave_association.rb:166:in `instance_eval'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/autosave_association.rb:166:in `block in define_non_cyclic_method'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:400:in `block in make_lambda'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:236:in `block in halting_and_conditional'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:599:in `block in invoke_after'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:599:in `each'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:599:in `invoke_after'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:108:in `run_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:929:in `_run_update_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/callbacks.rb:465:in `_update_record'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/timestamp.rb:121:in `_update_record'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/persistence.rb:1066:in `create_or_update'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/callbacks.rb:457:in `block in create_or_update'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/autosave_association.rb:370:in `around_save_collection_association'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:127:in `block in run_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:138:in `run_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:929:in `_run_save_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/callbacks.rb:457:in `create_or_update'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/timestamp.rb:126:in `create_or_update'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/persistence.rb:616:in `save'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/validations.rb:47:in `save'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/transactions.rb:298:in `block in save'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/transactions.rb:354:in `block in with_transaction_returning_status'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:314:in `transaction'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/transactions.rb:350:in `with_transaction_returning_status'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/transactions.rb:298:in `save'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/suppressor.rb:50:in `save'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/persistence.rb:770:in `block in update'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/transactions.rb:354:in `block in with_transaction_returning_status'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/transactions.rb:350:in `with_transaction_returning_status'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/persistence.rb:768:in `update'
     # ./lib/application_actions.rb:67:in `block in update_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/metal/mime_responds.rb:205:in `respond_to'
     # ./lib/application_actions.rb:64:in `update_action'
     # ./app/controllers/act_controller.rb:35:in `update'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/abstract_controller/base.rb:214:in `process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/metal/rendering.rb:53:in `process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/abstract_controller/callbacks.rb:234:in `block in process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
     # ./lib/h_d/database_setter.rb:35:in `with_database'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:127:in `block in run_callbacks'
     # ./lib/current_requests.rb:22:in `block in ensure_gracefull_shutdown_requests'
     # ./lib/current_requests.rb:10:in `process_request'
     # ./lib/current_requests.rb:21:in `ensure_gracefull_shutdown_requests'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:127:in `block in run_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/callbacks.rb:138:in `run_callbacks'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/abstract_controller/callbacks.rb:233:in `process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/metal/rescue.rb:22:in `process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/metal/instrumentation.rb:67:in `block in process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/notifications.rb:206:in `block in instrument'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2/lib/active_support/notifications.rb:206:in `instrument'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/metal/instrumentation.rb:66:in `process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/metal/params_wrapper.rb:259:in `process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/activerecord-7.0.2/lib/active_record/railties/controller_runtime.rb:27:in `process_action'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/abstract_controller/base.rb:151:in `process'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionview-7.0.2/lib/action_view/rendering.rb:39:in `process'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/metal.rb:188:in `dispatch'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/test_case.rb:601:in `block in process_controller_response'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/test_case.rb:593:in `wrap_execution'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/test_case.rb:601:in `process_controller_response'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/test_case.rb:511:in `process'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib/devise/test/controller_helpers.rb:35:in `block in process'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib/devise/test/controller_helpers.rb:104:in `catch'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib/devise/test/controller_helpers.rb:104:in `_catch_warden'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib/devise/test/controller_helpers.rb:35:in `process'
     # D:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/actionpack-7.0.2/lib/action_controller/test_case.rb:418:in `patch'
     # ./spec/rails_helper.rb:97:in `block (2 levels) in describe_rest_test_update

System configuration

Rails version: 7.0.2

Ruby version: 3.1.0

ianfleeton commented 2 years ago

This method has changed in Rails from #record_changed? to #_record_changed? between 7.0.1 and 7.0.2.

Appears fixed with autosave_assocation.rb line 17 changed to: if (autosave && record.changed_for_autosave?) || new_record? || _record_changed?(reflection, record, key)

Update: looks addressed in #570

zach-sim commented 2 years ago

For others who see this issue before the pr is merged, the below monkey-patch is a good temporary fix.

module ActiveRecord
  module AutosaveAssociation
    def record_changed?(reflection, record, key)
      _record_changed?(reflection, record, key)
    end
  end
end
cfis commented 2 years ago

Fixed by #570.