Custom Array Converters
zbaylin opened this issue · 4 comments
If I have a class Circle
and a model Shapes
, if I define a custom converter for Circle
(CircleConverter
) and do this:
class Shapes
...
column circles : Array(Circle)
...
end
I get this error: Error: No converter found for Array(Circle).
How do I convert arrays of custom types/classes?
Hi,
You cannot use directly your circle converter with Array(Circle)
because the way array is encoded might be different based on your implementation. You need to create a converter for Array(Circle)
and add it like this:
Clear::Model::Converter.add_converter("Array(Circle)", ArrayCircleConverter)
How do you go about doing this? I have the Circle encoded as TEXT
in the DB
I'm not sure about your data, but first you need to figure out what kind of data the pg
gems detect.
It might be Slice
or already Array(::PG::StringArray)
For that you can try a simple Select query like this:
# Assuming your column is living in models.circles
# I've not run this code so it might have some typo or errors :)
value = Clear::SQL.select.from("models").pluck_col("circles")
puts values.class.name
puts values
After that, just build your converter, based on the output you got; assuming it's a Array(::PG::StringArray)
for example (code not tested but you get the idea):
module ArrayCircleConverter
def self.to_column(x) : Array(Circle)?
return nil unless x
case x
when ::Array(::PG::StringArray)
return x.map{ |circle| CircleConverter.to_column(circle.to_s) } # Tricky `to_s` call here: circle could be a nested array but don't want to care about it.
else
raise "Cannot convert from #{x.class} to Array(Circle)"
end
end
def self.to_db(arr : Array(Circle)? ) : Clear::SQL::Any
return nil unless x
arr.map do |c|
Clear::Expression.unsafe({"Array[", CircleConverter.to_db(c), "]"}.join)
end
end
end
With some tweaking I got this to work, thanks!