Come posso modellare adeguatamente le relazioni che hanno una dipendenza ciclica?

3

Prendiamo due semplici modelli di Rails, Post e PostRevision.

class Post < ApplicationRecord
  # Attribute: Status (ex: draft, public, private, deleted)
  # Attribute: Views

  # An owner, likely a belongs_to relation. Perhaps a has_many relation.

  has_many :post_revisions
  validates :post_revisions, :presence => true

  has_many :comments

  has_many :votes

  # Delegation to most recent active / not deleted PostRevision for title,
  # body, tags to effectively expose these attributes
end

class PostRevision < ApplicationRecord
  belongs_to :post

  # Attribute: Title
  # Attribute: Body
  # Attribute: Status (ex: deleted / not deleted, perhaps just an int flag)
  # Attribute: Views

  # Attribute: Revision history notes / text.

  # If a Post has_many owners, an attribute for author/owner of revision

  has_many :tags
end

Il comportamento predefinito dell'associazione "appartiene a" è di richiedere che il record associato sia presente (ovvero, un PostRevision deve avere un Post - questo può essere disabilitato con un argomento).

Questo modello è concettualmente vero, tuttavia c'è un problema che si manifesta nelle azioni di configurazione e controllo del test - vedi questa domanda di overflow dello stack su " "1 a 1 o più" relazioni in SQL . Non è possibile creare un PostRevision finché non c'è un post, ma è necessario un postRevision valido per creare un post. Vedo due opzioni: posso rendere opzionale la relazione "appartiene a" in PostRevision. Questo mi consentirà di creare PostRevision prima di un post e di associarli. In alternativa, posso rimuovere la convalida dell'esistenza di PostRevision su un post. Questo mi permetterebbe di creare un Post e poi PostRevision multipli.

Mi sto appoggiando al secondo approccio: rimuovi la convalida su Post. Tuttavia, non riesco a mettere in parole perché questa è l'opzione migliore, a parte il fatto che sembra più giusto creare il post e le cose che tagliano le revisioni e quindi la revisione con il resto del testo i dati.

Esiste un approccio alternativo che non ho considerato? In caso contrario, c'è qualche tipo di giustificazione razionale all'approccio a cui mi sto proponendo?

    
posta Thomas Owens 22.02.2018 - 00:36
fonte

1 risposta

0

Il problema che stai cercando di risolvere è una forma annidata. Rails lo gestisce con il metodo di classe accepts_nested_attributes_for . Fondamentalmente, quando vai a creare un Post , dovresti anche passare gli attributi nidificati per il primo PostRevision . Rails crea quindi tutti i record insieme in un'unica transazione, consentendo di creare PostRevision prima che venga eseguita la convalida su Post .

Dato un modello Post con un attributo author e un modello PostRevision con attributi post_id , title e body , ecco come apparirà il codice:

class Post < ApplicationRecord
  has_many :post_revisions

  validates :post_revisions, presence: true

  accepts_nested_attributes_for :post_revisions
end

class PostRevision < ApplicationRecord
  has_one :post
end

Ecco il comando per creare Post e il primo PostRevision insieme:

Post.create(
  author: 'Langston Hughes', 
  post_revisions_attributes: [
    {
      title: 'Dust and Rainbows',
      body: <<~POEM 
        Oh, God of Dust and Rainbows, 
        Help us to see
        That without the dust the rainbow 
        Would not be.
      POEM
    }
  ]
)
    
risposta data 14.12.2018 - 08:33
fonte

Leggi altre domande sui tag