Module: ActsAsDAG::ActMethod
- Defined in:
- lib/acts_as_dag/acts_as_dag.rb
Class Method Summary collapse
-
.descendant_table_entries ⇒ Object
Returns a relation scoping to only descendant table entries table entries that match the link conditions.
-
.link_table_entries ⇒ Object
Returns a relation scoping to only link table entries that match the link conditions.
Instance Method Summary collapse
Class Method Details
.descendant_table_entries ⇒ Object
Returns a relation scoping to only descendant table entries table entries that match the link conditions
51 52 53 |
# File 'lib/acts_as_dag/acts_as_dag.rb', line 51 def self.descendant_table_entries descendant_class.where([:link_conditions]) end |
.link_table_entries ⇒ Object
Returns a relation scoping to only link table entries that match the link conditions
46 47 48 |
# File 'lib/acts_as_dag/acts_as_dag.rb', line 46 def self.link_table_entries link_class.where([:link_conditions]) end |
Instance Method Details
#acts_as_dag(options = {}) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 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 95 96 97 98 99 100 101 |
# File 'lib/acts_as_dag/acts_as_dag.rb', line 4 def acts_as_dag( = {}) class_attribute :acts_as_dag_options .assert_valid_keys :link_class, :descendant_class, :link_table, :descendant_table, :link_conditions .reverse_merge!( :link_class => "#{self.name}Link", :link_table => "acts_as_dag_links", :descendant_class => "#{self.name}Descendant", :descendant_table => "acts_as_dag_descendants", :link_conditions => {:category_type => self.name}) self. = # Create Link and Descendant Classes class_eval <<-EOV class ::#{[:link_class]} < ActsAsDAG::AbstractLink self.table_name = '#{[:link_table]}' belongs_to :parent, :class_name => '#{self.name}', :foreign_key => :parent_id, :inverse_of => :child_links belongs_to :child, :class_name => '#{self.name}', :foreign_key => :child_id, :inverse_of => :parent_links after_save Proc.new {|link| HelperMethods.update_transitive_closure_for_new_link(link) } after_destroy Proc.new {|link| HelperMethods.update_transitive_closure_for_destroyed_link(link) } def node_class; #{self.name} end end class ::#{[:descendant_class]} < ActsAsDAG::AbstractDescendant self.table_name = '#{[:descendant_table]}' belongs_to :ancestor, :class_name => '#{self.name}', :foreign_key => :ancestor_id belongs_to :descendant, :class_name => '#{self.name}', :foreign_key => :descendant_id def node_class; #{self.name} end end def self.link_class ::#{[:link_class]} end def self.descendant_class ::#{[:descendant_class]} end EOV # Returns a relation scoping to only link table entries that match the link conditions def self.link_table_entries link_class.where([:link_conditions]) end # Returns a relation scoping to only descendant table entries table entries that match the link conditions def self.descendant_table_entries descendant_class.where([:link_conditions]) end # Ancestors and descendants returned *include* self, e.g. A's descendants are [A,B,C,D] # Ancestors must always be returned in order of most distant to least # Descendants must always be returned in order of least distant to most # NOTE: Rails 4.0.0 currently ignores the order clause when eager loading, so results may not be returned in the correct order # NOTE: multiple instances of the same descendant/ancestor may be returned if there are multiple paths from ancestor to descendant # A # / \ # B C # \ / # D # has_many :ancestors, :through => :ancestor_links, :source => :ancestor has_many :descendants, :through => :descendant_links, :source => :descendant has_many :path, :through => :path_links, :source => :ancestor has_many :subtree, :through => :subtree_links, :source => :descendant has_many :ancestor_links, lambda { where([:link_conditions]).where("ancestor_id != descendant_id").order("distance DESC") }, :class_name => descendant_class, :foreign_key => 'descendant_id' has_many :descendant_links, lambda { where([:link_conditions]).where("descendant_id != ancestor_id").order("distance ASC") }, :class_name => descendant_class, :foreign_key => 'ancestor_id' has_many :path_links, lambda { where([:link_conditions]).order("distance DESC") }, :class_name => descendant_class, :foreign_key => 'descendant_id', :dependent => :delete_all has_many :subtree_links, lambda { where([:link_conditions]).order("distance ASC") }, :class_name => descendant_class, :foreign_key => 'ancestor_id', :dependent => :delete_all has_many :parents, :through => :parent_links, :source => :parent has_many :children, :through => :child_links, :source => :child has_many :parent_links, lambda { where [:link_conditions] }, :class_name => link_class, :foreign_key => 'child_id', :dependent => :delete_all, :inverse_of => :child has_many :child_links, lambda { where [:link_conditions] }, :class_name => link_class, :foreign_key => 'parent_id', :dependent => :delete_all, :inverse_of => :parent # NOTE: Use select to prevent ActiveRecord::ReadOnlyRecord if the returned records are modified scope :roots, lambda { joins(:parent_links).where(link_class.table_name => {:parent_id => nil}) } scope :leaves, lambda { joins("LEFT OUTER JOIN #{link_class.table_name} ON #{table_name}.id = parent_id").where(link_class.table_name => {:child_id => nil}).uniq } scope :children, lambda { joins(:parent_links).where.not(link_class.table_name => {:parent_id => nil}).uniq } scope :parent_records, lambda { joins(:child_links).where.not(link_class.table_name => {:child_id => nil}).uniq } scope :ancestors_of, lambda {|record| joins(:descendant_links).where("descendant_id = ?", record) } scope :descendants_of, lambda {|record| joins(:ancestor_links).where("ancestor_id = ?", record) } scope :path_of, lambda {|record| joins(:subtree_links).where("descendant_id = ?", record) } scope :subtree_of, lambda {|record| joins(:path_links).where("ancestor_id = ?", record) } after_create :initialize_dag extend ActsAsDAG::ClassMethods include ActsAsDAG::InstanceMethods extend ActsAsDAG::Deprecated::ClassMethods include ActsAsDAG::Deprecated::InstanceMethods end |