rspec / rspec-activemodel-mocks

Add stub_model and mock_model to rspec-mocks
MIT License
119 stars 32 forks source link

Rails 5.2.1 Support - Inversed_from support #31

Closed richseviora closed 6 years ago

richseviora commented 6 years ago

Rails 5.2.1 introduced a change that breaks models when used with associations. It throws an error about not having the method inversed_from defined.

I have patched it in my client's application with this patchfile.

# frozen_string_literal: true

module RSpec
  module ActiveModel
    module Mocks
      module Mocks
        # This extends the Association mock class so that it includes the inversed_from method introduced in 5.2.1
        # https://github.com/rails/rails/commit/6edf354b656ec556c3573402019504a519531953#diff-c47e1c26ae8a3d486119e0cc91f40a30
        class Association
          def inversed_from(record)
            self.target = record
            @inversed = !!record # rubocop:disable DoubleNegation
          end
        end
      end
    end
  end
end
kreintjes commented 6 years ago

I can confirm this issue. @CUnknown made a fix for it which you can find here: https://github.com/rspec/rspec-activemodel-mocks/pull/32. You can use this in your project with gem 'rspec-activemodel-mocks', '~> 1.0.3', git: 'https://github.com/CUnknown/rspec-activemodel-mocks'. It works in my project :)

viraptor commented 6 years ago

I raised this in the wrong repo initially - I think it's the same issue:

What Ruby, Rails and RSpec versions are you using?

Ruby version: 2.3 Rails version: 5.2.1 Rspec version: 3.8.0

Observed behaviour

mock_model(SomeModel) raises an exception on:

NoMethodError:
--
  | undefined method `inversed_from' for #<RSpec::ActiveModel::Mocks::Mocks::Association:0x007fe0e713b828>
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/associations/association.rb:101:in `set_inverse_instance'
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/associations/belongs_to_association.rb:23:in `replace'
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/associations/singular_association.rb:17:in `writer'
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/associations/builder/association.rb:116:in `expiry_event='
  | # ./vendor/bundle/ruby/2.3.0/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:51:in `public_send'
  | # ./vendor/bundle/ruby/2.3.0/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:51:in `_assign_attribute'
  | # ./vendor/bundle/ruby/2.3.0/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:44:in `block in _assign_attributes'
  | # ./vendor/bundle/ruby/2.3.0/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:43:in `each'
  | # ./vendor/bundle/ruby/2.3.0/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:43:in `_assign_attributes'
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/attribute_assignment.rb:23:in `_assign_attributes'
  | # ./vendor/bundle/ruby/2.3.0/gems/activemodel-5.2.1/lib/active_model/attribute_assignment.rb:35:in `assign_attributes'
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/core.rb:314:in `initialize'
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/inheritance.rb:66:in `new'
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/inheritance.rb:66:in `new'
  | # ./vendor/bundle/ruby/2.3.0/gems/activerecord-5.2.1/lib/active_record/persistence.rb:52:in `create!'
  | # ./spec/models/credit_expiry/unexpiry_event_spec.rb:6:in `block (3 levels) in <top (required)>'

The same model works fine with rails 5.1.x.

Expected behaviour

No exception.

Can you provide an example app?

https://github.com/viraptor/mock_model_repro/commit/c88e18cd97952a41f07795fe08b02dc7999caf57

JonRowe commented 6 years ago

The fix from #32 has been merged in with #33