Skip to content

Commit

Permalink
Optimize #parent_id Ancestry instance_method
Browse files Browse the repository at this point in the history
If @ancestor_ids has already been calculated, using that value will be
much more efficient for calculating the parent since the work translate
the string to the proper typecasted value has already been done.

But if it hasn't (for example, when calling `.arrange_nodes`), then
ancestor_ids is never actually needed in full, and we can avoid the
object allocations and CPU cycles needed to determine the depth by
typecasting all of the ids in the string and just use a bit of substring
manipulation to only allocate one object prior to typecasting (instead
of N+1 for number of ancestors).

Also, since it is possible for `@_parent_id` to be `nil`, make sure we
are removing the instance variable instead of just setting it to `nil`
if the location in the tree has been changed.
  • Loading branch information
NickLaMuro committed May 17, 2018
1 parent 4a41f3e commit b7e3d2d
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions lib/patches/ancestry_patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ def ancestor_ids
@_ancestor_ids ||= parse_ancestry_column(read_attribute(ancestry_base_class.ancestry_column))
end

def parent_id
return @_parent_id if defined?(@_parent_id)
@_parent_id = if @ancestor_ids
@ancestor_ids.empty? ? nil : @ancestor_ids.last
else
col = read_attribute(ancestry_base_class.ancestry_column)
# Specifically not using `.blank?` here because it is
# slower than doing the below.
if col.nil? || col.empty? # rubocop:disable Rails/Blank
nil
else
rindex = col.rindex(ANCESTRY_DELIMITER)
cast_primary_key(rindex ? col[rindex + 1, col.length] : col)
end
end
end

def depth
@_depth ||= if @ancestor_ids
@ancestor_ids.size
Expand All @@ -45,6 +62,9 @@ def cast_primary_key(key)
def clear_memoized_instance_variables
@_ancestor_ids = nil
@_depth = nil

# can't assign to `nil` since `nil` could be a valid result
remove_instance_variable(:@_parent_id) if defined?(@_parent_id)
end
end
end

0 comments on commit b7e3d2d

Please sign in to comment.