shroy
shroy

Reputation: 918

Rails 4: Complex Many to Many Relationships

I have the following models..

Like an eco-system, all models should have many-to-many relationships with one another. It's very important that I am able to query data from all directions.

After intensive research on Active Record associations, I find many blogs warning against has_and_belongs_to_many and using has_many :through. Only issue is that requires a table to act as the "middle-man" for lack of better words but I'm unsure how that would work with a 3 models.

The other option is a polymorphic association but I'm unsure if I should invest the time in understanding that method if it's inapplicable for this particular situation.

Any advice on how to create these relationships for maximum flexibility and efficiency?

Upvotes: 2

Views: 441

Answers (1)

PerformanceDBA
PerformanceDBA

Reputation: 33708

I have the following models

Tables, if they were modelled for a Relational database, files otherwise.

It's very important that I am able to query data from all directions.

Understood. That is simple and easy in a Relational Database.

Like an eco-system, all models should have many-to-many relationships with one another.

That is not correct.

If each of the three can be related to the other two, then your data is not modelled. There are basic dependencies that you have not identified. Eg: I can imagine that:

  • Providers provide services at Clinics

  • Clinics provide services to Patients

  • Patients visit Clinics to obtain services

  • Therefore, any relationship that a Patient may have with a Provider is via a Clinic, and not privately, without a Clinic.

Straighten those rules and dependencies out first, that will result in less than three Associative tables second. Something like this:

Response to Comment

Any advice on how to create these relationships for maximum flexibility and efficiency?

Well, Dr E F Codd's Relational Model is strongly established as the model, the method for organising data, such that it has (a) complete integrity (objects can't) (b) maximum flexibility (c) maximum speed. In the 45 years since its advent, there have been no other contenders. That is the model I am using. The principles that underpin that model are the principles that I rely upon, when I make my proposals.

All that has been, of course, confirmed and reinforced during my 34 years of database implementations. As well as thousands of other high-end implementations.

Data Independence

I've taken your post with great consideration and the difficulty is that there are many unique nuances with my app that won't allow me to simplify it to mirror the real world.

It is the other way around. The fact is, you are writing an app+db that deals with the real world. Therefore the db has to reflect that real world (limited to the scope of the enterprise) that you wish to engage with. Thousands of modellers have done that successfully (millions have done it incorrectly).

To the extent that you have "nuances" and complexities in the app, you have not modelled the data, as data, and the result will be a complex app that engages with an incorrectly modelled database, or worse, a non-database. All those "nuances" and complexities are in fact data; facts about data; rules about the data; and relationships between data. But you have an established view that the "nuances" and complexities are in the app, in your "models", not in the data.

Therefore your notion is false.

Every rule, constraint, control, nuance, complexity re the data, must be implemented in the data. That is simply data definition as per the RM. Otherwise you have no data independence, no database (just a bunch of files for data storage), no integrity, no relational power, no speed. And worse, you will be forever fixing up the "nuances" and complexities in the app layers, the object stack.

Data Definition

Let me start from first principles.

  • a databse is a collections of Facts, including relationships between those Facts

Assuming you understand that, there is an important next point.

  • There is no Fact that cannot be declared.

This is First order Logic, which the RM is based on. Therefore there is no such thing, as a "model" that is too complex (has "nuances" or too many "nuances") to be declared in terms of FOL. The scientific exercise that is called for, is to reduce that complexity to FOL Facts.

To the extent that those Facts are Facts about the real world, and they reflect the truth, your database will be isolated from the effect of change (you can extend the database and the app easily). Eg. Provider, Service, Specilisation are separate Facts.

To the extent that those "facts" are "facts" that you have chosen to store (as being relevant, from the perspective of your app, object design, etc), eg. Provider, Service and Specialisation as a single complex "fact", not discrete Facts, and not a reflection of the real world, your database and objects (a) will be hard to change, and (b) will keep changing, forever, until they are elevated, such that they do reflect the real world. You will have to "re-factor" the "database" every quarter.

Confidentiality

The data is very confidential so I'm reluctant to get to far into the matter.

