You know that when you want to organize many-to-many relationships between two models, the progressive part of humanity uses join-tables and the
has_many
method with the option
:through => :join_model_name
. Each connection between two ActiveRecord objects is an ActiveRecord object.
And this is wonderful, because in a join-table you can create useful (so-called "extra") fields with additional information about the relationships between objects.
The question is how beautiful it is to reach these extra attributes.
')
All screencasts and books, unfortunately, operate with simple examples. For example,
Article and
Category models are friends. Of course, for a join class, the name
Categorization or
ArticleCategorization is intuitive .

Accordingly, if we have two objects -
article and
category , and we want to find an AR-object (or objects) that personify the connection between them, then the authors of books with a pure heart suggest doing this:
relations = article.article_categorizations.find_by_category_id(category)
Life is more complicated. Models often have long compound names, or there is such a connection between models that making a name for each join-model turns into a little torture. Imagine that our models are not
Article and
Category , but
UserGroup and
Community , or
Preorder and
CustomerNotification . What should the binding model be called? Possible options.
Therefore, programmers and somehow pulls to standardize their names within the project, so as not to keep in mind. Templates are chosen according to taste, for example:
1)
FirstmodelSecondmodelRelation : ArticleCategoryRelation, UserGroupCommunityRelation or
2)
FirstmodelVsSecondmodel : ArticleVsCategory, UserGroupVsCommunity
3) ...
Suppose we chose the first option. And now look at what you have to go to just get to the objects of the connecting model:
preorder, message = Preorder.first, CustomerNotification.first relations = preorder.preorder_customer_notification_relations.find_by_customer_notification_id(message)
That is, the "version of the book" looks very verbose. And I would like to see something like:
preorder.relation_to(message)
similarly, it should work in the opposite direction, symmetrically:
message.relations_to(preorder).where(:extra_field => "value")
Why are these features not implemented in Rails? The answer is simple: their names and parameters do not even contain a hint of a link table, and in fact for any two models, the programmer can create as many join tables and links. Which of them should be searched? - unclear.
However, the two functions mentioned above have the right to life and reasonable use.
Because experience suggests:
1) most often between any two models there is only one join-model. And it can be calculated.
2) its objects have to be accessed often, especially if they have extra-attributes.
3) it is not scary to have long names of join-models - if they do not affect the readability of the code.
Add two files to our Rails project:
/lib/ext/active_record/base.rb is the actual
ActiveRecord :: Base extension
module MyExtensions module ActiveRecord module Base
/config/initializers/ext.rb
I will be glad to any additions and fixes simplifying the code.
I will also be happy to comment "dear, there is a simpler way, do this: ...", because I plan to live for a century and study as much :)