0

I'm trying the list my parent and children of my Model "Performance Indicators", in my model I have this for parent/children:

  belongs_to :parent, class_name: "PerformanceIndicator", :foreign_key => 'parent_id2'
  has_many :children, class_name: "PerformanceIndicator", :foreign_key => 'parent_id2'

and in my performance indicators table I have the column parent_id2: t.integer "parent_id2"

But if I try to call the parent like this for example: PerformanceIndicator.parent, its returning "Object", and if I try for the children it says #<NoMethodError: undefined method children' for

What am I doing wrong?

I want to list the performance indicators something like this:

Parent1
  Children1
  Children2
Parent2
  Children1

EDIT:

this is my performance indicators model:

class PerformanceIndicator < ActiveRecord::Base
  has_many :improvement_actions
  has_ancestry

  belongs_to :parent, class_name: "PerformanceIndicator"#, :foreign_key => :parent_id2
  has_many :children, class_name: "PerformanceIndicator", :foreign_key => 'parent_id2'

  scope :parents, -> { where('parent_id2=''') }


  def self.search(search)
    where("name iLIKE ? OR description iLIKE ?", "%#{search}%", "%#{search}%")


    # where("description LIKE ?", "%#{search}%")
  end


end
terrorista
  • 227
  • 1
  • 15

2 Answers2

0

I think you should consider changing your terminology. A child-parent relationship generally infers the child class inheriting from the parent class.

But if I try to call the parent like this for example: PerformanceIndicator.parent, its returning "Object", and if I try for the children it says #

This is happening because you are actually calling the class method parent on your class PerformanceIndicator, which inherits from Object. thus, the parent class of PerformanceIndicator is Object. There is no class method children for your class because it doesn't exist. What you have defined in your class is an instance method.

You must have an instance of your class to call these methods. You can instantiate a new instance of this object like so:

pi = PerformanceIndicator.new
pi.parent
pi.children
Sean
  • 983
  • 5
  • 13
0

The associations of a model are always per instance.

Therefore, you can't access PerformanceIndicator.parent as it is a call to the model itself, but not an instance.

to create proper associations, you have to create different instances, like:

indi1 = PerformanceIndicator.create
indi2 = PerformanceIndicator.create(parent: indi1)

Now you can access them like

indi1.children # => ActiveRecord::Relation
indi1.children.to_a # => [<PerformanceIndicator: id: 2, ....>]

indi2.parent  # => <PerformanceIndicator: id: 1>  alias indi1

If you already have a parent_id, then you should take away parent_id2 and change the relations as follows:

 belongs_to :parent, class_name: "PerformanceIndicator"
 has_many :children, class_name: "PerformanceIndicator", :foreign_key => 'parent_id'

Afterwards, you can create a parent scope:

scope :parents, -> { where(parent_id: nil) }

And you can iterate through them:

PerformanceIndicator.parents.each do |parent|
  # do stuff with parent
  parent.children.each do |child|
    # do stuff with child
  end
end
Dervol
  • 87
  • 4
  • but how can i loop them? I have them created already with the parent_id – terrorista Jun 24 '16 at 17:16
  • I edited my post to show you how to setup iterating through the parents and children. – Dervol Jun 24 '16 at 18:39
  • with that scope it says `stack level too deep` – terrorista Jun 24 '16 at 19:31
  • can you please edit your initial post to show how your productive code looks like, now? – Dervol Jun 24 '16 at 20:23
  • its the same, I just edited my model to what you wrote :/ with the belogs, has_many and the scope – terrorista Jun 24 '16 at 23:20
  • "the same" as before? As you haven't pasted the initial code snippet you are using, we can't see what it looks like. It would be very helpful to see the entire model code and the method with which you are accessing and using the parent-child relation, so we can have a look on why it is running into a recursive call. – Dervol Jun 25 '16 at 08:54
  • the same as your suggestion, i uptated the question with my model. I have parent_id2 because I also have the ancestry gem for a hierarchy mode, but I need multiple parent_id option so I was trying to use other parent id for the one with 2 parents – terrorista Jun 25 '16 at 11:45
  • ah, okay, I got the full picture now. You will have to uncomment the `parent_id2` part of the `belongs_to` association again, then. And I'm deeply sorry, I just tried it out and got the same problem, because the method `parents` already exists in ruby and the whole runs into an object-recursion. You just have to rename the scope to something like `:without_parents` and should be fine. One little further thing: your pasted code of the scope says `where('parent_id2=''')` might get you into trouble because of the apostrophe ambiguity. you should change it to `where(parent_id2: nil)` – Dervol Jun 25 '16 at 14:31
  • okay its working this way :) with this method its possible to have multiple parents ? – terrorista Jun 25 '16 at 15:39
  • Not really,if you plan on having multiple parents, you will have to introduce an `has_and_belongs_to_many` relation to itself. See this article here for more info on how to handle it: [Bi-Directional has_and_belongs_to_many on a Single Model in Rails](http://cobwwweb.com/bi-directional-has-and-belongs-to-many-on-a-single-model-in-rails) – Dervol Jun 25 '16 at 16:15
  • i did that tutorial you said, but now I don't undertand how can I list all the parents and childs in that tutorial way ? – terrorista Jun 26 '16 at 11:17
  • this question has already been answered in other threads, please see the following links: http://stackoverflow.com/questions/11279317/rails-habtm-find-all-records-with-no-association http://stackoverflow.com/questions/18165062/habtm-relation-find-all-records-excluding-some-based-on-association – Dervol Jun 27 '16 at 06:50