Module: ContentfulModel::Associations::HasManyNested::ClassMethods
- Defined in:
- lib/contentful_model/associations/has_many_nested.rb
Instance Method Summary collapse
-
#has_many_nested(association_name) ⇒ Object
has_many_nested allows you to set up a tree relationship it calls has_many and belongs_to_many on the class, and sets up some methods to find a deeply-nested instance’s parents.
Instance Method Details
#has_many_nested(association_name) ⇒ Object
has_many_nested allows you to set up a tree relationship it calls has_many and belongs_to_many on the class, and sets up some methods to find a deeply-nested instance’s parents
To set this up in contentful, add a multi-entry field validated to the same model as the parent, and give it a name. For example, Page might have a field called childPages:
has_many_nested :child_pages
would setup up an instance attribute called parent_pages which lists all the direct parents of this page. It would also create methods to find a page based on an array of its ancestors, and generate an array of ancestors. Note that this builds an array of the ancestors which called the object; because ‘many’ associations in Contentful are actually ‘belongs_to_many’ from the child end, we might have several ancestors to a page. You will need to write your own recursion for this, because it’s probably an implementation-specific problem.
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 |
# File 'lib/contentful_model/associations/has_many_nested.rb', line 24 def has_many_nested(association_name) has_many association_name, inverse_of: :"parent_#{self.to_s.underscore}" belongs_to_many :"parent_#{self.to_s.underscore.pluralize}", class_name: self.to_s, inverse_of: association_name # A utility method which returns the parent object; saves passing around interpolated strings define_method :parent do self.send(:"parent_#{self.class.to_s.underscore}") end # Determine if the object has any parents. If it doesn't, it's considered a root. # This only works if the objects are called through their parents' 'child_[whatever]' method define_method :root? do parent.nil? end # Iterate over parents until you reach the root. # @param [Proc] a block to call on each ancestor # @return [Enumerable] which you can iterate over define_method :find_ancestors do |&block| return enum_for(:find_ancestors) unless block if parent.nil? #this *is* the parent return self end block.call(parent) unless parent && parent.root? parent.find_ancestors {|a| block.call(a)} end end # A utility method to return the results of `find_ancestors` as an array # @return [Array] of ancestors in reverse order (root last) define_method :ancestors do self.find_ancestors.to_a end # Return the last member of the enumerable, which is the root # @return the root instance of this object define_method :root do find_ancestors.last end # @return [Boolean] whether or not this instance has children define_method :has_children? do !self.send(association_name).empty? end # @return [Array] a collection of child objects, based on the association name define_method :children do self.send(association_name) end end |