Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ActiveSupport::Concern to clean up dependencies #11

Merged
merged 1 commit into from
Feb 9, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 34 additions & 35 deletions lib/parentry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,49 @@ module Parentry
autoload :Navigation, 'parentry/navigation'
autoload :ClassMethods, 'parentry/class_methods'

# rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/BlockLength
def self.included(base)
base.class_eval do
mattr_accessor :parentry_strategy, :parentry_column, :depth_offset, :cache_depth, :touch_ancestors
extend ActiveSupport::Concern

belongs_to :parent, class_name: base_class.name, optional: true
has_many :children, class_name: base_class.name, foreign_key: :parent_id, dependent: :destroy
# rubocop:disable Metrics/BlockLength
included do
include Navigation
include InstanceMethods

validate do
errors.add(:parent, 'must be persisted') unless parent.blank? || parent.persisted?
end
mattr_accessor :parentry_strategy, :parentry_column, :depth_offset, :cache_depth, :touch_ancestors

validate :prevent_circular_parentry
belongs_to :parent, class_name: base_class.name, optional: true
has_many :children, class_name: base_class.name, foreign_key: :parent_id, dependent: :destroy

after_create :commit_parentry
before_update :assign_parentry, if: proc { changes[:parent_id].present? }
after_update :cascade_parentry, if: proc { saved_changes[parentry_column].present? }
validate do
errors.add(:parent, 'must be persisted') unless parent.blank? || parent.persisted?
end

before_validation :cache_parentry_depth, if: proc { cache_depth }
before_save :cache_parentry_depth, if: proc { cache_depth }
validate :prevent_circular_parentry

after_save :touch_ancestors_callback
after_touch :touch_ancestors_callback
after_destroy :touch_ancestors_callback
after_create :commit_parentry
before_update :assign_parentry, if: proc { changes[:parent_id].present? }
after_update :cascade_parentry, if: proc { saved_changes[parentry_column].present? }

scope :order_by_parentry, -> { order(parentry_depth_function) }
before_validation :cache_parentry_depth, if: proc { cache_depth }
before_save :cache_parentry_depth, if: proc { cache_depth }

scope :before_depth, ->(depth) { where("#{parentry_depth_function} - 1 < ?", depth + depth_offset) }
scope :to_depth, ->(depth) { where("#{parentry_depth_function} - 1 <= ?", depth + depth_offset) }
scope :at_depth, ->(depth) { where("#{parentry_depth_function} - 1 = ?", depth + depth_offset) }
scope :from_depth, ->(depth) { where("#{parentry_depth_function} - 1 >= ?", depth + depth_offset) }
scope :after_depth, ->(depth) { where("#{parentry_depth_function} - 1 > ?", depth + depth_offset) }
after_save :touch_ancestors_callback
after_touch :touch_ancestors_callback
after_destroy :touch_ancestors_callback

scope :roots, -> { where("#{parentry_depth_function} = 1") }
scope :ancestors_of, ->(node) { where(node.ancestor_conditions).where.not(id: node.id) }
scope :children_of, ->(node) { where(parent_id: node.id) }
scope :descendants_of, ->(node) { subtree_of(node).where.not(id: node.id) }
scope :subtree_of, ->(node) { where(node.subtree_conditions) }
scope :siblings_of, ->(node) { where(parent_id: node.parent_id).where.not(id: node.id) }
end
scope :order_by_parentry, -> { order(parentry_depth_function) }

scope :before_depth, ->(depth) { where("#{parentry_depth_function} - 1 < ?", depth + depth_offset) }
scope :to_depth, ->(depth) { where("#{parentry_depth_function} - 1 <= ?", depth + depth_offset) }
scope :at_depth, ->(depth) { where("#{parentry_depth_function} - 1 = ?", depth + depth_offset) }
scope :from_depth, ->(depth) { where("#{parentry_depth_function} - 1 >= ?", depth + depth_offset) }
scope :after_depth, ->(depth) { where("#{parentry_depth_function} - 1 > ?", depth + depth_offset) }

base.send :include, Navigation
base.send :include, InstanceMethods
base.extend ClassMethods
scope :roots, -> { where("#{parentry_depth_function} = 1") }
scope :ancestors_of, ->(node) { where(node.ancestor_conditions).where.not(id: node.id) }
scope :children_of, ->(node) { where(parent_id: node.id) }
scope :descendants_of, ->(node) { subtree_of(node).where.not(id: node.id) }
scope :subtree_of, ->(node) { where(node.subtree_conditions) }
scope :siblings_of, ->(node) { where(parent_id: node.parent_id).where.not(id: node.id) }
end
# rubocop:enable Metrics/AbcSize,Metrics/MethodLength,Metrics/BlockLength
# rubocop:enable Metrics/BlockLength
end