Module: Trees

Included in:
Classification, DigitalObject, Resource
Defined in:
backend/app/model/mixins/trees.rb

Defined Under Namespace

Modules: ClassMethods

Constant Summary

NODE_PAGE_SIZE =
2000

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Object) included(base)



5
6
7
# File 'backend/app/model/mixins/trees.rb', line 5

def self.included(base)
  base.extend(ClassMethods)
end

Instance Method Details

- (Object) adopt_children(old_parent)



10
11
12
13
14
15
16
# File 'backend/app/model/mixins/trees.rb', line 10

def adopt_children(old_parent)
  self.class.node_model.
       this_repo.filter(:root_record_id => old_parent.id,
                        :parent_id => nil).order(:position).each do |root_child|
                          root_child.set_root(self)
                        end
end

- (Object) assimilate(victims)



19
20
21
22
23
24
25
26
27
# File 'backend/app/model/mixins/trees.rb', line 19

def assimilate(victims)
  victims.each do |victim|
    adopt_children(victim)
  end

  Event.for_archival_record_merge(self, victims)

  super
end

- (Object) build_node_query



37
38
39
# File 'backend/app/model/mixins/trees.rb', line 37

def build_node_query
  self.class.node_model.this_repo.filter(:root_record_id => self.id)
end

- (Object) children



30
31
32
33
34
# File 'backend/app/model/mixins/trees.rb', line 30

def children
  self.class.node_model.
         this_repo.filter(:root_record_id => self.id,
                          :parent_id => nil)
end

- (Object) load_node_properties(node, properties, ids_of_interest = :all)



42
43
44
45
# File 'backend/app/model/mixins/trees.rb', line 42

def load_node_properties(node, properties, ids_of_interest = :all)
  # Does nothing by default, but classes that use this mixin add their own
  # behaviour here.
end

- (Object) load_root_properties(properties, ids_of_interest = :all)



48
49
50
51
# File 'backend/app/model/mixins/trees.rb', line 48

def load_root_properties(properties, ids_of_interest = :all)
  # Does nothing by default, but classes that use this mixin add their own
  # behaviour here.
end

- (Object) partial_tree(node_of_interest)

A tree that only contains nodes that are needed for displaying ‘node’

That is: any ancestors of ‘node’, plus the direct children of any ancestor



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'backend/app/model/mixins/trees.rb', line 57

def partial_tree(node_of_interest)
  ids_of_interest = []
  nodes_to_check = [node_of_interest]

  while !nodes_to_check.empty?
    node = nodes_to_check.pop

    # Include the node itself
    ids_of_interest << node.id if node != :root

    # Plus any of its siblings in this tree
    self.class.node_model.
         filter(:parent_id => (node == :root) ? nil : node.parent_id,
                :root_record_id => self.id).
         select(:id).all.each do |row|
      ids_of_interest << row[:id]
    end

    if node != :root && node.parent_id
      parent = self.class.node_model[node.parent_id]
      nodes_to_check << parent
    end
  end


  # Include the children of the node of interest too
  if node_of_interest != :root
    self.class.node_model.
         filter(:parent_id => node_of_interest.id,
                :root_record_id => self.id).
         select(:id).all.each do |row|
      ids_of_interest << row[:id]
    end
  end


  tree(ids_of_interest)
end

- (Object) transfer_to_repository(repository, transfer_group = [])



175
176
177
178
179
180
181
182
183
184
185
# File 'backend/app/model/mixins/trees.rb', line 175

def transfer_to_repository(repository, transfer_group = [])
  obj = super
  
  # All records under this one will be transferred too
  
  children.each do |child|
    child.transfer_to_repository(repository, transfer_group + [self])
  end

  obj
end

- (Object) tree(ids_of_interest = :all)



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'backend/app/model/mixins/trees.rb', line 97

def tree(ids_of_interest = :all)
  links = {}
  properties = {}

  root_type = self.class.root_type
  node_type = self.class.node_type

  top_nodes = []

  query = build_node_query

  has_children = {}
  if ids_of_interest != :all
    # Further limit our query to only the nodes we want to hear about
    query = query.filter(:id => ids_of_interest)

    # And check whether those nodes have children as cheaply as possible
    self.class.node_model.filter(:parent_id => ids_of_interest).distinct.select(:parent_id).all.each do |row|
      has_children[row[:parent_id]] = true
    end
  end

  offset = 0
  while true
    nodes = query.limit(NODE_PAGE_SIZE, offset).all

    nodes.each do |node|
      if node.parent_id
        links[node.parent_id] ||= []
        links[node.parent_id] << [node.position, node.id]
      else
        top_nodes << [node.position, node.id]
      end

      properties[node.id] = {
        :title => node[:title],
        :id => node.id,
        :record_uri => self.class.uri_for(node_type, node.id),
        :publish => node.respond_to?(:publish) ? node.publish===1 : true,
        :suppressed => node.respond_to?(:suppressed) ? node.suppressed===1 : false,
        :node_type => node_type.to_s
      }

      if ids_of_interest != :all
        properties[node.id]['has_children'] = !!has_children[node.id]
      end

      load_node_properties(node, properties, ids_of_interest)
    end

    if nodes.empty?
      break
    else
      offset += NODE_PAGE_SIZE
    end
  end


  result = {
    :title => self.title,
    :id => self.id,
    :node_type => root_type.to_s,
    :publish => self.respond_to?(:publish) ? self.publish===1 : true,
    :suppressed => self.respond_to?(:suppressed) ? self.suppressed===1 : false,
    :children => top_nodes.sort_by(&:first).map {|position, node| self.class.assemble_tree(node, links, properties)},
    :record_uri => self.class.uri_for(root_type, self.id)
  }
  
  if  self.respond_to?(:finding_aid_filing_title) && !self.finding_aid_filing_title.nil? && self.finding_aid_filing_title.length > 0
    result[:finding_aid_filing_title] = self.finding_aid_filing_title
  end

  load_root_properties(result, ids_of_interest)

  JSONModel("#{self.class.root_type}_tree".intern).from_hash(result, true, true)
end

- (Object) trigger_index_of_entire_tree



197
198
199
200
201
# File 'backend/app/model/mixins/trees.rb', line 197

def trigger_index_of_entire_tree
  self.class.node_model.
              filter(:root_record_id => self.id).
              update(:system_mtime => Time.now)
end

- (Object) update_from_json(json, opts = {}, apply_nested_records = true)



188
189
190
191
192
193
194
# File 'backend/app/model/mixins/trees.rb', line 188

def update_from_json(json, opts = {}, apply_nested_records = true)
  obj = super

  trigger_index_of_entire_tree

  obj
end