Schema Coercion mysql / sqlite integer to boolean

Can someone give me an example of how this can be done? OR how I should be reading these values (0/1) from the database to have them represented by ruby false and true?

Thanks!

1 Like

You can use a custom read type, ie attribute :admin, Types::Integer, read: Types::Params::Bool

Thanks! This works of course, but it is unclear why it works. The dry types state

params - types with constructors performing non-strict coercions specific to HTTP parameters

Why use the Params type category over others when reading from the db?

In this case, because Params does the loose type coercion that you need for numeric booleans.

By default, dry-types is strict about type checking. Try it and see:

Types::Strict::Bool[1]
# => Dry::Types::ConstraintError: 1 violates constraints (type?(FalseClass, 1) failed)

An integer is not a boolean in Ruby, and you don’t want that to be the case most of the time. Ruby is a strongly typed language, and so if you intend to convert a number to a boolean it should be done explicitly.

Interacting with a different type system is a special case, and Params is there to do those kind of coercions. It’s not specifically meant for databases, but it works here.

In more advanced cases, you might want to define your own coercion rules for custom types. For instance, this boolean coercion might be written as

Bool = Types::Strict::Bool.constructor do |input, type|
  case input
  when true, 1, 't', 'TRUE' then true
  when false, 0, 'f', 'FALSE' then false
  else type.(input)
end
1 Like

Thank you kindly for your detail response. This is helpful!