2017-10-14 2 views
0

Un transaction_record a beaucoup workflows, et chaque workflow a beaucoup milestones. L'un des milestones est marqué current: true, et je veux aller de l'transaction_record au current_milestone:Rails has_one: à travers avec le nom du modèle différent

class TransactionRecord < ApplicationRecord 
    has_many :workflows 
    has_many :milestones, through: :workflows 

    # DOES NOT WORK, but what I want to do... 
    has_one :current_milestone, through: :workflows, class: Milestone, source: :milestones 

    # Works, but want to make an association for including 
    def current_milestone 
    milestones.where(current: true).first 
    end 
end 

class Workflow < ApplicationRecord 
    belongs_to :transaction_record 
    has_many :milestones 
end 

class Milestone < ApplicationRecord 
    belongs_to :workflow 
end 

Je peux créer une méthode qui retourne le choix milestone, mais je veux faire une association réelle que je puisse incluez-le pour les performances de DB.

J'ai une page transaction_records#index où je liste le transaction_records et le current_milestone pour chacun. C'est un n+1 sauf si je peux comprendre cela.

Je veux vraiment être en mesure de faire quelque chose comme:

@transaction_records = TransactionRecord.includes(:current_milestone) 

<% @transaction_records.each do |transaction_record| %> 
    <%= transaction_record.name %> - <%= transaction_record.current_milestone.name %> 
<% end %> 

mise à jour

Je peux spécifier une relation de direction entre transaction_record et milestone, puis faire transaction_record has_one :current_milestone, -> { where(current: true) }, class_name: Milestone. Mais maintenant je change mon schéma DB pour une requête de chargement plus efficace. Pas la fin du monde, mais pas ma préférence si j'ai déjà une association.

Répondre

0

Pour être honnête, je n'aime pas le concept, que transaction_record a une sorte de active_milestone sans mention de rejoindre current_workflow.

bonne solution est de penser à la fois workflow et milestone d'avoir une capacité d'être current puis:

class TransactionRecord < ApplicationRecord 
    has_one :current_workflow, .... 
    has_one :current_milestone, through: current_workflow, .... 
end 

class Workflow < ApplicationRecord 
    has_one :current_milestone, condition: .... 
end 

Ceci est beaucoup mieux pour moi, mais vous avez encore besoin d'ajouter attribut supplémentaire current de drapeau dans workflow .

C'est pourquoi une meilleure solution est de retravailler votre concept. Supprimez current du jalon et ajoutez current_milestone_id au workflow. Si c'est nul, alors ce workflow n'a pas current_milestone. S'il contient un identifiant, alors ceci est votre current_workflow et current_milestone_id.

Le code sera très similaire, mais il ne sera pas laid dans Workflow