diff --git a/lib/ar_lazy_preload/active_record/base.rb b/lib/ar_lazy_preload/active_record/base.rb index 51888fd..09a0d8b 100644 --- a/lib/ar_lazy_preload/active_record/base.rb +++ b/lib/ar_lazy_preload/active_record/base.rb @@ -10,5 +10,11 @@ def self.included(base) attr_accessor :lazy_preload_context delegate :try_preload_lazily, to: :lazy_preload_context, allow_nil: true + + def skip_preload + lazy_preload_context&.records&.delete(self) + self.lazy_preload_context = nil + self + end end end diff --git a/lib/ar_lazy_preload/active_record/collection_association.rb b/lib/ar_lazy_preload/active_record/collection_association.rb index 37a5814..1e89c29 100644 --- a/lib/ar_lazy_preload/active_record/collection_association.rb +++ b/lib/ar_lazy_preload/active_record/collection_association.rb @@ -3,7 +3,7 @@ module ArLazyPreload # ActiveRecord::CollectionAssociation patch with a hook for lazy preloading module CollectionAssociation - # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity def ids_reader return super if owner.lazy_preload_context.blank? @@ -16,6 +16,6 @@ def ids_reader @association_ids ||= reader.map(&primary_key) end end - # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity end end diff --git a/spec/ar_lazy_preload/active_record/base_spec.rb b/spec/ar_lazy_preload/active_record/base_spec.rb index bf8e945..14d4a64 100644 --- a/spec/ar_lazy_preload/active_record/base_spec.rb +++ b/spec/ar_lazy_preload/active_record/base_spec.rb @@ -3,9 +3,15 @@ require "spec_helper" describe ArLazyPreload::Base do - describe "lazy_preload" do + describe "#lazy_preload" do subject { ActiveRecord::Base } it { is_expected.to respond_to(:lazy_preload) } end + + describe "#skip_preload" do + subject { User.new } + + it { is_expected.to respond_to(:skip_preload) } + end end diff --git a/spec/ar_lazy_preload/skip_preload_spec.rb b/spec/ar_lazy_preload/skip_preload_spec.rb new file mode 100644 index 0000000..8137be0 --- /dev/null +++ b/spec/ar_lazy_preload/skip_preload_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "ArLazyPreload.skip_preload" do + let!(:user1) { create(:user) } + let!(:user2) { create(:user) } + let!(:user3) { create(:user) } + + let!(:post1) { create(:post, user: user1) } + let!(:post2) { create(:post, user: user1) } + let!(:post3) { create(:post, user: user2) } + + before(:each) { ArLazyPreload.config.auto_preload = true } + + describe "#skip_preload" do + subject { User.all } + + it "after skip preload, changed lazy preload context" do + subject.load.last.skip_preload + expect(subject.last.lazy_preload_context).to be(nil) + expect(subject.first.lazy_preload_context.records).not_to include(subject.last) + end + + it "only load own association" do + subject.each do |user| + # SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = ? + expect do + user.skip_preload.posts.load + end.to make_database_queries(matching: "\"posts\".\"user_id\" = ?") + end + end + + it "loads excluded association" do + subject.load.last.skip_preload.posts.to_a + expect do + subject.first.posts.to_a + end.to make_database_queries( + matching: "\"user_id\" IN (#{subject[0..-2].map(&:id).join(', ')})" + ) + end + end +end