开发者

Rails: How to use fields_for with two objects of the same class in a single form?

I'm trying to use form_for and fields_for in Rails 3 to let me edit two objects (of the same class) on one page, but I'm not having any luck: the second object's HTML input tags come out with the same IDs as the first object's.

The specific situation:

  • I have a class Card. I'm trying to follow general RESTful patterns for it.
  • Most Cards stand alone, but a small number of them have a second Card object affiliated with the first one, via the "link" property. (I call these "multipart" Cards.)
  • I want it to be possible to use the standard Card edit page (views/cards/edit.html.erb and views/cards/_form.html.erb) to switch a Card from standalone mode to multipart mode. I'm using JavaScript to show the second set of edit fields on the form when the user selects multipart mode on the edit page. Therefore, the edit form for every Card needs to contain the form fields for a second Card, to potentially become the "link"ed Card from the main Card being edited.
  • The HTML fields for the second Card should be identical to those for the first one. I have a complex pretty HTML layout for my fields and inputs, and I want to keep things DRY and avoid duplicating all that code for the second Card's field.

This turns out to be really problematic. I've tried assorted things like:

<%= form_for(@card) do |outer_form| %>
...
 <% [@card, @card2].each_with_index do |card, card_index| %>
  <%= fields_for card do |f| %>

This doesn't work because the second object's HTML input tags come out with the same IDs as the first object's. They both come out with HTML <select id="card_rarity" name="card[rarity]">, which seems obviously wrong.

I tried changing the quoted lines to say

 <% [@card, @card2].each_with_index do |card, card_index| %>
  <%= fields_for (card_index == 0 ? card : card.link) do |f| %>

with the hope that this would then provide HTML names like "card[link][rarity]". (Edit:) But it doesn't: even with fields_for card.link, it still produces form fields with name="card[rarity]". So the page has two inputs with the same name and ID, and discards one of them on submission.

I tried saying

 <% [@card, @card2].each_with_index do |card, card_index| %>
  <%= fields_for card, :as => (card_index == 0 ? "card" : "card2") do |f| %>

but that didn't work either. The :as parameter seemed to be completely ignored.

Can anyone suggest the approach that I'm missing here? I don't find the official documentation on form_for and fields_for ver开发者_Python百科y helpful.

(Edit to add:) In particular, surely there must be a way to edit fields for two different objects of the same class within a single Rails form? fields_for makes it trivial to do this with any number of objects of different classes - but how can it be done for two of the same class?

Many thanks!


You say:

with the hope that this would then provide HTML names like "card[link][rarity]", but the problem there is that Rails calls class_name on the object, and in most cases card.link is Nil. I don't want submission of this form to automatically create a dummy linked card for all cards, which is what I think would happen in this case.

I would pursue this strategy a bit more. In your edit controller action I would add @card.link ||= Card.new to prevent nil access errors; in the update controller action (or in the Card model itself if you want to defer the logic there), make sure that empty "link" cards are discarded.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