rom-rb / rom

Data mapping and persistence toolkit for Ruby
https://rom-rb.org
MIT License
2.08k stars 161 forks source link

Configurable StructCompiler #528

Open solnic opened 5 years ago

solnic commented 5 years ago

Currently, it's not possible to configure a custom StructCompiler because MapperCompiler uses a hard-coded constant. This can be easily changed to use an option with the default value set to StructCompiler.

Examples

This could be configurable on a per-relation basis, with the ability to pre-configure it for all relations from a specific gateway instance.

Setting for all relations in a given gateway

# set it for all relations, this can be handled in `finalize_relations` because we have
# access to gateway instance there
config = ROM::Configuration.new(:sql, 'sqlite::memory', struct_compiler: MyStructCompiler)
rom = ROM.container(config)

Setting per relation

class Users < ROM::Relation[:sql]
  # the same method should be used in `finalize_relation` when we set it
  # via gateway config
  struct_compiler MyStructCompiler

  schema(:users, infer: true)
end

TODO

Resources

Refs #519

parndt commented 5 years ago

This would be useful @solnic! I had to work around this in https://github.com/parndt/rom-firebase at https://github.com/parndt/rom-firebase/blob/master/lib/rom/firebase/mapper_compiler.rb

flash-gordon commented 5 years ago

For the record, dry-struct 1.0 has support for "direct loading" i.e. without type checks. It's done internally via allocate + send(:initialize, attributes). It's ok to instantiate structs this way when the storage has internal type checks (e.g. in case of a SQL database). We probably want to use it for loading ROM::Structs because it's faster. Since it doesn't work for all cases, it should be an adapter-specific setting with possible manual override. We should also consider case where base class has constructor types in its definition (no idea if we should detect it automatically).