Non-ActiveRecord::Base serialized has_many attributes in a nested form
Per my previous post, I’m trying to be better about recording “Duh” / “Aha” moments in my experiments with Rails to 1) improve my learning / general consumer-of-open-source-software habits, and 2) in hopes that I don’t make similar same silly mistakes again.
This post: `fields_for` with a serialized `has_many` relationship
I’ve used plenty of nested forms recently, but always (and now, in retrospect, not always necessarily) with ActiveRecord-based has_many
relationships.
Today, I was adding a new attribute to an existing model, and wanted to add some attributes that would simply be attached to the model via a serialized field, rather than any sort of join (similar to the setup in this post).
I wanted to store a set of BillItems on each User, but since they would be fairly isolated from anything else in the database and be tied strictly to each User, I decided to just attach it to each User.
And because each User could theoretically have many BillItems, we’d want to ensure :bill_items
was serialized as an Array.
I was finding, though, frustratingly, that the following form was being generated incorrectly - only a single bill_item
field was represented in the form, and even when sanity checking by iterating over bill_item
records manually, the field markup was missing the indices necessary for the form to recognize each field as a separate form parameter. So when the template looked like this:
The output looked (sadly) like this:
What the docs missed out on saying (under One-to-many) is that: rather than the projects_attributes=
attributes writer method just being 1) recommended, 2) worth considering, and 3) available to be replaced by a accepts_nested_attributes_for
if :projects
were already an association on the model, it’s actually required for fields_for
to correctly nest the fields.
And, of course, :bill_items
not being a proper association, I wasn’t able to use the standard accepts_nested_attributes_for
helper and ran afoul of this. With the correct *_attributes
method defined, the form finally displays perfectly, so that bill_items
are passed through correctly, as an Array:
Lesson learned, and change committed.
Let me know what you think on Twitter.