Class: PaperTrailDiff::PreparedHistory
- Inherits:
-
Object
- Object
- PaperTrailDiff::PreparedHistory
- Defined in:
- lib/paper_trail_diff/prepared_history.rb,
sig/generated/paper_trail_diff/prepared_history.rbs
Overview
Batched record states and relationship candidates for one activity range.
Constant Summary collapse
- DIRECT_RESOLVERS =
{ belongs_to: :resolve_belongs_to, has_one: :resolve_children, has_many: :resolve_children, has_and_belongs_to_many: :resolve_habtm }.freeze
Instance Method Summary collapse
-
#belongs_to_class(record, reflection) ⇒ Object
: (untyped, untyped) -> untyped.
-
#belongs_to_records(record, reflection, boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped) -> Array?.
-
#child_ids_for(group, owner) ⇒ Array[untyped]
: (Hash[Symbol, untyped], untyped) -> Array.
-
#child_records(record, reflection, boundary) ⇒ Array[untyped]
: (untyped, untyped, untyped) -> Array.
-
#default_scoped?(model_class) ⇒ Boolean
: (untyped) -> bool.
-
#direct_records(record, reflection, boundary, habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?.
-
#edge(owner_class, reflection) ⇒ Hash[String, Hash[Symbol, untyped]]
: (untyped, untyped) -> Hash[String, Hash[Symbol, untyped]].
-
#edge_key(owner_class, reflection) ⇒ Array[String]
: (untyped, untyped) -> Array.
-
#habtm_records(record, reflection, boundary, habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?.
-
#initialize(records) ⇒ PreparedHistory
constructor
: (PreparedRecordIndex) -> void.
-
#mark_unsupported(owner_class, reflection) ⇒ void
: (untyped, untyped) -> void.
-
#member_of?(child, reflection, owner) ⇒ Boolean
: (untyped, untyped, untyped) -> bool.
-
#merge_edge(owner_class, reflection, groups) ⇒ void
: (untyped, untyped, Hash[String, Hash[Symbol, untyped]]) -> void.
-
#merge_groups(existing, incoming) ⇒ Hash[String, Hash[Symbol, untyped]]
: (Hash[String, Hash[Symbol, untyped]], Hash[String, Hash[Symbol, untyped]]) -> Hash[String, Hash[Symbol, untyped]].
-
#owner_types(reflection, owner) ⇒ Array[String]
: (untyped, untyped) -> Array.
-
#record_transition(model_class, id, version) ⇒ [ Hash[untyped, untyped], Hash[untyped, untyped] ]?
: (untyped, untyped, untyped) -> [Hash[untyped, untyped], Hash[untyped, untyped]]?.
-
#register_habtm(owner_class, reflection, memberships) ⇒ void
: (untyped, untyped, Hash[String, Array[untyped]]) -> void.
-
#resolve(record, reflection, boundary, habtm_boundary:) ⇒ [ bool, Array[untyped] ]
: (untyped, untyped, untyped, habtm_boundary: untyped) -> [bool, Array[untyped]].
-
#resolve_belongs_to(record, reflection, boundary, _habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?.
-
#resolve_children(record, reflection, boundary, _habtm_boundary) ⇒ Array[untyped]
: (untyped, untyped, untyped, untyped) -> Array.
-
#resolve_habtm(record, reflection, boundary, habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?.
-
#resolve_sources(intermediates, reflection, boundary, habtm_boundary) ⇒ Array[[ bool, Array[untyped] ]]
: (Array, untyped, untyped, untyped) -> Array[[bool, Array[untyped]]].
-
#scalar_foreign_key(reflection) ⇒ String?
: (untyped) -> String?.
-
#supported?(owner_class, reflection) ⇒ Boolean
: (untyped, untyped) -> bool.
-
#through_records(record, reflection, boundary, habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?.
-
#transaction_id_for(boundary) ⇒ Object
: (untyped) -> untyped.
- #unique_records(records) ⇒ Array[untyped]
Constructor Details
#initialize(records) ⇒ PreparedHistory
: (PreparedRecordIndex) -> void
16 17 18 19 20 21 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 16 def initialize(records) @records = records @edges = {} #: Hash[Array[String], Hash[String, Hash[Symbol, untyped]]] @unsupported = {} #: Hash[Array[String], bool] @habtm = {} #: Hash[Array[String], Hash[String, Array[untyped]]] end |
Instance Method Details
#belongs_to_class(record, reflection) ⇒ Object
: (untyped, untyped) -> untyped
193 194 195 196 197 198 199 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 193 def belongs_to_class(record, reflection) return reflection.klass unless reflection.polymorphic? Object.const_get(record.public_send(reflection.foreign_type).to_s) rescue NameError nil end |
#belongs_to_records(record, reflection, boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped) -> Array?
103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 103 def belongs_to_records(record, reflection, boundary) foreign_key = scalar_foreign_key(reflection) return unless foreign_key id = record.public_send(foreign_key) return [] if id.nil? model_class = belongs_to_class(record, reflection) return unless model_class && @records.loaded?(model_class, id) Array(@records.record_before(model_class, id, boundary)).compact end |
#child_ids_for(group, owner) ⇒ Array[untyped]
: (Hash[Symbol, untyped], untyped) -> Array
128 129 130 131 132 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 128 def child_ids_for(group, owner) owners = group[:owners] empty = [] #: Array[untyped] owners ? owners.fetch(owner.id.to_s, empty) : group.fetch(:ids) end |
#child_records(record, reflection, boundary) ⇒ Array[untyped]
: (untyped, untyped, untyped) -> Array
117 118 119 120 121 122 123 124 125 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 117 def child_records(record, reflection, boundary) edge(record.class, reflection).values.flat_map do |group| model_class = group.fetch(:model) child_ids_for(group, record).filter_map do |id| child = @records.record_before(model_class, id, boundary) child if child && member_of?(child, reflection, record) end end end |
#default_scoped?(model_class) ⇒ Boolean
: (untyped) -> bool
77 78 79 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 77 def default_scoped?(model_class) model_class.default_scopes? end |
#direct_records(record, reflection, boundary, habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?
82 83 84 85 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 82 def direct_records(record, reflection, boundary, habtm_boundary) resolver = DIRECT_RESOLVERS.fetch(reflection.macro) send(resolver, record, reflection, boundary, habtm_boundary) end |
#edge(owner_class, reflection) ⇒ Hash[String, Hash[Symbol, untyped]]
: (untyped, untyped) -> Hash[String, Hash[Symbol, untyped]]
31 32 33 34 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 31 def edge(owner_class, reflection) empty = {} #: Hash[String, Hash[Symbol, untyped]] @edges.fetch(edge_key(owner_class, reflection), empty) end |
#edge_key(owner_class, reflection) ⇒ Array[String]
: (untyped, untyped) -> Array
218 219 220 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 218 def edge_key(owner_class, reflection) [owner_class.base_class.name.to_s, reflection.name.to_s] end |
#habtm_records(record, reflection, boundary, habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?
135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 135 def habtm_records(record, reflection, boundary, habtm_boundary) transaction_id = transaction_id_for(habtm_boundary) return unless transaction_id empty = {} #: Hash[String, Array[untyped]] ids = @habtm.fetch(edge_key(record.class, reflection), empty)[transaction_id.to_s] return unless ids ids.filter_map do |id| @records.record_before(reflection.klass, id, boundary) end end |
#mark_unsupported(owner_class, reflection) ⇒ void
This method returns an undefined value.
: (untyped, untyped) -> void
37 38 39 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 37 def mark_unsupported(owner_class, reflection) @unsupported[edge_key(owner_class, reflection)] = true end |
#member_of?(child, reflection, owner) ⇒ Boolean
: (untyped, untyped, untyped) -> bool
177 178 179 180 181 182 183 184 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 177 def member_of?(child, reflection, owner) foreign_key = scalar_foreign_key(reflection) return false unless foreign_key return false unless child.public_send(foreign_key).to_s == owner.id.to_s return true unless reflection.[:as] owner_types(reflection, owner).include?(child.public_send(reflection.type).to_s) end |
#merge_edge(owner_class, reflection, groups) ⇒ void
This method returns an undefined value.
: (untyped, untyped, Hash[String, Hash[Symbol, untyped]]) -> void
24 25 26 27 28 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 24 def merge_edge(owner_class, reflection, groups) key = edge_key(owner_class, reflection) empty = {} #: Hash[String, Hash[Symbol, untyped]] @edges[key] = merge_groups(@edges.fetch(key, empty), groups) end |
#merge_groups(existing, incoming) ⇒ Hash[String, Hash[Symbol, untyped]]
: (Hash[String, Hash[Symbol, untyped]], Hash[String, Hash[Symbol, untyped]]) -> Hash[String, Hash[Symbol, untyped]]
223 224 225 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 223 def merge_groups(existing, incoming) Support.merge_record_groups(existing, incoming) end |
#owner_types(reflection, owner) ⇒ Array[String]
: (untyped, untyped) -> Array
202 203 204 205 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 202 def owner_types(reflection, owner) types = [owner.class.name, owner.class.base_class.name, reflection.active_record.name] types.map(&:to_s).uniq end |
#record_transition(model_class, id, version) ⇒ [ Hash[untyped, untyped], Hash[untyped, untyped] ]?
: (untyped, untyped, untyped) -> [Hash[untyped, untyped], Hash[untyped, untyped]]?
47 48 49 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 47 def record_transition(model_class, id, version) @records.transition(model_class, id, version) end |
#register_habtm(owner_class, reflection, memberships) ⇒ void
This method returns an undefined value.
: (untyped, untyped, Hash[String, Array[untyped]]) -> void
42 43 44 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 42 def register_habtm(owner_class, reflection, memberships) @habtm[edge_key(owner_class, reflection)] = memberships.transform_keys(&:to_s) end |
#resolve(record, reflection, boundary, habtm_boundary:) ⇒ [ bool, Array[untyped] ]
: (untyped, untyped, untyped, habtm_boundary: untyped) -> [bool, Array[untyped]]
52 53 54 55 56 57 58 59 60 61 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 52 def resolve(record, reflection, boundary, habtm_boundary:) return [false, []] unless supported?(record.class, reflection) records = if reflection.[:through] through_records(record, reflection, boundary, habtm_boundary) else direct_records(record, reflection, boundary, habtm_boundary) end records ? [true, records] : [false, []] end |
#resolve_belongs_to(record, reflection, boundary, _habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?
88 89 90 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 88 def resolve_belongs_to(record, reflection, boundary, _habtm_boundary) belongs_to_records(record, reflection, boundary) end |
#resolve_children(record, reflection, boundary, _habtm_boundary) ⇒ Array[untyped]
: (untyped, untyped, untyped, untyped) -> Array
93 94 95 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 93 def resolve_children(record, reflection, boundary, _habtm_boundary) child_records(record, reflection, boundary) end |
#resolve_habtm(record, reflection, boundary, habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?
98 99 100 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 98 def resolve_habtm(record, reflection, boundary, habtm_boundary) habtm_records(record, reflection, boundary, habtm_boundary) end |
#resolve_sources(intermediates, reflection, boundary, habtm_boundary) ⇒ Array[[ bool, Array[untyped] ]]
: (Array, untyped, untyped, untyped) -> Array[[bool, Array[untyped]]]
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 165 def resolve_sources(intermediates, reflection, boundary, habtm_boundary) intermediates.map do |intermediate| resolve( intermediate, reflection.source_reflection, boundary, habtm_boundary: habtm_boundary ) end end |
#scalar_foreign_key(reflection) ⇒ String?
: (untyped) -> String?
187 188 189 190 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 187 def scalar_foreign_key(reflection) key = reflection.foreign_key key.to_s unless key.is_a?(Array) end |
#supported?(owner_class, reflection) ⇒ Boolean
: (untyped, untyped) -> bool
71 72 73 74 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 71 def supported?(owner_class, reflection) !@unsupported[edge_key(owner_class, reflection)] && reflection.scope.nil? && !default_scoped?(reflection.klass) end |
#through_records(record, reflection, boundary, habtm_boundary) ⇒ Array[untyped]?
: (untyped, untyped, untyped, untyped) -> Array?
149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 149 def through_records(record, reflection, boundary, habtm_boundary) handled, intermediates = resolve( record, reflection.through_reflection, boundary, habtm_boundary: habtm_boundary ) return unless handled resolved = resolve_sources(intermediates, reflection, boundary, habtm_boundary) return unless resolved.all?(&:first) unique_records(resolved.flat_map(&:last)) end |
#transaction_id_for(boundary) ⇒ Object
: (untyped) -> untyped
208 209 210 |
# File 'lib/paper_trail_diff/prepared_history.rb', line 208 def transaction_id_for(boundary) boundary.transaction_id end |