We have been working with confidential data and/or systems for over 45 years without breaching confidentiality.

  • There is nothing new under the Sun.

  • We are dealing with structure, not content, it is not reasonable to suggest that your structure is so new and unique that it cannot be (i) discussed or (ii) modelled.

  • But most important, if you cannot describe it (in FOL terms), you cannot model it. If you cannot model it, you cannot write an app to engage with it (you can try, but as evidenced here, you will be stuck in that unresolved position).

  • Noting that the OO/ORM literature teaches people to obsess about the data content, in order to avoid dealing with the structure, meaning, relevance, etc, please note that I do not want to know. and the exercise does not need to know, the content. Describe only the data in terms of meaning, relevance, relationships, and we will model the required structure.

My question was more about how to create a cycle of many-to-many relationships with 3 models than whether my models "should" have them or not.

I think I understand that. That would be adding complexity to an article of which the complexity has been determined to be the fundamental problem. If you ask me to build an airplane without wings, and I tell you that your approach is incorrect, that you need wings, there is no point in telling me that you are seeking someone who can tell you HOW to build an airplane without wings, you have missed the point.

Reasoning

I would love to hear your reasoning if you believe there should never be a situation like this in any database.

Again, you have that the wrong way around. It is not that there should never be a situation like this in any database, it is that if there is a situation like this, it raises a red flag (to qualified and experienced modellers) that the data is not yet Normalised, not yet organised into discrete Facts. That means you need to take a step back and deal with the complexity in your "models", first. Then the relationships that are your current focus will be simplified.

Then, yes, there will not be a situation like this in the database.

My reasoning is Codd's RM, and the principles behind it. It has been the subject of many papers. (As well as many "papers" that are non-relational or anti-relational, such as those that support the OO/ORM "model".)

  • Specifically, here, that if you have a n-ary relation (technical term for the three-way relationship that you are seeking) that that can be, and should be, resolved into [multiple] binary relations (two-way relationships). Eg. the TRD I have suggested.

OO/ORM Mythology

In the context of "love to hear your reasoning", there are two sides, I have given the what you should be doing side, above. This is the what you should not be doing or why your method is broken side. Where do I start.

The OO/ORM model is that the "database" is merely a storage location to make the objects "persistent", a slave of the objects, and that constructing a monolith, layers of object classifiers, complexity, is the way to solve any problem.

The OO/ORM model is a total, abject failure. It has no scientific basis whatsoever.

  • (Noting that due to the destruction of the education system, these days "mathematicians" and "theoreticians" write "papers" that "prove" complete and utter nonsense. It is nonsense because it contradicts established science. They are not the class of mathematicians and theoreticians of the old school, who reject contradiction; non-science; nonsensical proofs. The only way that they can write such absurd "proofs", in to maintain a state of ignorance, a state of pathological denial, of other sciences.)

  • Specifically, they are in denial of the Relational Model (whilst referring to it, to give their papers some credibility, which is a fraud); its prescriptions (such as Data Independence, FOL); its prohibitions, they are in denial of Relational data models (UML cannot model data like IDEF1X can), thus they produce non-relational files, which have no Relational integrity, power, or speed.

  • They employ the Hammer phylosophy (ie. if one only knows a hammer, then every problem looks like a nai), in staggering denial that Maslow destroyed it, scientifically, over a century ago. Which leads them to pile more layers, more complexity, into the monolith. The converse is of course, to use the right tool for the job, which means define data according to the standard for data, the RM, and separately, objects according to whatever OO philosophy you choose.

  • They attempt to do everything in objects, to model everything in UML (which is not a standard by any means; nor adequate [one symbol plus a million notations], it has no decomposition, it is in fact a free-for-all in which everyone does their own thing).

  • The model exists is denial of the fact that since 1980's, in the software industry, we architect, write, and deploy components. Database components in the database, program components in the objects. Not monolithic Towers of Babel, that is pre-1970's technology.

  • Since 1984, we have had Client/Server and Open Architecture Standards. We have had OLTP Transaction Standards since 1960, restated in the C/S context in 1984. The OO/ORM crowd are in flagrant rebellion of each and every one of those Standards, they build monolithic object stacks sans architecture, sans components, sans Transactions, sans everything. (Apologies to the Bard.)

    You might consider what everyone (even cartoonists) knows about the OO/ORM stack, the monolith, the non-architecture and compare it with the deployment of components in the Open Architecture diagram, given above.

  • Further, they are in denial that every implementation of the "model" is a massive failure, they deny the evidenced facts, and keep adding complexity to the already complex and unmanageable object layers. A "model" that has failed due to its non-architecture, part of which is precisely that failed complexity.

  • In case their evidenced pathological denial of the reality does not stand, in and of itself, as evidence of insanity, there is more, much more. The Twelve Steppers have an interesting definition of insanity: doing the same thing over and over again, being aware that it produces the same result, every time, but expecting a different result the next time. That doesn't stop them from adding more complexity to the complex model, or from marketing their pre-1970's technology, as "modern" "science".

  • But that doesn't stop them from writing yet more books and marketing their failed "model".

    The OO/ORM crowd exists in isolation from, in pathological denial of, reality

