Ensure parent models are the same for a has_many :

2019-09-18 06:08发布

问题:

I have a Department parent model that is associated with a Product and Document model through a has_many / belongs_to relationship. The Product and Document models are then associated to each other through a has_many :through relationship via a ProductDocuments join model.

As part of the associations there is a requirement that the Product and Document models have the same Department parent model when being associated to each other.

Right now I'm doing the following:

ProductDocumentsController < ApplicationController
    ...
    def create
        @product = Product.find(params[:product_document][:product_id])
        @document = Document.find(params[:product_document][:document_id])

        if @product.department.id == @document.department.id
            ...
        end
    end
    ...
end

This works, however it feels inefficient as it introduces two addition database calls in the controller.

Does anyone know of a way that this can be accomplished in a more efficient way, perhaps through a validation in the model?

Any help would be greatly appreciated; thank you!

回答1:

Here are my thoughts. Get pencil, paper and draw with me =). I've ended up with something like this.

Department * * * Product
*                   *
*                   *
*                   *
Document * * * ProductDocument

And that is something called circular reference. Typically it leads to cases like yours - complex validations of field equality among possibly infinite number of tables. So, how do we fix it?

Couple of variants:

  1. Simply break one of the links. For example, Document will reference to Product alone.
  2. Remove references to Department from both Product and Document, and put it somewhere else. For example, into ProductDocument (however, it's going to be renamed to something more appropriate since it will join three models).

That's all I can say for now.