Skip to content

Commit

Permalink
Feature skip_preload (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
Davinderx committed Jul 21, 2020
1 parent 58d27a4 commit 9d711e5
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,8 @@

## master

- [PR [#33](https://github.com/DmitryTsepelev/ar_lazy_preload/pull/34)] Feature skip_preload, allow turn automatic preload off ([@OuYangJinTing][])

## 0.3.1 (2020-07-10)

- [PR [#33](https://github.com/DmitryTsepelev/ar_lazy_preload/pull/33)] Don't do merge if there is nothing to merge ([@Earendil95][])
Expand Down
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -44,6 +44,12 @@ ArLazyPreload.config.auto_preload = true

After that there is no need to call `#lazy_preload` on the association, everything would be loaded lazily.

If you want to turn automatic preload off for a specific record, you can call `.skip_preload` before any associations method:

```ruby
users.first.skip_preload.posts # => SELECT * FROM posts WHERE user_id = ?
```

## Installation

Add this line to your application's Gemfile, and you're all set:
Expand Down
6 changes: 6 additions & 0 deletions lib/ar_lazy_preload/active_record/base.rb
Expand Up @@ -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
4 changes: 2 additions & 2 deletions lib/ar_lazy_preload/active_record/collection_association.rb
Expand Up @@ -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?

Expand All @@ -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
8 changes: 7 additions & 1 deletion spec/ar_lazy_preload/active_record/base_spec.rb
Expand Up @@ -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
45 changes: 45 additions & 0 deletions spec/ar_lazy_preload/skip_preload_spec.rb
@@ -0,0 +1,45 @@
# 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
id_concat = subject[0..-2].map(&:id).join(", ")
question_concat = (["?"] * (subject.size - 1)).join(", ")
expect do
subject.first.posts.to_a
end.to make_database_queries(
matching: /\"user_id\" IN ([(#{id_concat})|(#{question_concat})])/
)
end
end
end

0 comments on commit 9d711e5

Please sign in to comment.