Put another way, it is insane, in 2015, to implement software, in a un-architected monolith, that "does everything", rather than to architect; design; build; and deploy software components in the correct architectural position.

OO/ORM "Model" as Data

The fact that you keep calling your tables "model" is another red flag. That confirms that you have way too much complexity in them. A database consists of simple tables, each reflecting a discrete Fact, not models. To the extent that you consider them "models", you have (usually due to fixed notions re complex objects and classifiers) objects+data+complexity combined, not discrete data and discrete objects. That is the precise problem that will cause the app+db to fail.

So the next step is to (a) shelve the current focus re HOW to relate un-normalised complex "models", and to (b) normalise those "models" such that they are defined in terms of a Relational Database, such that they are discrete Facts. Following which, (c) the relating of the then Normalised tables will be straight-forward.

In one instance, each model acts as a type of 'User' but in another, they don't.

That is exactly the type of mashed-up concept that has to be rationalised, Normalised, such that it is (a) absolutely clear [when it is an user, and when it isn't] (b) defined in data, in FOL terms, as discrete Facts (c) such that you can confidently write code against it, build objects from it. Conversely, the absence of that clarity, the retention of complexity in the object layers, will result in complex objects that fail, and more important, data stored in files that have no integrity, power, or speed.

Self-Contradiction

Consider this. Since you are seeking Relational integrity, power, and speed, you cannot at the same time be

  • seeking to retain unresolved complexity that is well-known to destroy integrity, power, and speed, or

  • refusing to implement the requirements the host integrity, power, and speed, that you seek.

It is a massive, and double, contradiction, on your side. It is a philosophical and reasoning issue, that you have to consider and resolve for yourself. The OO/ORM seduces people into believing in magicke, into such crazy self-contradictions.

Regardless, I was very impressed with your answer and really appreciate the time you took to make the diagram.

Thank you. You are most welcome.

That took me all of five minutes. Because I have clarity. Because I follow scientific principles and standards. Because we have had a science and a methodology since 1970. Because we have had a modelling methodology and full notation for modelling Relational Data since 1987 (as a standard, IDEF1X, since 1993). The point is, it is nothing special, the sad fact is, it is not common, and it should be. The second sad fact is, it is unknown in the OO/ORM world.

Further Reading

You may be interested in this Question and Answer. The Answer covers many aspects of Relational Databases, that you will most certainly have to deal with, if not now, then at some point in the future. The minimum reading I draw your attention to right now is: - Response to Update 3, pages 1, 2 and 6, - specifically including the embedded link to Predicates That might give you an idea of the reasoning; the depth of data definition that the RM affords; that all Facts can be declared in terms of FOL Predicates, that the OO/ORM crowd is totally ignorant of.

You may choose to add an Update to your question and ask how to declare one or the other "model", in terms of the RM, as discrete Facts, or open a new Question (and ping me).

Conversely, if you choose to stick to your position, the original question, then I think I have answered it (but the answer raises issues that you must address and resolve).

Please study carefully and comment or ask questions.

Upvotes: 2

Related Questions