Integrating polymorphic models into controllers views? how?

I'm having trouble trying to get this to work.

How the heck do you get a polymorphic controller to work? Especially
integrating it with a view?

Let's say that we have shows, and episodes, then comments.

A show has many episodes, an episode has many comments.

the route is /shows/1/episodes/1/

Now to add a comment to that episode, how would I do it? Let's say
that the comment is polymorphic, how do I create a dynamic view for
polymorphic assocations? This has the same question towards a
controller. I have taken a look at http://revolutiononrails.blogspot.com/2
... llers.html but that still doesn't answer my question with two
parents?

I need something like

- form_for([@parent1, @parent2, :comment]) do |f|
  = f.text_area :comment
  = f.submit 'Comment!'

Any help would be awesome, thanks!

Anyone?

Hi --

I'm having trouble trying to get this to work.

How the heck do you get a polymorphic controller to work? Especially
integrating it with a view?

Let's say that we have shows, and episodes, then comments.

A show has many episodes, an episode has many comments.

the route is /shows/1/episodes/1/

Now to add a comment to that episode, how would I do it? Let's say
that the comment is polymorphic, how do I create a dynamic view for
polymorphic assocations? This has the same question towards a
controller. I have taken a look athttp://revolutiononrails.blogspot.com/2
... llers.html but that still doesn't answer my question with two
parents?

I need something like

- form_for([@parent1, @parent2, :comment]) do |f|
  = f.text_area :comment
  = f.submit 'Comment!'

Any help would be awesome, thanks!

Try this in routes.rb:

   map.resources :shows do |s|
     s.resources :episodes do |e|
       e.resources :comments
     end
   end

and then in the view:

   <% form_for "comment", :url => comments_path(@show,@episode) do |f| %>

assuming you've set @show and @episode in the controller.

David

David,

Thanks, my question is how to make this:

<% form_for "comment", :url => comments_path(@show,@episode) do |f|
%>

More dynamic, because it's a polymorphic model (comments)

Is there a way to make it so it can automatically pull the parents?

Something like <% form_for "comment", :url =>
comments_path(@parent1,@parent2) do |f| %>

And the controller will automatically figure out that @parent2 =
episode and @parent1 = show.

Anyway to do that?

Hi --

David,

Thanks, my question is how to make this:

<% form_for "comment", :url => comments_path(@show,@episode) do |f|
%>

More dynamic, because it's a polymorphic model (comments)

Is there a way to make it so it can automatically pull the parents?

Something like <% form_for "comment", :url =>
comments_path(@parent1,@parent2) do |f| %>

And the controller will automatically figure out that @parent2 =
episode and @parent1 = show.

Anyway to do that?

OK, I see what you mean now. I wonder whether you could modify the
railsrevolution code so that parent_resources took an array... and
then you could do:

class CommentController < ApplicationController
   parent_resources [:show, :episode], [:user, :post]

etc. I haven't tried it yet, but I think it could well work nicely.

(This is also reminding me that I really must get back to work on the
Inferred Routes plugin, which lets you skip the parent nesting for
nested resource routes, and see how it shapes up with all the recent
changes.)

David

Whoops, I mean revolutiononrails. /me reaches for coffee....

David

Hi --

Hi --

David,

Thanks, my question is how to make this:

<% form_for "comment", :url => comments_path(@show,@episode) do |f|
%>

More dynamic, because it's a polymorphic model (comments)

Is there a way to make it so it can automatically pull the parents?

Something like <% form_for "comment", :url =>
comments_path(@parent1,@parent2) do |f| %>

And the controller will automatically figure out that @parent2 =
episode and @parent1 = show.

Anyway to do that?

OK, I see what you mean now. I wonder whether you could modify the
railsrevolution code so that parent_resources took an array... and
then you could do:

class CommentController < ApplicationController
  parent_resources [:show, :episode], [:user, :post]

etc. I haven't tried it yet, but I think it could well work nicely.

Now I've tried it. Here's a first iteration, anyway. First, add
these methods to the ones from the revolutiononrails blog post (in
application.rb):

   def parent_ids(parent)
     parent.map {|p| parent_id(p) }
   end

   def parent_types
     self.class.parents.detect {|parent| parent_ids(parent) }
   end

   def parent_classes
     parent_types && parent_types.map {|pt| parent_class(pt) }
   end

   def parent_nest
     parent_classes && parent_classes.zip(parent_types).map {|pc, pt|
       pc.find_by_id(parent_id(pt))
     }
   end

Now, in comments_controller.rb:

   parent_resources [:show, :episode], [:user, :post]

   def new
     @parent_nest = parent_nest
     @comment = Comment.new # still one of my least favorite common
                               # Rails idioms, but anyway
   end

And then in the view -- this part could use some refinement:

   <% form_for @parent_nest << @comment do |f| %>

etc.

Since @parent_nest is already an array, you can't just list it
alongside @comment inside an array -- though of course you could
modify form_for so that that would be possible.

The kind of functional testing you'd want would be things like:

   def test_parent_nesting
     CommentsController.parent_resources([:show, :episode], [:user, :post])
     get("new", :user_id => 1, :post_id => 1)
     assert_equal([:user, :post], @controller.send(:parent_types))
     assert_equal([User, Post], @controller.send(:parent_classes))
     assert_equal([User.find(1), Post.find(1)], @controller.send(:parent_nest))
   end

Hopefully that will get you started.

David