Is it possible to have forms that are too DRY ??

Hi.

I've got a form that I'm using with polymorphic associations. It's
super basic. The form fields will be used in multiple places, but the
hidden polymorphic fields will change with each model that needs them.

Currently in views/books/new.html.erb
<% form_for(@review) do |f| %>
  <b>Title</b><%= f.text_field :title %>
  <b>Body</b><%= f.text_area :body %>
  <%= f.hidden_field :reviewable_type, :value => 'Book' %>
  <%= f.hidden_field :reviewable_id, :value => @book.id %>
  <%= f.submit "Submit" %>
<% end %>

Currently in views/reviews/_form.rhtml
<% form_for(@review) do |f| %>
  <b>Title</b><%= f.text_field :title %>
  <b>Body</b><%= f.text_area :body %>
  <%= f.submit "Update" %>
<% end %>

Is it better to just have 2 fields in a form partial in views/reviews
and then have the other required fields in the appropriate views?

If I DRY them up, they would look like this.

In views/books/new.html.erb
<% form_for(@review) do |f| %>

  <%= render :partial => 'reviews/form', :locals=>{:f => f} %>

  <%= f.hidden_field :reviewable_type, :value => 'Book' %>
  <%= f.hidden_field :reviewable_id, :value => @book.id %>
  <%= f.submit "Submit" %>
<% end %>

In views/reviews/_form.rhtml
<b>Title</b><%= f.text_field :title %>
<b>Body</b><%= f.text_area :body %>

Thanks for the great guidance!

Becca,

It looks like you're on the right track, but you might want to
familiarize yourself with nested resources/routes in Ruby on Rails.
You shouldn't need to specify the type/id as hidden fields like this.

In your routes, you can do something like:

  map.resources :books, :has_many => [ ::reviews ]

Then where you want to show the review form, you could do something like...

<% form_for :book, :url => book_reviews_path( @book ) do |f| %>

When the form submits, you should see the book_id in the params hash,
which you can use to connect the dots.

Good luck!

Cheers,
Robby

What I've found is that DRY is good until it leads to the point of
obscurity...

I use a standard partial to handle the hidden fields for routing users
to the appropriate place after an add or update (if you add a B from A,
you should go back to A. if you added the B from C, you go back to C,
etc).

As long as the partials are named descriptively and can lead another
developer easily to the correct source, "DRY"ness is in the eye of the
beholder...

Robby Russell wrote:

In your routes, you can do something like:

  map.resources :books, :has_many => [ ::reviews ]

Then where you want to show the review form, you could do something
like...

<% form_for :book, :url => book_reviews_path( @book ) do |f| %>

When the form submits, you should see the book_id in the params hash,
which you can use to connect the dots.

I have this in my routes file
map.resources :books, :has_many => [ :reviews ]

But I wasn't able to get the form_for to work for me. Do I have to
include an action to get this to work properly or do I need to revise
the above syntax to get that to work properly.

I currently have an error on this line <%= f.text_field :title %> with
the error message of" undefined method `title'".

Thanks.