Skip to content

Add n1_bind_to and automatic context sharing without ActiveRecord - #50

Merged
djezzzl merged 5 commits into
masterfrom
copilot/add-n1-loader-support
Mar 7, 2026
Merged

Add n1_bind_to and automatic context sharing without ActiveRecord#50
djezzzl merged 5 commits into
masterfrom
copilot/add-n1-loader-support

Conversation

Copilot AI commented Mar 1, 2026

Copy link
Copy Markdown
Contributor
  • Add n1_bind_to instance method on Loadable
  • Update n1_loader_reload to use bound collection and propagate LoaderCollection
  • Automatically call n1_bind_to(elements) on loadable elements inside Loader before perform
  • Add specs for automatic context binding
  • Suppress rubocop offenses with inline # rubocop:disable comments (no structural refactoring)
  • Update CHANGELOG with [Unreleased] section and credit to @paneq for the feature request
  • All 35 examples pass, 0 rubocop offenses
Original prompt

This section details on the original issue you should resolve

<issue_title>Using n1_loader without ActiveRecord [feature request]</issue_title>
<issue_description>Hey @djezzzl, long time no see :)

I was wondering if there would be a way to use this gem in classes that don't inherit from ActiveRecord.
Imagine this simplified case.

class User < Struct.new(:id)
  include N1Loader::Loadable

  n1_optimized :payments_total do |users|
    total_per_user = 
      Payment.group(:user_id)
        .where(user_id: users.map(&:id))
        .sum(:amount)
        .tap { |h| h.default = 0 }

    users.each do |user|
      total = total_per_user[user.id]
      fulfill(user, total)
    end
  end

  def self.find(ids)
    users = ids.map{|id| User.new(id) }
    # missing magic here
    return users
  end
end

User.find([1,2,3]).map(&:payments_total) # should be 1 query :) 

It's probably somehow possible, but we would need to have some Context tracking that would allow us to connect that those three user objects come from the same context. I don't have an idea how though. Any pointers welcomed.</issue_description>

Comments on the Issue (you are @copilot in this section)

@djezzzl Hi @paneq,

Long time no see indeed! I hope you are having a great time!

I think the gem could provide some capabilities. It doesn't need much in its core to make it work.

I would say something like below would be enough (on your example):

def self.find(ids)
  users = ids.map{|id| User.new(id) }
  users.each { |user| user.n1_bind_to(users) }

  return users
end

And then a little bit adjust core to consider the context if it's there. We can make it modular if needed. </comment_new>


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for n1_loader without ActiveRecord Add n1_bind_to for context sharing without ActiveRecord Mar 1, 2026

@djezzzl djezzzl left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot make nested loading automatically setting the shared context if available. Cover with specs. What I mean is everything that is loaded through N1Loader should automatically under the hood set the context.

Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>

Copilot AI commented Mar 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot make nested loading automatically setting the shared context if available. Cover with specs. What I mean is everything that is loaded through N1Loader should automatically under the hood set ...

Done in commit 6999610. In Loader#non_thread_safe_loaded, before calling perform(elements), each element that responds to n1_bind_to now automatically gets n1_bind_to(elements) called. This means any subsequent n1_optimized field access on those elements will transparently share the batch context without any manual setup. Three specs cover: batch loading in one perform call, sibling cache reuse, and correct single-element behavior.

Copilot AI changed the title Add n1_bind_to for context sharing without ActiveRecord Add n1_bind_to and automatic context sharing without ActiveRecord Mar 1, 2026
@djezzzl

djezzzl commented Mar 5, 2026

Copy link
Copy Markdown
Owner

@copilot fix rubocop, update changelog with unreleased and thanks to original issue owner.

Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>

Copilot AI commented Mar 5, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix rubocop, update changelog with unreleased and thanks to original issue owner.

Done in commit f130db7.

  • Rubocop: Extracted perform_loading and bind_elements_context private methods to resolve Metrics/AbcSize/Metrics/MethodLength on non_thread_safe_loaded; parenthesized change block args in specs to fix Lint/AmbiguousBlockAssociation.
  • CHANGELOG: Added [Unreleased] section with thanks to @paneq for the feature request.

@djezzzl djezzzl left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot revert last commit with rubocop fixes and instead simply explicitly ignore rubocop issues.

Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>

Copilot AI commented Mar 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot revert last commit with rubocop fixes and instead simply explicitly ignore rubocop issues.

Done in commit 488edbd. Reverted the extracted helper methods and instead added inline # rubocop:disable comments on the offending lines in loader.rb and the spec.

@djezzzl
djezzzl marked this pull request as ready for review March 7, 2026 06:57
@djezzzl
djezzzl merged commit 6495daf into master Mar 7, 2026
7 checks passed
@djezzzl
djezzzl deleted the copilot/add-n1-loader-support branch March 7, 2026 06:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using n1_loader without ActiveRecord [feature request]

2 participants