Methods of storing arrays in MySQL

#1

Hi all,

I’m converting a project that currently uses Mongoid to use ROM and MySQL. Due to some infrastructure restrictions, we need to use MySQL, rather than PostgreSQL or another RDBMS.

I need to be able to store an array of strings. This would be fairly easy to do with Postgres, but not so with MySQL. From what I understand, I can do something like this to set write/read types:

module Persistence
  module Relations
    class Countries < ROM::Relation[:sql]
      JSONWrite = Dry::Types::Constructor.new(Dry::Types['string'], fn: ->(v) { JSON.dump(v) })
      JSONRead = Dry::Types::Constructor.new(Dry::Types['string'], fn: ->(v) { JSON.parse(v) })

      schema(:countries) do
        attribute :id, Types::Integer
        attribute :number_types, ROM::Types::String, read: JSONRead

        primary_key :id
      end
    end
  end
end

However, when I try to then create a record:

Dry::Types::SchemaError: ["geographic", "toll_free"] (Array) has invalid type for :number_types violates constraints (no implicit conversion of Array into String failed)
from /Users/ethan/.asdf/installs/ruby/2.5.3/lib/ruby/gems/2.5.0/gems/dry-types-0.14.0/lib/dry/types/hash/schema.rb:192:in `rescue in block in coerce'
Caused by TypeError: no implicit conversion of Array into String
from /Users/ethan/.asdf/installs/ruby/2.5.3/lib/ruby/2.5.0/json/common.rb:156:in `initialize'

The column number_types is set of TEXT MySQL type, so I’m not sure where to go from here.

#2

You configured db type to be Types::String, you want to set JSONWrite there instead. Otherwise rom assumes the input will be a string, and you pass an array, so it must go through your JSONWrite.

#3

Thanks for the help! Looks like it’s saving correctly, however it’s not reading correctly. From throwing a binding.pry into the JSONRead type, it’s actually reading it twice: once when it’s actually a string, and then again when it’s an array. Why would it be doing this?

I guess a better question to ask is if there’s a suggested way to do serialization with ROM?

#4

Oh this doesn’t sound good. Are you able to reproduce this in a simple standalone script?

#5

I’m not sure I’m able to reproduce this in a standalone script — I realized we’re using the edge version of ROM from the GitHub repo, downgrading fixed the issue.

#6

oh that’s very useful info, we’ll look into it.