Class: PaperTrailDiff::ActivityVersionCollector
- Inherits:
-
Object
- Object
- PaperTrailDiff::ActivityVersionCollector
- Defined in:
- lib/paper_trail_diff/activity_version_collector.rb,
sig/generated/paper_trail_diff/activity_version_collector.rbs
Overview
Collects root and selected-descendant versions relevant to one root history range.
Instance Method Summary collapse
-
#belongs_to_groups(parent_class, parent_versions, reflection) ⇒ Hash[String, untyped]
: (untyped, Array, untyped) -> Hash[String, untyped].
-
#call ⇒ Array[ActivityEvent]
: () -> Array.
-
#collect_reflection(parent, reflection, subtree, path, branch) ⇒ void
: (Hash[Symbol, untyped], untyped, AssociationTree, String, String) -> void.
-
#collect_tree(parent_class, parent_ids, tree, path:, branch:) ⇒ void
: (untyped, Array, AssociationTree, path: String, branch: String?) -> void.
-
#direct_child_groups(parent_class, parent_ids, reflection) ⇒ Hash[String, untyped]
: (untyped, Array, untyped) -> Hash[String, untyped].
-
#edge_groups(parent, reflection, branch) ⇒ Hash[String, untyped]
: (Hash[Symbol, untyped], untyped, String) -> Hash[String, untyped].
-
#group(model_class, ids) ⇒ Hash[Symbol, untyped]
: (untyped, Array) -> Hash[Symbol, untyped].
-
#habtm_groups(parent_class, parent_versions, reflection) ⇒ Hash[String, untyped]
: (untyped, Array, untyped) -> Hash[String, untyped].
-
#identity_groups(rows, reflection) ⇒ Hash[String, untyped]
: (Array, untyped) -> Hash[String, untyped].
-
#in_range?(version) ⇒ Boolean
: (untyped) -> bool.
-
#initialize(record, root_versions:, tree:, traversal:, range_start: root_versions.first, range_end: root_versions.last) ⇒ ActivityVersionCollector
constructor
: (untyped, root_versions: Array, tree: AssociationTree, traversal: AssociationTraversal, ?range_start: untyped, ?range_end: untyped) -> void.
-
#join_path(parent, name) ⇒ String
: (String, String) -> String.
-
#merge_groups!(destination, source) ⇒ void
: (Hash[String, untyped], Hash[String, untyped]) -> void.
-
#target_class(reflection, row) ⇒ Object
: (untyped, untyped) -> untyped.
-
#through_groups(parent, reflection, branch) ⇒ Hash[String, untyped]
: (Hash[Symbol, untyped], untyped, String) -> Hash[String, untyped].
- #versions_for(model_class, ids) ⇒ Array[untyped]
Constructor Details
#initialize(record, root_versions:, tree:, traversal:, range_start: root_versions.first, range_end: root_versions.last) ⇒ ActivityVersionCollector
: (untyped, root_versions: Array, tree: AssociationTree, traversal: AssociationTraversal, ?range_start: untyped, ?range_end: untyped) -> void
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 8 def initialize( # rubocop:disable Metrics/ParameterLists record, root_versions:, tree:, traversal:, range_start: root_versions.first, range_end: root_versions.last ) @record = record @root_versions = root_versions @tree = tree @traversal = traversal @range = ActivityRange.new(range_start, range_end) @registry = ActivityEventRegistry.new end |
Instance Method Details
#belongs_to_groups(parent_class, parent_versions, reflection) ⇒ Hash[String, untyped]
: (untyped, Array, untyped) -> Hash[String, untyped]
99 100 101 102 103 104 105 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 99 def belongs_to_groups(parent_class, parent_versions, reflection) rows = parent_class.paper_trail.version_association_class.where( version_id: parent_versions.map(&:id), foreign_key_name: reflection.foreign_key.to_s ).to_a identity_groups(rows, reflection) end |
#call ⇒ Array[ActivityEvent]
: () -> Array
25 26 27 28 29 30 31 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 25 def call @registry.add(@root_versions) collect_tree(@record.class, [@record.id], @tree, path: '', branch: nil) unless @tree.empty? @registry.to_a.sort_by do |event| Support.chronological_version_key(event.version) end.freeze end |
#collect_reflection(parent, reflection, subtree, path, branch) ⇒ void
This method returns an undefined value.
: (Hash[Symbol, untyped], untyped, AssociationTree, String, String) -> void
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 56 def collect_reflection(parent, reflection, subtree, path, branch) groups = edge_groups(parent, reflection, branch) groups.each_value do |group| @registry.add(group.fetch(:versions), branch: branch) next if subtree.empty? child_path = join_path(path, reflection.name.to_s) collect_tree(group.fetch(:model), group.fetch(:ids), subtree, path: child_path, branch: branch) end end |
#collect_tree(parent_class, parent_ids, tree, path:, branch:) ⇒ void
This method returns an undefined value.
: (untyped, Array, AssociationTree, path: String, branch: String?) -> void
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 43 def collect_tree(parent_class, parent_ids, tree, path:, branch:) parent = group(parent_class, parent_ids) @registry.add(parent.fetch(:versions), branch: branch) unless path.empty? @traversal.reflections_for(parent_class, tree, path: path).each do |reflection| subtree = tree.child(reflection.name) next unless subtree selected_branch = branch || reflection.name.to_s collect_reflection(parent, reflection, subtree, path, selected_branch) end end |
#direct_child_groups(parent_class, parent_ids, reflection) ⇒ Hash[String, untyped]
: (untyped, Array, untyped) -> Hash[String, untyped]
108 109 110 111 112 113 114 115 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 108 def direct_child_groups(parent_class, parent_ids, reflection) item_ids = ActivityChildCandidateLoader.new( parent_class, parent_ids, reflection, @range ).call return {} if item_ids.empty? { reflection.klass.name => group(reflection.klass, item_ids) } end |
#edge_groups(parent, reflection, branch) ⇒ Hash[String, untyped]
: (Hash[Symbol, untyped], untyped, String) -> Hash[String, untyped]
69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 69 def edge_groups(parent, reflection, branch) return through_groups(parent, reflection, branch) if reflection.[:through] case reflection.macro when :belongs_to belongs_to_groups(parent.fetch(:model), parent.fetch(:versions), reflection) when :has_one, :has_many direct_child_groups(parent.fetch(:model), parent.fetch(:ids), reflection) when :has_and_belongs_to_many habtm_groups(parent.fetch(:model), parent.fetch(:versions), reflection) else {} end end |
#group(model_class, ids) ⇒ Hash[Symbol, untyped]
: (untyped, Array) -> Hash[Symbol, untyped]
143 144 145 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 143 def group(model_class, ids) { model: model_class, ids: ids, versions: versions_for(model_class, ids) } end |
#habtm_groups(parent_class, parent_versions, reflection) ⇒ Hash[String, untyped]
: (untyped, Array, untyped) -> Hash[String, untyped]
118 119 120 121 122 123 124 125 126 127 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 118 def habtm_groups(parent_class, parent_versions, reflection) transaction_ids = parent_versions.filter_map do |version| version.transaction_id if version.respond_to?(:transaction_id) end rows = parent_class.paper_trail.version_association_class.where( version_id: transaction_ids, foreign_key_name: reflection.name.to_s ).to_a identity_groups(rows, reflection) end |
#identity_groups(rows, reflection) ⇒ Hash[String, untyped]
: (Array, untyped) -> Hash[String, untyped]
130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 130 def identity_groups(rows, reflection) identities = rows.group_by { |row| target_class(reflection, row) } groups = {} #: Hash[String, untyped] identities.each do |model_class, class_rows| next unless model_class ids = class_rows.map(&:foreign_key_id).compact.uniq groups[model_class.name] = group(model_class, ids) end groups end |
#in_range?(version) ⇒ Boolean
: (untyped) -> bool
184 185 186 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 184 def in_range?(version) @range.include?(version) end |
#join_path(parent, name) ⇒ String
: (String, String) -> String
189 190 191 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 189 def join_path(parent, name) parent.empty? ? name : "#{parent}.#{name}" end |
#merge_groups!(destination, source) ⇒ void
This method returns an undefined value.
: (Hash[String, untyped], Hash[String, untyped]) -> void
148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 148 def merge_groups!(destination, source) source.each do |name, incoming| existing = destination[name] unless existing destination[name] = incoming next end ids = (existing.fetch(:ids) | incoming.fetch(:ids)) destination[name] = group(existing.fetch(:model), ids) end end |
#target_class(reflection, row) ⇒ Object
: (untyped, untyped) -> untyped
175 176 177 178 179 180 181 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 175 def target_class(reflection, row) return reflection.klass unless reflection.polymorphic? Object.const_get(row.foreign_type.to_s) unless row.foreign_type.to_s.empty? rescue NameError nil end |
#through_groups(parent, reflection, branch) ⇒ Hash[String, untyped]
: (Hash[Symbol, untyped], untyped, String) -> Hash[String, untyped]
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 85 def through_groups(parent, reflection, branch) through = reflection.through_reflection intermediate = edge_groups(parent, through, branch) result = {} #: Hash[String, untyped] intermediate.each_value do |group| @registry.add(group.fetch(:versions), branch: branch) source = reflection.source_reflection children = edge_groups(group, source, branch) merge_groups!(result, children) end result end |
#versions_for(model_class, ids) ⇒ Array[untyped]
162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/paper_trail_diff/activity_version_collector.rb', line 162 def versions_for(model_class, ids) return [] if ids.empty? version_class = model_class.paper_trail.version_class @range.scope( version_class.where( item_type: model_class.base_class.name, item_id: ids ) ).to_a.select { |version| in_range?(version) } end |