Skip to content

Commit

Permalink
Merge pull request #150 from ifad/bugfix/fix-belongs-to-preload-142
Browse files Browse the repository at this point in the history
Bugfix/fix belongs to preload 142
  • Loading branch information
tagliala authored Mar 22, 2022
2 parents 1212031 + 33bdae7 commit 0a2ae52
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 23 deletions.
31 changes: 19 additions & 12 deletions lib/chrono_model/patches/preloader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ module Patches
# and it is ugly :-(.
#
module Preloader
attr_reader :options
attr_reader :chronomodel_options

# We overwrite the initializer in order to pass the +as_of_time+
# parameter above in the build_preloader
#
def initialize(options = {})
@options = options.freeze
if ActiveRecord::VERSION::STRING >= '7.0'
super(associate_by_default: true, **options)
def initialize(**options)
@chronomodel_options = options.extract!(:as_of_time, :model)
options[:scope] = chronomodel_scope(options[:scope]) if options.key?(:scope)

if options.empty?
super()
else
super **options
end
end

Expand All @@ -40,17 +44,20 @@ def initialize(options = {})
# so we use it directly.
#
def preload(records, associations, given_preload_scope = nil)
if options[:as_of_time]
preload_scope = given_preload_scope ||
ChronoModel::Patches::AsOfTimeRelation.new(options[:model])
super records, associations, chronomodel_scope(given_preload_scope)
end

private

preload_scope.as_of_time!(options[:as_of_time])
elsif given_preload_scope.respond_to?(:as_of_time)
preload_scope = given_preload_scope
def chronomodel_scope(given_preload_scope)
preload_scope = given_preload_scope

if chronomodel_options[:as_of_time]
preload_scope ||= ChronoModel::Patches::AsOfTimeRelation.new(chronomodel_options[:model])
preload_scope.as_of_time!(chronomodel_options[:as_of_time])
end

super records, associations, preload_scope
preload_scope
end

module Association
Expand Down
15 changes: 4 additions & 11 deletions lib/chrono_model/patches/relation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,15 @@ module Relation
include ChronoModel::Patches::AsOfTimeHolder

def preload_associations(records) # :nodoc:
return super if ActiveRecord::VERSION::STRING < '7.0'
return super unless ActiveRecord::Associations::Preloader.instance_methods.include?(:call)

preload = preload_values
preload += includes_values unless eager_loading?
scope = strict_loading_value ? StrictLoadingScope : nil
preload.each do |associations|
if as_of_time
## the tree structure of preloading ensure that children are loaded from history
klass = if associations.is_a? Hash
associations.keys[0].to_s.classify.constantize
else
associations.to_s.classify.constantize
end
scope = klass.as_of(as_of_time) if klass.respond_to?(:as_of)
end
ActiveRecord::Associations::Preloader.new(records: records, associations: associations, scope: scope).call
ActiveRecord::Associations::Preloader.new(
records: records, associations: associations, scope: scope, model: model, as_of_time: as_of_time
).call
end
end

Expand Down
2 changes: 2 additions & 0 deletions spec/chrono_model/time_machine/as_of_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@
it { expect(Foo.as_of($t.foo.ts[1]).includes(:bars).first.bars).to eq [] }
it { expect(Foo.as_of($t.foo.ts[2]).includes(:bars).first.bars).to eq [$t.bar] }

it { expect(Foo.as_of($t.foo.ts[0]).includes(:goo).first).to eq $t.foo }

it { expect(Foo.as_of($t.bar.ts[0]).includes(:bars).first.bars.first.name).to eq 'bar' }
it { expect(Foo.as_of($t.bar.ts[1]).includes(:bars).first.bars.first.name).to eq 'foo bar' }
it { expect(Foo.as_of($t.bar.ts[2]).includes(:bars).first.bars.first.name).to eq 'bar bar' }
Expand Down
13 changes: 13 additions & 0 deletions spec/support/time_machine/structure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,22 @@ module ChronoTest::TimeMachine
adapter.create_table 'foos', :temporal => true do |t|
t.string :name
t.integer :fooity
t.references :goo
end

class ::Foo < ActiveRecord::Base
include ChronoModel::TimeMachine

has_many :bars
has_many :sub_bars, :through => :bars

belongs_to :goo, class_name: 'FooGoo', optional: true
end

class ::FooGoo < ActiveRecord::Base
include ChronoModel::TimeGate

has_many :foos, inverse_of: :goo
end

class ::Boo < ActiveRecord::Base
Expand Down Expand Up @@ -61,6 +70,10 @@ class ::Moo < ActiveRecord::Base
t.references :boo
end

adapter.create_table 'foo_goos' do |t|
t.string :name
end


class ::Bar < ActiveRecord::Base
include ChronoModel::TimeMachine
Expand Down

0 comments on commit 0a2ae52

Please sign in to comment.