How can I get rails to automatically populate a dynamically generated form?
Asked Answered
C

1

0

Let's say I have a model

class A < ApplicationRecord
  serialize :vals, Array
end

which stores an array of values. How can I dynamically populate a list of form values? My first guess was to write

<%= @a.vals.each_with_index do |v, i| %>
  <%= f.text_field :hints %>
<% end %>

but this is giving me errors.

Commonly answered 12/7, 2017 at 20:9 Comment(7)
Broadly speaking, A.vals is wrong because you are declaring vals as a serialized field, which would be accessed from an instance of A, not the class object. serialize :vals, Array looks wrong, because Array isn't a serializer class. Won't be able to get more specific than that without more information. What is the form_for or form_tag for the example form? How is vals initialized?Illuminati
You should add the errors to your question. And, what @AdamLassek said, too. (Although, serialize :vals, Array may be correct based on this answer - not 100% sure.)Hardiness
@AdamLassek serialize :vals, Array worksCommonly
@AdamLassek thank you for pointing out that typo.Commonly
@Commonly you're right, it looks like serialize will default to YAML if you give it a non-coder class, and then it will pass the deserialized value into Array.new.Illuminati
@AdamLassek Interesting. Is this behavior documented?Commonly
@Commonly the official documentation sort of discusses it, but it's not entirely clear what happens.Illuminati
W
2

Submitting this form

<%= form_for @a do |f| %>
  <% @a.vals.each do |val| %>
    <%= f.text_field :vals, value: val, multiple: true %>
  <% end %>

  <%= f.submit %>
<% end %>

passes "a"=>{"vals"=>["first", "second", "third"]} in the params to the controller.

As mentioned in the comments, you want to look at the vals from an instance of A not the class A.

Note about the serialize (more for the comments saying it looks wrong) I had never used it, that serialize :vals, Array seems to be working for me

A.create(vals: ['hint 1', 'hint 2']); A.last.vals
#   (0.2ms)  BEGIN
#   SQL (0.4ms)  INSERT INTO ... [["vals", "---\n- hint 1\n- hint 2\n"]...
#   (0.6ms)  COMMIT
#   A Load (0.3ms)  SELECT  "as".* FROM "as" ORDER BY "as"."id" DESC LIMIT $1  [["LIMIT", 1]]
# => ["hint 1", "hint 2"]
Wive answered 12/7, 2017 at 20:33 Comment(2)
Also, I made a typo for the instance of A.Commonly
After inspecting the source of serialize more closely, it appears that passing a non-coder class like Array causes it to default to YAMLColumn, which passes the deserialized data into Array.new. So there was some magic here that confused me.Illuminati

© 2022 - 2024 — McMap. All rights reserved.