3

I have a serialized Array field in my model called :cords, and part of my form looks like so:

<%= form_for @group do |f| %>
    ....
    <p>
        <%= f.label :cords %><br>
        <%= f.text_field :cords, name: "group[cords][]" %>
    </p>
    ....

Then inside my controller, I attempt to use it like so

    @group = Group.new(params.require(:group).permit(:name, :members, cords: [] ))

    if @group.save
        redirect_to @group
    else
        render 'new'
    end

This doesn't seem to work though, because when I type in some array like [[1,2],[3,4]] I see the SQL insert is

INSERT INTO "groups" ("cords", "name", "members", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["cords", "---\n- \"[[1,2],[3,4],[5.5,6]]\"\n"], ["name", "GG"], ["members", 55], ["created_at", "2017-06-12 02:13:37.462355"], ["updated_at", "2017-06-12 02:13:37.462355"]]

Why is cords submitted as ["cords", "---\n- \"[[1,2],[3,4],[5.5,6]]\"\n"]? I believe I'm doing something wrong with my actual form setup

5
  • Which database management are you using? Commented Jun 12, 2017 at 2:20
  • @SebastiánPalma Default that comes with rails5.1? Commented Jun 12, 2017 at 2:28
  • 1
    Sqlite doesn't support array columns type, see the datatypes in the version 3, most probably youll need Postgresql. Commented Jun 12, 2017 at 2:42
  • 1
    I would be very eager to see the params that are coming in the server log. Commented Jun 12, 2017 at 5:22
  • try this <%= f.text_field "group[cords][]" %> instead Commented Jun 12, 2017 at 8:37

1 Answer 1

6
+50

Explanation of problem:

Rails serialized column indeed allow us to store complex data types such as array, but they do so in YAML format by default. What you do is pass a text as group[cords][] param. So, what you should get in your params is {group: {cords: [ "[[1,2],[3,4],[5.5,6]]" ]}}. Take notice, that cords is array of one element, which is string you pass to it: "[[1,2],[3,4],[5.5,6]]"

That array gets serialized in compliance with YAML scalar syntax: "---\n- \"[[1,2],[3,4],[5.5,6]]\"\n". Let's look at it up close, first substituting newlines:

---
- "[[1,2],[3,4],[5.5,6]]"
#here also newline

Three hyphens indicate start of YAML document.

Array is packed like this:

- "first_element"
- "second_element"
- "third_element"

Is equal to ["first_element", "second_element", "third_element"]

Backslash before quotation marks just escape those in SQL denoting that quotes are part of the string.

So, as you can see, rails do just what it is supposed / you told it to do: it gets single string as one element of array and it stores one element of array, containing that string.

Solution:

What you should do if you still want to get user input as array is transform that manually.

  • Drop the [] in text_field: f.text_field :cords, name: "group[cords]"
  • In controller, transform that text into ruby array, for example like this:
def cords_to_a
  # get the params[:group][:cords], if it's empty use empty array string
  cords = params.dig(:group, :cords).presence || "[]"
  # parse it, possibly you also want to handle parse exceptions
  # and transform parsed array as something else
  # also, user will be able to save any json object
  # to your serialized field, and it will be parsed
  # accordingly: either to array or to hash
  JSON.parse cords
end

def group_params
  params.require(:group).permit(:name, :members).merge({cords: cords_to_a})
end

and after that use Group.new(group_params)

Take notice: you still will get a "strange" string in your INSERT statement, because that will contain YAML-encoded array: essentially, a string.

Further reading:

Sign up to request clarification or add additional context in comments.

2 Comments

Awesome answer! When my question becomes eligible, I'm going to give you a bounty for going into such detail.
You absolutely nailed it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.