From 0fc3494724ec6b4c5d2de114039f2043a8b164c0 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:05:06 +0100 Subject: [PATCH 01/14] Add in AND/OR logic for find_by --- lib/testing_record/dsl/builder/filters.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/testing_record/dsl/builder/filters.rb b/lib/testing_record/dsl/builder/filters.rb index 6ff4a48..86f2374 100644 --- a/lib/testing_record/dsl/builder/filters.rb +++ b/lib/testing_record/dsl/builder/filters.rb @@ -14,16 +14,21 @@ def exists?(attributes) end # Finds all entities that match specified attribute values + # attributes (Hash) -> The attributes you wish to filter on, each is iterated through sequentially + # :logic (Symbol) -> Whether to use `AND` or `OR` logic to combine each sequential key in attributes hash # # @return [Array] - def find_by(attributes) - pool = all - attributes.each do |key, value| - TestingRecord.logger.debug("Current user pool size: #{pool.length}") - TestingRecord.logger.debug("Filtering User list by #{key}: #{value}") - pool = pool.select { |entity| entity.attributes[key] == value } + def find_by(attributes, logic: :AND) + TestingRecord.logger.debug("Filtering Entity: '#{self}' list by #{attributes}. Logic: '#{logic}'") + if logic == :OR + all.select do |entity| + attributes.any? { |key, value| entity.key?(key) && entity.fetch(key) == value } + end + else + all.select do |entity| + attributes.all? { |key, value| entity.fetch(key) == value } + end end - pool end # Finds an entity with the provided email address From 227ec3a65f7fadad5c258a55562651afac7897e4 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:08:53 +0100 Subject: [PATCH 02/14] Fix bug on finder to ensure we lookup on the nested entity attributes hash --- lib/testing_record/dsl/builder/filters.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/testing_record/dsl/builder/filters.rb b/lib/testing_record/dsl/builder/filters.rb index 86f2374..368992d 100644 --- a/lib/testing_record/dsl/builder/filters.rb +++ b/lib/testing_record/dsl/builder/filters.rb @@ -22,11 +22,11 @@ def find_by(attributes, logic: :AND) TestingRecord.logger.debug("Filtering Entity: '#{self}' list by #{attributes}. Logic: '#{logic}'") if logic == :OR all.select do |entity| - attributes.any? { |key, value| entity.key?(key) && entity.fetch(key) == value } + attributes.any? { |key, value| entity.attributes.key?(key) && entity.attributes.fetch(key) == value } end else all.select do |entity| - attributes.all? { |key, value| entity.fetch(key) == value } + attributes.all? { |key, value| entity.attributes.fetch(key) == value } end end end From ebbdf3e12405e4fad04dc871fffb664140a842ef Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:10:11 +0100 Subject: [PATCH 03/14] Move attr reader for attributes closer to location --- lib/testing_record/model.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/testing_record/model.rb b/lib/testing_record/model.rb index 25fd59b..4c3e780 100644 --- a/lib/testing_record/model.rb +++ b/lib/testing_record/model.rb @@ -11,8 +11,6 @@ class Model extend DSL::Builder::Helpers extend DSL::Builder::Settings - attr_reader :attributes - class << self attr_reader :current @@ -110,6 +108,8 @@ def ensure_primary_key_presence(attributes) end end + attr_reader :attributes + def initialize(attributes = {}) @attributes = attributes end From 80f5493b889a24aeb9ca2a5ad11090623fd808db Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:13:02 +0100 Subject: [PATCH 04/14] Avoid error when finders fail by permitting failures in the query --- lib/testing_record/dsl/builder/filters.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/testing_record/dsl/builder/filters.rb b/lib/testing_record/dsl/builder/filters.rb index 368992d..3103c98 100644 --- a/lib/testing_record/dsl/builder/filters.rb +++ b/lib/testing_record/dsl/builder/filters.rb @@ -22,11 +22,11 @@ def find_by(attributes, logic: :AND) TestingRecord.logger.debug("Filtering Entity: '#{self}' list by #{attributes}. Logic: '#{logic}'") if logic == :OR all.select do |entity| - attributes.any? { |key, value| entity.attributes.key?(key) && entity.attributes.fetch(key) == value } + attributes.any? { |key, value| entity.attributes[key] == value } end else all.select do |entity| - attributes.all? { |key, value| entity.attributes.fetch(key) == value } + attributes.all? { |key, value| entity.attributes[key] == value } end end end From 122753ed0db8614ec96d69e1e36ab159533a0859 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:14:40 +0100 Subject: [PATCH 05/14] Duplicate tests with OR logic --- .../dsl/builder/filters_spec.rb | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/spec/testing_record/dsl/builder/filters_spec.rb b/spec/testing_record/dsl/builder/filters_spec.rb index 9a3624c..ae4590c 100644 --- a/spec/testing_record/dsl/builder/filters_spec.rb +++ b/spec/testing_record/dsl/builder/filters_spec.rb @@ -75,7 +75,7 @@ def self.name end end - describe '.find_by' do + describe '.find_by - AND logic' do let(:foo_entity) { model_klazz.create({ email_address: 'foo@foo.com', foo: 3, other: :foo }) } let(:bar_entity) { model_klazz.create({ email_address: 'bar@bar.com', foo: 3, other: :bar }) } let(:baz_entity) { model_klazz.create({ email_address: 'baz@baz.com', foo: 3, other: :baz }) } @@ -107,6 +107,38 @@ def self.name end end + describe '.find_by - OR logic' do + let(:foo_entity) { model_klazz.create({ email_address: 'foo@foo.com', foo: 3, other: :foo }) } + let(:bar_entity) { model_klazz.create({ email_address: 'bar@bar.com', foo: 3, other: :bar }) } + let(:baz_entity) { model_klazz.create({ email_address: 'baz@baz.com', foo: 3, other: :baz }) } + + before do + foo_entity + bar_entity + baz_entity + end + + context 'with a simple 1 attribute query' do + it 'returns a collection of entities that match the query' do + expect(model_klazz.find_by({ foo: 3 }, logic: :OR)).to eq([foo_entity, bar_entity, baz_entity]) + end + + it 'returns a blank collection when no entities match the query' do + expect(model_klazz.find_by({ foo: 4 }, logic: :OR)).to eq([]) + end + end + + context 'with a more complex set of attributes as a query' do + it 'returns a collection of entities that match all query attributes' do + expect(model_klazz.find_by({ foo: 3, other: :foo, email_address: 'foo@foo.com' }, logic: :OR)).to eq([foo_entity]) + end + + it 'returns a blank collection when no entities match all query attributes' do + expect(model_klazz.find_by({ foo: 3, other: :jeff, email_address: 'foo@foo.com' }, logic: :OR)).to eq([]) + end + end + end + describe '.with_id' do before { model_klazz.primary_key :id } after { model_klazz.primary_key :email_address } From c2ef7934f23994139b23f906aaa8136fb3be280e Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:16:01 +0100 Subject: [PATCH 06/14] Fix up logic and casing to be more optimal; --- lib/testing_record/dsl/builder/filters.rb | 10 +++++----- spec/testing_record/dsl/builder/filters_spec.rb | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/testing_record/dsl/builder/filters.rb b/lib/testing_record/dsl/builder/filters.rb index 3103c98..32af14f 100644 --- a/lib/testing_record/dsl/builder/filters.rb +++ b/lib/testing_record/dsl/builder/filters.rb @@ -15,18 +15,18 @@ def exists?(attributes) # Finds all entities that match specified attribute values # attributes (Hash) -> The attributes you wish to filter on, each is iterated through sequentially - # :logic (Symbol) -> Whether to use `AND` or `OR` logic to combine each sequential key in attributes hash + # :logic (Symbol) -> Whether to use `and` (Intersection), or `or` (Union), logic to combine each key in attributes hash # # @return [Array] - def find_by(attributes, logic: :AND) + def find_by(attributes, logic: :and) TestingRecord.logger.debug("Filtering Entity: '#{self}' list by #{attributes}. Logic: '#{logic}'") - if logic == :OR + if logic == :and all.select do |entity| - attributes.any? { |key, value| entity.attributes[key] == value } + attributes.all? { |key, value| entity.attributes[key] == value } end else all.select do |entity| - attributes.all? { |key, value| entity.attributes[key] == value } + attributes.any? { |key, value| entity.attributes[key] == value } end end end diff --git a/spec/testing_record/dsl/builder/filters_spec.rb b/spec/testing_record/dsl/builder/filters_spec.rb index ae4590c..3ac45a3 100644 --- a/spec/testing_record/dsl/builder/filters_spec.rb +++ b/spec/testing_record/dsl/builder/filters_spec.rb @@ -75,7 +75,7 @@ def self.name end end - describe '.find_by - AND logic' do + describe '.find_by - `:and` logic' do let(:foo_entity) { model_klazz.create({ email_address: 'foo@foo.com', foo: 3, other: :foo }) } let(:bar_entity) { model_klazz.create({ email_address: 'bar@bar.com', foo: 3, other: :bar }) } let(:baz_entity) { model_klazz.create({ email_address: 'baz@baz.com', foo: 3, other: :baz }) } @@ -107,7 +107,7 @@ def self.name end end - describe '.find_by - OR logic' do + describe '.find_by - `:or` logic' do let(:foo_entity) { model_klazz.create({ email_address: 'foo@foo.com', foo: 3, other: :foo }) } let(:bar_entity) { model_klazz.create({ email_address: 'bar@bar.com', foo: 3, other: :bar }) } let(:baz_entity) { model_klazz.create({ email_address: 'baz@baz.com', foo: 3, other: :baz }) } @@ -120,21 +120,21 @@ def self.name context 'with a simple 1 attribute query' do it 'returns a collection of entities that match the query' do - expect(model_klazz.find_by({ foo: 3 }, logic: :OR)).to eq([foo_entity, bar_entity, baz_entity]) + expect(model_klazz.find_by({ foo: 3 }, logic: :or)).to eq([foo_entity, bar_entity, baz_entity]) end it 'returns a blank collection when no entities match the query' do - expect(model_klazz.find_by({ foo: 4 }, logic: :OR)).to eq([]) + expect(model_klazz.find_by({ foo: 4 }, logic: :or)).to eq([]) end end context 'with a more complex set of attributes as a query' do it 'returns a collection of entities that match all query attributes' do - expect(model_klazz.find_by({ foo: 3, other: :foo, email_address: 'foo@foo.com' }, logic: :OR)).to eq([foo_entity]) + expect(model_klazz.find_by({ foo: 3, other: :foo, email_address: 'foo@foo.com' }, logic: :or)).to eq([foo_entity]) end it 'returns a blank collection when no entities match all query attributes' do - expect(model_klazz.find_by({ foo: 3, other: :jeff, email_address: 'foo@foo.com' }, logic: :OR)).to eq([]) + expect(model_klazz.find_by({ foo: 3, other: :jeff, email_address: 'foo@foo.com' }, logic: :or)).to eq([]) end end end From 1f423a64e981c4eceb5d5269893f3d65e7a75e80 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:18:39 +0100 Subject: [PATCH 07/14] Fix up tests for :or logic --- spec/testing_record/dsl/builder/filters_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/testing_record/dsl/builder/filters_spec.rb b/spec/testing_record/dsl/builder/filters_spec.rb index 3ac45a3..72a3b01 100644 --- a/spec/testing_record/dsl/builder/filters_spec.rb +++ b/spec/testing_record/dsl/builder/filters_spec.rb @@ -119,22 +119,22 @@ def self.name end context 'with a simple 1 attribute query' do - it 'returns a collection of entities that match the query' do + it 'returns a collection of entities that match the query - behaving the same as `:and` logic' do expect(model_klazz.find_by({ foo: 3 }, logic: :or)).to eq([foo_entity, bar_entity, baz_entity]) end - it 'returns a blank collection when no entities match the query' do + it 'returns a blank collection when no entities match the query - behaving the same as `:and` logic' do expect(model_klazz.find_by({ foo: 4 }, logic: :or)).to eq([]) end end context 'with a more complex set of attributes as a query' do - it 'returns a collection of entities that match all query attributes' do - expect(model_klazz.find_by({ foo: 3, other: :foo, email_address: 'foo@foo.com' }, logic: :or)).to eq([foo_entity]) + it 'returns a collection of entities that match any of the query attributes' do + expect(model_klazz.find_by({ other: :bar, email_address: 'foo@foo.com' }, logic: :or)).to eq([foo_entity, bar_entity]) end - it 'returns a blank collection when no entities match all query attributes' do - expect(model_klazz.find_by({ foo: 3, other: :jeff, email_address: 'foo@foo.com' }, logic: :or)).to eq([]) + it 'returns a blank collection when no entities match any of the query attributes' do + expect(model_klazz.find_by({ foo: 55, other: :jeff, email_address: 'jeff@foo.com' }, logic: :or)).to eq([]) end end end From ed9661bf54e79f41846a8158d711288e17ec3372 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:20:38 +0100 Subject: [PATCH 08/14] Add changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1f6b30..f0fb84e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ### Removed ### Added +- Added a new conditional piece of logic for filtering. This allows you to filter using "AND" logic or "OR" logic + - Filters using "AND" logic will require all attributes to match the criteria specified in order for an entity to be returned + - Filters using "OR" logic will require at least one attribute to match the criteria specified in order for an entity to be returned + - By default, all filters will use "AND" logic, but you can specify "OR" logic by using the `:logic :or` keyword argument when defining a filter ### Changed - Exposed `.find_by` as a public method for more complex querying of models, and to allow people to write From 4959aebd7ca94b614dd2194fa735977472be79fc Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:25:27 +0100 Subject: [PATCH 09/14] Add new errors and validations for ensuring that this is held true --- lib/testing_record/dsl/builder/filters.rb | 3 +++ lib/testing_record/dsl/builder/settings.rb | 2 +- lib/testing_record/dsl/validation/input.rb | 8 ++++---- lib/testing_record/error.rb | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/testing_record/dsl/builder/filters.rb b/lib/testing_record/dsl/builder/filters.rb index 32af14f..2e91cbd 100644 --- a/lib/testing_record/dsl/builder/filters.rb +++ b/lib/testing_record/dsl/builder/filters.rb @@ -6,6 +6,8 @@ module Builder # [TestingRecord::DSL::Builder::Filters] # Ways in which we can filter our collection to find specific models module Filters + include DSL::Validation::Input + # Checks to see whether an entity exists with the provided attributes # # @return [Boolean] @@ -19,6 +21,7 @@ def exists?(attributes) # # @return [Array] def find_by(attributes, logic: :and) + raise InvalidArgumentError, 'Invalid filtering logic option, must be `:and` or `:or`' unless filter_logic_valid?(logic) TestingRecord.logger.debug("Filtering Entity: '#{self}' list by #{attributes}. Logic: '#{logic}'") if logic == :and all.select do |entity| diff --git a/lib/testing_record/dsl/builder/settings.rb b/lib/testing_record/dsl/builder/settings.rb index 0675f20..0d25084 100644 --- a/lib/testing_record/dsl/builder/settings.rb +++ b/lib/testing_record/dsl/builder/settings.rb @@ -24,7 +24,7 @@ def __primary_key # # @return [Symbol] def caching(option) - raise Error::InvalidConfigurationError, 'Invalid caching option, must be :enabled or :disabled' unless caching_valid?(option) + raise Error::InvalidConfigurationError, 'Invalid caching option, must be `:enabled` or `:disabled`' unless caching_valid?(option) return unless option == :enabled instance_variable_set(:@all, []) diff --git a/lib/testing_record/dsl/validation/input.rb b/lib/testing_record/dsl/validation/input.rb index 4b01a82..27673ed 100644 --- a/lib/testing_record/dsl/validation/input.rb +++ b/lib/testing_record/dsl/validation/input.rb @@ -10,12 +10,12 @@ module Input # # @return [Boolean] def caching_valid?(input) - enabled_or_disabled.include?(input) + %i[enabled disabled].include?(input) end - private - - def enabled_or_disabled = %i[enabled disabled] + def filter_logic_valid?(input) + %i[and or].include?(input) + end end end end diff --git a/lib/testing_record/error.rb b/lib/testing_record/error.rb index 349cdf8..72efe01 100644 --- a/lib/testing_record/error.rb +++ b/lib/testing_record/error.rb @@ -5,5 +5,6 @@ module Error class AttributeError < StandardError; end class EntityError < StandardError; end class InvalidConfigurationError < StandardError; end + class InvalidArgumentError < StandardError; end end end From 46b9c99660764f34fc9e2ce3eef1238843bc1f5b Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:27:49 +0100 Subject: [PATCH 10/14] Fix load error --- CHANGELOG.md | 5 +++-- lib/testing_record/dsl.rb | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0fb84e..9cff4ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,10 @@ ### Removed ### Added -- Added a new conditional piece of logic for filtering. This allows you to filter using "AND" logic or "OR" logic +- Added a new conditional piece of logic for filtering whilst using `#find_by`. This allows you to filter using "AND" logic or "OR" logic - Filters using "AND" logic will require all attributes to match the criteria specified in order for an entity to be returned - Filters using "OR" logic will require at least one attribute to match the criteria specified in order for an entity to be returned - - By default, all filters will use "AND" logic, but you can specify "OR" logic by using the `:logic :or` keyword argument when defining a filter + - By default, all filters will use "AND" logic, but you can specify "OR" logic by using the `:logic :or` keyword argument when defining a filter that uses `#find_by` ### Changed - Exposed `.find_by` as a public method for more complex querying of models, and to allow people to write @@ -16,6 +16,7 @@ their own custom filters on top of this method ruby conventions and to prevent issues with helper generation - `.with_email` filter now supports `email_address`, `email` and `email-address` key names for better flexibility when filtering on email addresses +- Refactored `.find_by` to use more ruby-like methods to improve performance rather than repeated iterations and selections ### Fixed - Hyphenated keys are not permitted for the `primary_key` setting as this will cause issues with ruby diff --git a/lib/testing_record/dsl.rb b/lib/testing_record/dsl.rb index 6279b95..4c99339 100644 --- a/lib/testing_record/dsl.rb +++ b/lib/testing_record/dsl.rb @@ -1,4 +1,6 @@ # frozen_string_literal: true -require_relative 'dsl/builder' +# Must be loaded before builder as some validations are needed during build phase require_relative 'dsl/validation' + +require_relative 'dsl/builder' From 23e321cc76b1369f94a6030c0f0420cc377f1cb4 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:31:29 +0100 Subject: [PATCH 11/14] Fix load order of error and model invocation Tidy up error to be more streamlined --- lib/testing_record/dsl/builder/filters.rb | 2 +- lib/testing_record/model.rb | 1 + spec/testing_record/dsl/builder/filters_spec.rb | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/testing_record/dsl/builder/filters.rb b/lib/testing_record/dsl/builder/filters.rb index 2e91cbd..4e6457f 100644 --- a/lib/testing_record/dsl/builder/filters.rb +++ b/lib/testing_record/dsl/builder/filters.rb @@ -21,7 +21,7 @@ def exists?(attributes) # # @return [Array] def find_by(attributes, logic: :and) - raise InvalidArgumentError, 'Invalid filtering logic option, must be `:and` or `:or`' unless filter_logic_valid?(logic) + raise Error::InvalidArgumentError, 'Invalid filtering logic option, must be `:and` or `:or`' unless filter_logic_valid?(logic) TestingRecord.logger.debug("Filtering Entity: '#{self}' list by #{attributes}. Logic: '#{logic}'") if logic == :and all.select do |entity| diff --git a/lib/testing_record/model.rb b/lib/testing_record/model.rb index 4c3e780..aa7887d 100644 --- a/lib/testing_record/model.rb +++ b/lib/testing_record/model.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'automation_helpers/extensions/string' + require_relative 'dsl' module TestingRecord diff --git a/spec/testing_record/dsl/builder/filters_spec.rb b/spec/testing_record/dsl/builder/filters_spec.rb index 72a3b01..980cc00 100644 --- a/spec/testing_record/dsl/builder/filters_spec.rb +++ b/spec/testing_record/dsl/builder/filters_spec.rb @@ -139,6 +139,16 @@ def self.name end end + describe '.find_by - invalid logic' do + let(:foo_entity) { model_klazz.create({ email_address: 'foo@foo.com', foo: 3, other: :foo }) } + + it 'raises an error that the logic is not valid' do + expect { model_klazz.find_by({ foo: 3 }, logic: :foo) } + .to raise_error(TestingRecord::Error::InvalidArgumentError) + .with_message('Invalid filtering logic option, must be `:and` or `:or`') + end + end + describe '.with_id' do before { model_klazz.primary_key :id } after { model_klazz.primary_key :email_address } From 9ef7c2244e8b1cc7ef7f700e5af93bd5e074cbdc Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:33:14 +0100 Subject: [PATCH 12/14] Add in unit tests for validator --- .../dsl/validation/input_spec.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/spec/testing_record/dsl/validation/input_spec.rb b/spec/testing_record/dsl/validation/input_spec.rb index be93f42..ee5fe08 100644 --- a/spec/testing_record/dsl/validation/input_spec.rb +++ b/spec/testing_record/dsl/validation/input_spec.rb @@ -8,11 +8,11 @@ end describe '.caching_valid?' do - it 'is `true` when the type is enabled' do + it 'is `true` when the type is :enabled' do expect(klazz.caching_valid?(:enabled)).to be true end - it 'is `true` when the type is disabled' do + it 'is `true` when the type is :disabled' do expect(klazz.caching_valid?(:disabled)).to be true end @@ -20,4 +20,18 @@ expect(klazz.caching_valid?(:foo)).to be false end end + + describe '.filter_logic_valid??' do + it 'is `true` when the type is :and' do + expect(klazz.filter_logic_valid?(:and)).to be true + end + + it 'is `true` when the type is :or' do + expect(klazz.filter_logic_valid?(:or)).to be true + end + + it 'is `false` for all other types' do + expect(klazz.filter_logic_valid?(:foo)).to be false + end + end end From 739190705edcf958e084ec8eb61bea91a40f7b61 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:35:08 +0100 Subject: [PATCH 13/14] Add missing test for invalid caching setting proper --- spec/testing_record/model_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/testing_record/model_spec.rb b/spec/testing_record/model_spec.rb index 7a61449..dfe870d 100644 --- a/spec/testing_record/model_spec.rb +++ b/spec/testing_record/model_spec.rb @@ -86,6 +86,14 @@ end end + context 'with an invalid caching setting' do + it 'does not permit the class to be configured with an invalid caching setting' do + expect { FakeModel.caching :foo } + .to raise_error(TestingRecord::Error::InvalidConfigurationError) + .with_message('Invalid caching option, must be `:enabled` or `:disabled`') + end + end + context 'with any hyphenated keys' do before do FakeModel.caching :enabled From 6f7ff4a0a34712004c918050ef6f2d4fb719a195 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Mon, 25 May 2026 12:37:11 +0100 Subject: [PATCH 14/14] Fix rubocop offenses for cyclomatic complexity --- lib/testing_record/dsl/builder/filters.rb | 27 ++++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/testing_record/dsl/builder/filters.rb b/lib/testing_record/dsl/builder/filters.rb index 4e6457f..52c2336 100644 --- a/lib/testing_record/dsl/builder/filters.rb +++ b/lib/testing_record/dsl/builder/filters.rb @@ -22,15 +22,12 @@ def exists?(attributes) # @return [Array] def find_by(attributes, logic: :and) raise Error::InvalidArgumentError, 'Invalid filtering logic option, must be `:and` or `:or`' unless filter_logic_valid?(logic) + TestingRecord.logger.debug("Filtering Entity: '#{self}' list by #{attributes}. Logic: '#{logic}'") if logic == :and - all.select do |entity| - attributes.all? { |key, value| entity.attributes[key] == value } - end + find_by_and(attributes) else - all.select do |entity| - attributes.any? { |key, value| entity.attributes[key] == value } - end + find_by_or(attributes) end end @@ -76,6 +73,24 @@ def with_primary_key?(primary_key) def with_primary_key(primary_key) find_by({ __primary_key => primary_key })&.first&.tap { |entity| entity.class.current = entity } end + + private + + def find_by_and(attributes) + all.select do |entity| + attributes.all? do |key, value| + entity.attributes[key] == value + end + end + end + + def find_by_or(attributes) + all.select do |entity| + attributes.any? do |key, value| + entity.attributes[key] == value + end + end + end end end end