# One-to-many and acts\_as\_tree troubles

**URL:** <https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288>\
**Category:** Rails\
**Created:** [July 13, 2007, 4:23am UTC](https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288 "2007-07-13T04:23:02Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![spacesquirrel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/67e7ee/32.png) [@spacesquirrel](https://www.ruby-forum.com/u/spacesquirrel)\
**Post date:** [July 13, 2007, 4:23am UTC](https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288/1 "2007-07-13T04:23:02Z")

</div>

ok. so iâ€™ve got two models, Photo and Place:

class Photo \< ActiveRecord::Base  
belongs\_to :place, :counter\_cache =\> true

class Place \< ActiveRecord::Base

```
 acts_as_tree :order => "name"
 has_many :photo

```

the places database contains specific locations, cities, and states. the  
specific locations connect to cities by parent\_id and in turn cities  
connect to states by parent\_id.

each Photo belongs to a Place, referencing to a place\_id in the photos  
table.

for some reason, i canâ€™t get the one-to-many relationship to work out.  
when i put

\<%= place.photos.size %\>

in a view, i get a NoMethodError saying that â€˜photosâ€™ is an undefined  
method of the Place model.

any ideas?

---

<div class="post-metadata">

**Author:** ![spacesquirrel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/67e7ee/32.png) [@spacesquirrel](https://www.ruby-forum.com/u/spacesquirrel)\
**Post date:** [July 13, 2007, 5:20am UTC](https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288/2 "2007-07-13T05:20:02Z")

</div>

On Jul 13, 9:23 am, Zeke R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> the places database contains specific locations, cities, and states. the
> 
> in a view, i get a NoMethodError saying that ‘photos’ is an undefined  
> method of the Place model.
> 
> any ideas?
> 
> –  
> Posted viahttp://www.ruby-forum.com/.

Try to change :  
from  
class Place \< ActiveRecord::Base  
acts\_as\_tree :order =\> “name”  
has\_many :photo

to  
class Place \< ActiveRecord::Base  
acts\_as\_tree :order =\> “name”  
has\_many :photos #\<------  
may be help you  
p.s. sorry for my english

---

<div class="post-metadata">

**Author:** ![spacesquirrel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/67e7ee/32.png) [@spacesquirrel](https://www.ruby-forum.com/u/spacesquirrel)\
**Post date:** [July 13, 2007, 8:57pm UTC](https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288/3 "2007-07-13T20:57:18Z")

</div>

actually, the recursive descendants method doesn’t really work. here’s a  
replacement.

```
 def descendants
      descendants = []
      self.children.each do |child|
           descendants << child
           if child.children
                child.children.each do |grandchild|
                     descendants << grandchild
                end
           end
      end
      return descendants.flatten
 end

```

i’m able to successfully use this function elsewhere, but i still can’t  
get the :conditions of the has\_many to call include\_descendents…

z.

---

<div class="post-metadata">

**Author:** ![spacesquirrel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/67e7ee/32.png) [@spacesquirrel](https://www.ruby-forum.com/u/spacesquirrel)\
**Post date:** [July 13, 2007, 5:53pm UTC](https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288/4 "2007-07-13T17:53:04Z")

</div>

ah, that did it! thanks!!

now i’ve got a new problem. so, with my hierarchical places structure  
i’d like to be able to count (and allow to be counter\_cache-d) the  
number of photos associated with any descendant of a particular place.

for example, say i’ve got a photo that references the place “central  
park” which in turn references to “manhattan” which references to “new  
york” in the Places tree. i’d like to be able to call this:

```
 Place.find_by_name("new york").photos.size

```

and get the number of photos taken anywhere in manhattan and new york  
combined… i thought this could be accomplished by adding a :conditions  
to the has\_many statement in the Place model:

```
 class Place < ActiveRecord::Base

      acts_as_tree :order => "name"
      has_many :photos, :conditions => include_descendants

      def descendants
           (self.children.each { |child| child.descendants }.flatten 

```

- self)  
end

but i get a NameError, saying that include\_descendents is undefined. any  
suggestions on how to get this to work?

thanks in advance,  
z.

---

<div class="post-metadata">

**Author:** ![spacesquirrel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/67e7ee/32.png) [@spacesquirrel](https://www.ruby-forum.com/u/spacesquirrel)\
**Post date:** [July 14, 2007, 5:07pm UTC](https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288/5 "2007-07-14T17:07:06Z")

</div>

> ```
> class Place < ActiveRecord::Base
> 
> acts_as_tree :order => "name"
> has_many :photos, :conditions => include_descendants
> 
> def descendants
> (self.children.each { |child| child.descendants }.flatten 
> 
> ```
> 
> - self)  
> end

the problem you have is that when you write

class Klass  
has\_many :photos, :conditions =\> include\_descendants  
end

you’re actually writing  
class Klass  
self.has\_many(:photos, :conditions =\> include\_descendants)  
end

ie. the method is being called as a class method on Klass,  
and, as such, the “include\_descendants” is being evaluated when you  
declare the has\_many.

so, the following would evaluate like this

class Klass  
def self.include\_descendants  
“this string gets evaluated at class load time”  
end  
has\_many :photos, :conditions =\> include\_descendants  
end

this would actually define

has\_many :photos, :conditions =\> “this string gets evaluated at class  
load time”

which is plainly not what you want.

(if i wasnt about to go play tennis, I’d have a go at writing the  
recursive relation in SQL for you, so we can make it work proper)

---

<div class="post-metadata">

**Author:** ![spacesquirrel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/67e7ee/32.png) [@spacesquirrel](https://www.ruby-forum.com/u/spacesquirrel)\
**Post date:** [July 13, 2007, 8:58pm UTC](https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288/6 "2007-07-13T20:58:05Z")

</div>

> i’m able to successfully use this function elsewhere, but i still can’t  
> get the :conditions of the has\_many to call include\_descendents…

ack! include\_descendants, rather.

z.

---

<div class="post-metadata">

**Author:** ![spacesquirrel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/67e7ee/32.png) [@spacesquirrel](https://www.ruby-forum.com/u/spacesquirrel)\
**Post date:** [July 14, 2007, 7:44pm UTC](https://www.ruby-forum.com/t/one-to-many-and-acts-as-tree-troubles/109288/7 "2007-07-14T19:44:34Z")

</div>

> has\_many :photos, :conditions =\> “this string gets evaluated at class  
> load time”
> 
> which is plainly not what you want.

ah! i see where this is going now.

> (if i wasnt about to go play tennis, I’d have a go at writing the  
> recursive relation in SQL for you, so we can make it work proper)

eek! maybe i’m going down the wrong road for storing this information.  
perhaps i should migrate to acts\_as\_nested\_set or dotted ids (as  
suggested at  
[http://blog.rapidred.com/articles/2006/06/08/ruby-working-with-trees](http://blog.rapidred.com/articles/2006/06/08/ruby-working-with-trees)) so  
i could find all descendants with one sql query.

maybe then i could set up the has\_many :conditions more easily to work  
with counter\_cache? after all, i could just maintain a photos\_count  
column of my places table manually, updating it whenever a place is  
added to or deleted from the database…

thoughts?

z.
