Out of curiosity, do you have a "new task" link on the form which
dynamically adds new fields using Javascript? Is it difficult to
generate the auto-incrementing number with this?
I do have a "new task" link but it doesn't use javascript (I'm
somewhat new to web development so I'm keeping this as simple as
possible, which means no javascript).
Eloy's idea of using a timestamp for the id is, as you said, genius.
Re. Josh's comment on ordering, as long as you use a hash you're safe,
right? You can order by the hash key -- I'm not missing anything?
(perhaps around javascript drag-and-drop reordering?)
Re. approach 5 (in the gist), I prefer approach 4 because in your view
you can say:
fields_for "tasks[#{position}]"
instead of having to remember "update_tasks_params" and
"create_tasks_params".
Like Eloy's implementation, in my project I specify whether or not I
want to destroy records that are missing from the hash, by
definitely agree that the best implementation would be to match what
ActiveRecord already does for tasks= when taking an array of objects
rather than a params hash -- which is, according to the docs:
"Replaces the collection's content by deleting and adding objects as
appropriate."
Re. Eloy's :reject_empty option: I never create records if all the
attributes are blank (i.e. the user presses the "add another task"
button but leaves the task completely blank). Is there really a use
case for that? In fact, if a user deletes all the content from the
fields of an existing task, my implementation would delete that
record.
Great to hear! I brought the issue up because the params parser can
only parse 2 levels deep before it gets screwed up and generates the
wrong hash (I guess this all depends on the hash structure that is
ultimately decided on for nested mass-assignment).
I also agree that enabling this manually makes a lot of sense for
security purposes.
Great to hear! I brought the issue up because the params parser can
only parse 2 levels deep before it gets screwed up and generates the
wrong hash (I guess this all depends on the hash structure that is
ultimately decided on for nested mass-assignment).
Yes, that's why whatever implementation is chosen *must* use hashes
rather than arrays.
Re. Josh's comment on ordering, as long as you use a hash you're safe,
right? You can order by the hash key -- I'm not missing anything?
(perhaps around javascript drag-and-drop reordering?)
Indeed. That's actually what he opted for with that comment, if I understood correctly.
Like Eloy's implementation, in my project I specify whether or not I
want to destroy records that are missing from the hash, by
a :destroy_missing option on the has_many declaration. But I
definitely agree that the best implementation would be to match what
ActiveRecord already does for tasks= when taking an array of objects
rather than a params hash -- which is, according to the docs:
"Replaces the collection's content by deleting and adding objects as
appropriate."
Agreed, it seems to follow the principle of least surprise.
However, I wonder if that might have to do with the fact that
using a has_many writer method is usually not used in combination with mass assignment....?
I guess for me it just doesn't feel right if by default stuff will get deleted,
where one might expect that you are simply updating the attributes.
But this may very well just be me being "paranoia"
Comments?
Re. Eloy's :reject_empty option: I never create records if all the
attributes are blank (i.e. the user presses the "add another task"
button but leaves the task completely blank). Is there really a use
case for that? In fact, if a user deletes all the content from the
fields of an existing task, my implementation would delete that
record.
Using the :reject_empty option as a default might indeed be sensible.
Deleting records for which we get a empty hash however is a different case.
The problem is that you might not always be sending
all attributes of a record. Thus assuming that a empty hash also means that
all the attributes of a record are empty is a bit dangerous.
There are ways to solve this of course, but that is not something I would
like to have by default.
Agreed, it seems to follow the principle of least surprise.
However, I wonder if that might have to do with the fact that
using a has_many writer method is usually not used in combination with
mass assignment....?
I guess for me it just doesn't feel right if by default stuff will get
deleted,
where one might expect that you are simply updating the attributes.
But this may very well just be me being "paranoia"
Comments?
You're right: "I submitted a form to edit one of my comments on a blog
post, and all the other comments got deleted" is way more surprising
than "when Post#comments= takes a params hash it acts differently than
when it takes an array of Comment objects."
This is why I don't like overloading the comments= setter to handle hashes, but prefer having a comments_params= setter instead. The basic setter deals with models, the params setter is the convenience interface for controllers to use for multi-model form support. It's a much simpler implementation too.
Agreed, the setter method should have a different name than the
existing "tasks=" method. The behavior is different enough to warrant
its own method. Otherwise it will just be confusing on the
implementation side and the API side. Is there any good reason for
using the same setter method?
Sorry I'm late to this discussion, I've been on holidays.
I've already spammed the list with this before, but I believe my plugin
(which screws with UrlEncodedParameterParser) could solve some of the
issues you guys are running into with this.
It's not very well named, but it effectively uses Arrays instead of
Hashes when numeric indices are used in the form. It also simplifies the
implementation of UrlEncodedPairParser at the expense of slightly
modified semantics in the parameter parsing (i.e. yes, it breaks a few
tests -- some of which I'm convinced were not correct to begin with).
With such a patch in play, ordering issues would be resolved (thanks to
the use of Arrays) and updates could be detected by effectively checking
if the :id attribute is set on the nested form attributes. In the "Add
Comment" case mentioned later in this discussion, I would assume one
would be doing a many_assoc#<< rather than a many_assoc#= ...
The only thing really missing from the plugin is a way to handle sparse
arrays. i.e. Assigning values only to indices 1, 200 and 999 of an array
should not yield an array of 1000 elements, 997 of which are nil. This
should be fairly trivial.
Agreed, the setter method should have a different name than the
existing "tasks=" method. The behavior is different enough to warrant
its own method. Otherwise it will just be confusing on the
implementation side and the API side. Is there any good reason for
using the same setter method?
The reason I had used the association setter is because in the case
of a has_one association things like fields_for would work out of
the box and I only needed to create a special fields_for for a has_many association.
I know this thread is crazy old…but I’m looking for a solution to submit one form with multiple instances of one model. I have a Responses model, and a user answers many questions on a page (like a quiz), and I want them to submit all their responses on one form. I had it working similar to Ryan’s approach 1, but the problem of multiple inputs with the same name in the HTML was causing trouble.
What is the current thinking on handling this in Rails 5? This has got to be a relatively common thing to want to do…