Deep join, where clauses, and demeter principles

Hello everyone,

I am looking to split my code from one “god” relation into related relations.
The split would help reliability and composability.

I will use an example with Animals, Classifications, and Categories.

class Animals < ROM::Relation[:sql]
  schema(:animals, infer: true) do
    associations do
      belongs_to :classifications

  def level_one_animals
    # Here join classification with categories level 1

class Classifications < ROM::Relation[:sql]
  schema(:classifications, infer: true) do
    associations do
      belongs_to :categories

  def with_categories_level(level)
    # Here join categories for level

class Categories < ROM::Relation[:sql]
  schema(:categories, infer: true)

  def for_level(level)
    where(level: level)

How may Animals join Classification and Categories, without knowing anything about Categories?

Thanks !

Use whatever query makes sense in your case. Typically, you want as little db roundtrips as possible and data in a form that is either exactly what you need or very close to what you need, so that you can easily post-process it on the ruby side.

Demeter doesn’t apply here as long as you define view methods, meaning methods that always return relation objects.

Yes, but I need to split as possible features so that I can reuse them.

In my production app, “Animal” has 1000 lines, and have features that “Foo” would like to use when using “Classification”.

If my queries AST are not splittable, so I have to repeat myself, including security and it’s a bad pattern.

AST sharing should not impact database performance, because you continue to process it in ruby, not queries have been made to the database.

Reusability can be achieved through relation plugins. Have you looked into it?

I had never heard anything about relation plugins, do you have any documentation about it?

I have seen that there are pull requests from 2015-2016 that add this kind of feature but nothing how to use it.