This could be a lot simpler than I think and I''m just missing something obvious! I''m working on a creative collaboration app whereby one user could submit a Story and this can then be forked by another user and worked on seperately. To acheive this I have a has_many association within the same Story model as such: class Story < ActiveRecord::Base has_many :forked_stories, :class_name => ''Story'', :foreign_key => :parent_story_id belongs_to :parent_story end In this way if a single story is an original it''s parent_story_id will be nil. Similarly, if I call @story.forked_stories I can get a collection of all the stories that have been forked from the current one, or @story.parent_story will return the story from which it has been forked. What I want is to be able to return all the forked_stories and their forked_stories for a given Story and I''m finding this very difficult since they''re all based on the same model. I keep running into dead ends. If I can return them to a certain depth as well that''d be great, so I''ve been trying to write a method that accepts a depth parameter but the crazy loops are frying my brain. Perhaps there''s something I can do with routes that would solve the problem? -- Posted via http://www.ruby-forum.com/.
Jon Hope wrote:> This could be a lot simpler than I think and I''m just missing something > obvious! > > > I''m working on a creative collaboration app whereby one user could > submit a Story and this can then be forked by another user and worked on > seperately. To acheive this I have a has_many association within the > same Story model as such: > > class Story < ActiveRecord::Base > > has_many :forked_stories, :class_name => ''Story'', :foreign_key => > :parent_story_id > > belongs_to :parent_story > > end > > In this way if a single story is an original it''s parent_story_id will > be nil. Similarly, if I call @story.forked_stories I can get a > collection of all the stories that have been forked from the current > one, or @story.parent_story will return the story from which it has been > forked.So you have a tree structure of arbitrary depth?> > What I want is to be able to return all the forked_stories and their > forked_stories for a given Story and I''m finding this very difficult > since they''re all based on the same model. I keep running into dead > ends. If I can return them to a certain depth as well that''d be great, > so I''ve been trying to write a method that accepts a depth parameter but > the crazy loops are frying my brain.There is a less obvious but ultimately much simpler way to do this. Use a nested-set data structure, which will make what you''re talking about pretty easy. The awesome_nested_set plugin would be just what you need.> > Perhaps there''s something I can do with routes that would solve the > problem?No. Your issues have to do with data structure, not routing. Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/.
On Sep 1, 5:42 pm, Jon Hope <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> What I want is to be able to return all the forked_stories and their > forked_stories for a given Story and I''m finding this very difficult > since they''re all based on the same model. I keep running into dead > ends. If I can return them to a certain depth as well that''d be great, > so I''ve been trying to write a method that accepts a depth parameter but > the crazy loops are frying my brain.As far as I can tell you have an algorithmical difficulty, not one related to Rails. To get back all the forked stories for a given story the following code snippet would do the job: def fork_tree forked = forked_stories forked_from_children = forked.inject([]) do |fstories, fstory| fstories + fstory.fork_tree end forked + forked_from_children end (you can see the whole thing here: http://gist.github.com/179186) Note1: This has been tested under Ruby, not Rails Note2: The method is badly named, since it just returns an array, not a tree-like structure of all the stories forked directly from the story or from its children, or grandchildren, etc. Hope this helps, Bálint
Balint Erdi wrote:> On Sep 1, 5:42�pm, Jon Hope <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote: > >> What I want is to be able to return all the forked_stories and their >> forked_stories for a given Story and I''m finding this very difficult >> since they''re all based on the same model. I keep running into dead >> ends. If I can return them to a certain depth as well that''d be great, >> so I''ve been trying to write a method that accepts a depth parameter but >> the crazy loops are frying my brain. > > As far as I can tell you have an algorithmical difficulty, not one > related to Rails. To get back all the forked stories for a given story > the following code snippet would do the job: > > def fork_tree > forked = forked_stories > forked_from_children = forked.inject([]) do |fstories, fstory| > fstories + fstory.fork_tree > end > forked + forked_from_children > end > > (you can see the whole thing here: http://gist.github.com/179186) > > Note1: This has been tested under Ruby, not Rails > Note2: The method is badly named, since it just returns an array, not > a tree-like structure of all the stories forked directly from the > story or from its children, or grandchildren, etc. > > Hope this helps, > B�lintNote 3: Unless the whole array has already been loaded into memory, that''s horribly inefficient. Nested sets are the way to go here. Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/.
> Note 3: Unless the whole array has already been loaded into memory, > that''s horribly inefficient. Nested sets are the way to go here. > > Best, > -- > Marnen Laibow-Koserhttp://www.marnen.org > mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org > -- > Posted viahttp://www.ruby-forum.com/.Seems interesting, could you sketch up how that would work? Balint
Balint Erdi wrote:>> Note 3: Unless the whole array has already been loaded into memory, >> that''s horribly inefficient. �Nested sets are the way to go here. >> >> Best, >> -- >> Marnen Laibow-Koserhttp://www.marnen.org >> mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org >> -- >> Posted viahttp://www.ruby-forum.com/. > > Seems interesting, could you sketch up how that would work?There are plenty of good articles available on nested sets (notably those by Joe Celko and Vadim Tropashko). Check ''em out, and also look at the awesome_nested_set rdoc!> > BalintBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Best -- Posted via http://www.ruby-forum.com/.