Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StoreModel gem doesn't appear to support arrays

I am trying to use the StoreModel gem to back my jsonb data using classes. When trying to define an array attribute I get ArgumentError (unknown keyword: array). For example:

class A
   include StoreModel::Model

   attribute :my_array, :integer, array:true, default:Array.new
end

Typing this into irb will yield the error.

Upon further inspection it doesn't really seem to be related to the StoreModel gem.

class A
  include ActiveModel::Model
  include ActiveModel::Attributes

   attribute :my_array, :integer, array:true, default:Array.new
end

will yield the same result. According to the Attributes API the class doesn't need to be backed by a database table. However when I try the example:

class MyModel < ActiveRecord::Base
  attribute :my_string, :string
  attribute :my_int_array, :integer, array: true
  attribute :my_float_range, :float, range: true
end

model = MyModel.new(
  my_string: "string",
  my_int_array: ["1", "2", "3"],
  my_float_range: "[1,3.5]",
)

in IRB it attempts to do an SQL query and so I get:

ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR:  relation "my_models" does not exist)
LINE 8:                WHERE a.attrelid = '"my_models"'::regclass
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
                     c.collname, col_description(a.attrelid, a.attnum) AS comment
                FROM pg_attribute a
                LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
                LEFT JOIN pg_type t ON a.atttypid = t.oid
                LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
               WHERE a.attrelid = '"my_models"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum
like image 617
Tracey Beauchat Avatar asked Oct 26 '25 08:10

Tracey Beauchat


1 Answers

the author of the gem is here :) There is an ongoing discussion in the issue here – I'm going to implement a real array support later, but there is a workaround:

  1. Define custom types (I keep them in app/types)
class ArrayOfStringsType < ActiveRecord::Type::Value
  def type
    :array_of_strings
  end
end

class ArrayOfIntegersType < ActiveRecord::Type::Value
  def type
    :array_of_integers
  end

  def cast(values)
    return if values.blank?
    values.map(&:to_i)
  end
end
  1. Register them (initializer is a good place to do that):
ActiveModel::Type.register(:array_of_strings, ArrayOfStringsType)
ActiveModel::Type.register(:array_of_integers, ArrayOfIntegersType)
  1. Use them in your model:
class Configuration
  include StoreModel::Model

  attribute :colors, :array_of_strings, default: -> { [] }
  attribute :prices, :array_of_integers, default: -> { [] }
end
like image 137
Dmitry Tsepelev Avatar answered Oct 28 '25 23:10

Dmitry Tsepelev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!