hyperstack-org/hyperstack

relationship/collection .first transfers entire scope to client

Open

#296 opened on Mar 1, 2020

View on GitHub
 (0 comments) (0 reactions) (0 assignees)JavaScript (531 stars) (43 forks)batch import
buggood first issue

Description

SomeModelWithLotsOfData.first will transfer the entire table to the client then select the first item.

This patch appears to fix, and can be added as is to your ApplicationRecord file at the start.

module ReactiveRecord
  class Collection

   # THIS IS THE KEY PART OF THE PATCH... DO THE SAME THING AS last FOR first
    def first(n = nil)
      if n
        apply_scope(:__hyperstack_internal_scoped_first_n, n)
      else
        __hyperstack_internal_scoped_first
      end
    end
  end

    def method_missing(method, *args, &block)
      if args.count == 1 && method.start_with?('find_by_')
        find_by(method.sub(/^find_by_/, '') => args[0])
      elsif [].respond_to? method
        all.send(method, *args, &block)
      elsif ScopeDescription.find(@target_klass, method)
        apply_scope(method, *args)
      elsif @target_klass.respond_to?(method) && ScopeDescription.find(@target_klass, "_#{method}")
       # .first was being used here.  change to [0] so we don't get into infinite recursion
        apply_scope("_#{method}", *args)[0]
      else
        super
      end
    end
end if RUBY_ENGINE == 'opal'

module ActiveRecord
  class Base
    # define the scope and finder method used by the first method above

    finder_method :__hyperstack_internal_scoped_first do
      first
    end

    scope :__hyperstack_internal_scoped_first_n, ->(n) { first(n) }

    # this method was using collection.first rather than collection[0]

    def self.__hyperstack_internal_scoped_find_by(attrs)
      collection = all.apply_scope(:___hyperstack_internal_scoped_find_by, attrs)
      if !collection.collection
        collection._find_by_initializer(self, attrs)
      else
        # use collection[0] rather than collection.first to avoid infinite recursion
        collection[0]
      end
    end
  end unless Base.respond_to? :__hyperstack_internal_scoped_first_n # only needed for the patch
end

Test case might be interesting to create....

Contributor guide