Module: TemporalTables::RelationExtensions

Defined in:
lib/temporal_tables/relation_extensions.rb

Overview

Stores the time from the “at” field into each of the resulting objects so that it can be carried forward in subsequent queries.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



5
6
7
8
9
# File 'lib/temporal_tables/relation_extensions.rb', line 5

def self.included(base)
  base.class_eval do
    ActiveRecord::Relation::SINGLE_VALUE_METHODS << :at
  end
end

Instance Method Details

#at(*args) ⇒ Object



19
20
21
# File 'lib/temporal_tables/relation_extensions.rb', line 19

def at(*args)
    spawn.at!(*args)
end

#at!(value) ⇒ Object



23
24
25
26
# File 'lib/temporal_tables/relation_extensions.rb', line 23

def at!(value)
  self.at_value = value
  self
end

#at_valueObject



11
12
13
# File 'lib/temporal_tables/relation_extensions.rb', line 11

def at_value
  get_value(:at) || Thread.current[:at_time]
end

#at_value=(value) ⇒ Object



15
16
17
# File 'lib/temporal_tables/relation_extensions.rb', line 15

def at_value=(value)
  set_value(:at, value)
end

#exec_queriesObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/temporal_tables/relation_extensions.rb', line 67

def exec_queries
  # Note that record preloading, like when you specify
  #  MyClass.includes(:associations)
  # happens within this exec_queries call.  That's why we needed to
  # store the at_time in the thread above.
  threadify_at do
    super
  end

  if historical?
    # Store the at value on each record returned
    @records.each do |r|
      r.at_value = at_value
    end
  end
  @records
end

#historical?Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/temporal_tables/relation_extensions.rb', line 85

def historical?
  table_name =~ /_h$/i && at_value
end

#limited_ids_for(*args) ⇒ Object



61
62
63
64
65
# File 'lib/temporal_tables/relation_extensions.rb', line 61

def limited_ids_for(*args)
  threadify_at do
    super *args
  end
end

#threadify_atObject



50
51
52
53
54
55
56
57
58
59
# File 'lib/temporal_tables/relation_extensions.rb', line 50

def threadify_at
  if at_value && !Thread.current[:at_time]
    Thread.current[:at_time] = at_value
    result = yield
    Thread.current[:at_time] = nil
  else
    result = yield
  end
  result
end

#to_sql(*args) ⇒ Object



44
45
46
47
48
# File 'lib/temporal_tables/relation_extensions.rb', line 44

def to_sql(*args)
  threadify_at do
    super *args
  end
end

#where_clauseObject



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/temporal_tables/relation_extensions.rb', line 28

def where_clause
  s = super

  at_clauses = []
  if historical?
    at_clauses << where_clause_factory.build(
      arel_table[:eff_to].gteq(at_value).and(
        arel_table[:eff_from].lteq(at_value)
      ),
      []
    )
  end

  [s, *at_clauses.compact].sum
end