The rationale behind the `belongs_to` name

ecto

#1

If a schema can have several belongs_to associations with different other schemas then to which of these does it really belong?

For me, the belongs_to name implies the idea of aggregation between schemas, but an aggregate is something indivisible, so the fact that something can have several belongs_to associations does not seem to make sense.

Where does the belongs_to name come from?

What is our opinion about this?

Thanks


#2

Directly - from Rails’ ActiveRecord. But it must be older than that :slight_smile:


#3

Do you have other proposal? belongs_to is natural opposite of has_many/has_one. I believe that name used by Ecto comes from ActiveRecord, but I also believe that it is much older in it’s origin.

And since when aggregations are indivisible? Have you even heard of intrusive lists?


#4

An aggregate is indivisible.

From Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans (I highly recommend):

An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single, specific ENTITY contained in the AGGREGATE. The root is the only member of the AGGREGATE that outside objects are allowed to hold references to, although objects within the boundary may hold references to each other. ENTITIES other than the root have local identity, but that identity needs to be distinguishable only within the AGGREGATE, because no outside object can ever see it out of the context of the root ENTITY.


#5

Other names? Well never thought about that but quickly perhaps:

  • belongs_to – for an aggregated child
  • one – for a single association
  • and many – for multiple associations

Perhaps it would serve the purposes, don’t know.


#6

Can you elaborate on how you’re relating an ecto schema or set of schemas to the notion of an aggregate? Is a single schema an aggregate? a collection of them?


#7

You can build aggregates on top of a single or multiple schemas.

For a single schema, you can use embedded schemas, so the aggregate comprises the single schema and its embedded schemas.

For the other case, you have a “root” schema, and several child schemas, all separated, but at application level you treat a “root” and its “children” as an aggregate.

By using the notion of aggregate, you can leverage a typical SQL database as if it was a document-oriented one, with the advantages of both, but without the inconvenience of the second (mainly its query limitations to the inner parts of aggregates in these databases).

Essentially this results in building a document-oriented like database on top of an SQL database.


#8

So perhaps this question can be answered by the Rails folks …


#9

Cool, so going off of:

An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes.

Where does the “aggregate is indivisible” come in here? If you have a collection of schemas, their indivisibility from an outside view doesn’t prevent them from having associations with one another.


#10

You are right, and in that case you must care that your code does not break the indivisibility.

The solution to this is building an aggregate-aware layer on top of Ecto, and then, use that layer directly in the code instead of Ecto.

I am designing my application around this, so to have the best of aggregates and SQL.


#11

Isn’t that just the repository pattern/concept?


#12

No, it’s something above that, above Ecto. See the referenced book above (in fact the repository pattern is described in this book too).


#13

Yes, that’s what I meant, sorry. Not Ecto.Repo, but having a MyFooRepository module with functions coordinating persistence of various Ecto schema instances.


#14

Yep, that’s it: the schema MyFoo is handled as an aggregate, and MyFooRepository coordinates the root schema MyFoo and its child schemas.


#15

This level of DDD aggregate idea can be implemented as a Phoenix context.

It’s also possible (though I’m not sure how widely practiced) to have multiple Ecto Repos that all point to the same physical db.


#16

I am not aware of Phoenix contexts because I never used Phoenix, but soon I will, so I would like to understand how they relate to the notion of aggregate. Can you explain this better?

I did not understand what you wanted to say with the second sentence. Can you be more clear?


#17

Many words have been spent discussing Phoenix Contexts. I’d suggest starting here How would you explain Phoenix Contexts to a newbie?

It’s been a long time since I read DDD, but if you squint you can correlate Phoenix contexts with a less strict type of bounded context.

The basic idea is that Ecto Repos do not have to map 1:1 with physical databases. You can set up an Ecto Repo per aggregate/context if you want. I have done this once with the idea that we might want to shift the database tables backing a particular aggregate to another physical database in the future. With this Repo separation, it would only involve Repo config change but no real code change. It offers a finer grain to the Repository pattern than most users of Ecto consider.


#18

It’s been around for a long time but personally I always preferred the simple “one to many”, “many to one”, “many to many” and “one to one”.

Rails was very big on language expression when it first came out and there are entire rule sets around pluralization of object names, pluralizer libraries that account for language exceptions, etc to work within that model.

It is easier to say “A User belongs to an Account” than “Users are many to one with Accounts”. The inverse is fine “An Account has many Users”.

The issue was around key placement. If you say “A User has one Account” the language is fine but you don’t know where the key is stored. Rails went with “A User belongs to an Account” to mean the user table has an account id and “A User has one Account” to mean the Account table has a User id.


#19

I think you have answered well to my original question, making clear what was the idea of introducing the belongs_to name. This name solved the problem you mention, nevertheless it causes confusion when thinking on aggregation between entities.

I don’t know if the idea of aggregates existed by the time Rails was introduced, if it existed but Rails’ authors were not aware of it, or if they were aware but ignored that choosing belongs_to would conflict with such idea. Perhaps they thought about it but did not find anything better than belongs_to that would solve the key placement problem, without conflicting with the aggregate idea.

Perhaps a better nomenclature exists …, perhaps it exists not.

Thank you.