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 –

On Fri, 10 Aug 2007, DanielFischer.com wrote:

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

  • 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

Hi –

On Fri, 10 Aug 2007, DanielFischer.com wrote:

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

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?

On Sat, 11 Aug 2007, [email protected] wrote:

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

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

David

Daniel F. wrote:

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)

In application_helper.rb:

def polymorphic_comments_path(item)
send("#{item.class.to_s.underscore}_comments_path", item)
end

Hi –

On Sat, 11 Aug 2007, [email protected] wrote:

<% form_for “comment”, :url => comments_path(@show,@episode) do |f|
episode and @parent1 = show.
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