diff --git a/lib/rspec/active_model/mocks/mocks.rb b/lib/rspec/active_model/mocks/mocks.rb index 8cfe696..07a1464 100644 --- a/lib/rspec/active_model/mocks/mocks.rb +++ b/lib/rspec/active_model/mocks/mocks.rb @@ -61,6 +61,9 @@ def [](key) # alternative to record['id'] alias_method :_read_attribute, :[] + # Rails>7.1 added read_attribute for external usage similar to record['id'] + alias_method :read_attribute, :[] + # Returns the opposite of `persisted?` def new_record? !persisted? @@ -103,6 +106,7 @@ def mock_model(string_or_model_class, stubs={}) model_class = Object.const_set(string_or_model_class, Class.new do # rubocop:disable Style/SingleLineMethods extend ::ActiveModel::Naming + def self.primary_key; :id; end # For detection of being a valid association in 7+ @@ -146,6 +150,7 @@ def self.param_delimiter; "-"; end msingleton = class << m; self; end msingleton.class_eval do include ActiveModelInstanceMethods + include ActiveRecordInstanceMethods if defined?(ActiveRecord) include ActiveModel::Conversion include ActiveModel::Validations diff --git a/spec/rspec/active_model/mocks/mock_model_spec.rb b/spec/rspec/active_model/mocks/mock_model_spec.rb index d936aa0..8d32d7f 100644 --- a/spec/rspec/active_model/mocks/mock_model_spec.rb +++ b/spec/rspec/active_model/mocks/mock_model_spec.rb @@ -482,6 +482,44 @@ def self.===(_other) end end + describe "attribute access methods" do + it "supports [] method with symbol" do + model = mock_model(MockableModel, :name => "John", :age => 25) + expect(model[:name]).to eq("John") + expect(model[:age]).to eq(25) + end + + it "supports [] method with string" do + model = mock_model(MockableModel, :name => "John", :age => 25) + expect(model["name"]).to eq("John") + expect(model["age"]).to eq(25) + end + + it "supports read_attribute method with symbol" do + model = mock_model(MockableModel, :name => "John", :age => 25) + expect(model.read_attribute(:name)).to eq("John") + expect(model.read_attribute(:age)).to eq(25) + end + + it "supports read_attribute method with string" do + model = mock_model(MockableModel, :name => "John", :age => 25) + expect(model.read_attribute("name")).to eq("John") + expect(model.read_attribute("age")).to eq(25) + end + + it "supports _read_attribute method with symbol" do + model = mock_model(MockableModel, :name => "John", :age => 25) + expect(model._read_attribute(:name)).to eq("John") + expect(model._read_attribute(:age)).to eq(25) + end + + it "supports _read_attribute method with string" do + model = mock_model(MockableModel, :name => "John", :age => 25) + expect(model._read_attribute("name")).to eq("John") + expect(model._read_attribute("age")).to eq(25) + end + end + describe "ActiveModel Lint tests" do # rubocop:disable Lint/EmptyExpression,Metrics/BlockNesting begin @@ -519,6 +557,7 @@ def self.===(_other) ERR end include Test::Unit::Assertions + if defined?((Test::Unit::AutoRunner.need_auto_run = ())) Test::Unit::AutoRunner.need_auto_run = false elsif defined?((Test::Unit.run = ())) @@ -532,6 +571,7 @@ def self.===(_other) else require 'test/unit/assertions' include Test::Unit::Assertions + if defined?((Test::Unit::AutoRunner.need_auto_run = ())) Test::Unit::AutoRunner.need_auto_run = false elsif defined?((Test::Unit.run = ())) diff --git a/spec/support/ar_classes.rb b/spec/support/ar_classes.rb index 6d05540..19c27c7 100644 --- a/spec/support/ar_classes.rb +++ b/spec/support/ar_classes.rb @@ -41,6 +41,7 @@ class NonActiveRecordModel class MockableModel < ActiveRecord::Base extend Connections + has_one :associated_model end @@ -54,6 +55,7 @@ class SubMockableModel < MockableModel class AssociatedModel < ActiveRecord::Base extend Connections + belongs_to :mockable_model belongs_to :nonexistent_model, :class_name => "Other" end @@ -61,5 +63,6 @@ class AssociatedModel < ActiveRecord::Base class AlternatePrimaryKeyModel < ActiveRecord::Base self.primary_key = :my_id extend Connections + attr_accessor :my_id end