accepts_nested_attributes_for associazione bambino in mancanza di convalida

Sto usando accepts_nested_attributes_for in una delle mie Guide modelli, e voglio salvare i bambini dopo la creazione del padre.

Il modulo funziona perfettamente, ma la convalida non riesce. Per semplicità immaginiamo il seguente:

class Project < ActiveRecord::Base
  has_many :tasks
  accepts_nested_attributes_for :tasks
end

class Task < ActiveRecord::Base
  belongs_to :project

  validates_presence_of :project_id
  validates_associated :project
end

E io sono in esecuzione:

Project.create!(
  :name => 'Something',
  :task_attributes => [ { :name => '123' }, { :name => '456' } ]
)

Al momento del salvataggio il modello di progetto, la validazione è un errore sull’attività perché non hanno un project_id (dal momento che il progetto non è stato salvato).

Sembra Guide seguente modello:

  • Convalidare Progetto
  • Convalidare Attività
  • Salva Progetto
  • Salvare Compiti

Il modello dovrebbe essere:

  • Convalidare Progetto
  • Pass: Salvare il Progetto e continuare…
  • Convalidare Attività
    • Pass: Salvare Compiti
    • A Fallire: per Cancellare il Progetto (rollback forse?)

Quindi la mia domanda si riduce a: Come posso ottenere Guide per eseguire il project_id= (o di progetto=) il metodo e la convalida dei bambini (attività) DOPO che il genitore (progetto) è stata salvata, ma NON salvare il padre (progetto) modello se ogni bambino (attività) non è valido?

Tutte le idee?

 

6 Replies
  1. 12

    Utilizzare questa risposta per 2 Binari, altrimenti vedi sotto per la :inverse_of risposta

    Si può ovviare a questo non controllo per l’project_id se il relativo progetto è valido.

    
    class Task < ActiveRecord::Base
      belongs_to :project
    
      validates_presence_of :project_id, :unless => lambda {|task| task.project.try(:valid?)}
      validates_associated :project
    end
    • Questo non ha funzionato per me. Nel validates_presence_of :project_id chiama ‘progetto’ è il ritorno nil facendolo provare e convalidare il project_id e, in difetto, le convalide. Ho creato un altra domanda, perché ho pensato che il problema era diverso, ma sembra essere la stessa stackoverflow.com/questions/2102724/… .
    • Il inverse_of soluzione di seguito è più corretto per Rails 3.0 e superiori.
  2. 161

    Utilizzare :inverse_of e validates_presence_of :parent. Questo dovrebbe risolvere il tuo problema di convalida.

       class Dungeon < ActiveRecord::Base
         has_many :traps, :inverse_of => :dungeon
       end
    
       class Trap < ActiveRecord::Base
         belongs_to :dungeon, :inverse_of => :traps
         validates_presence_of :dungeon
       end

    http://apidock.com/rails/ActiveModel/Validations/HelperMethods/validates_presence_of

    https://github.com/rails/rails/blob/73f2d37505025a446bb5314a090f412d0fceb8ca/activerecord/test/cases/nested_attributes_test.rb

    • undefined method `validate_presence_of’ per le Guide 3.2.3. La linea dovrebbe essere validates_presence_of :dungeon.
    • Non ha funzionato per me, su rotaie, 3.1.4. Il genitore modello viene salvato anche il modello del bambino non è valido e non è stato salvato.
    • Questo dovrebbe essere accettato risposta, in quanto l’altro è solo una soluzione.
    • Qual è il motivo per questo?
    • Mi piacerebbe fino voto questa risposta, una volta di più perché non solo mi ha salvato ancora una volta.
    • Grazie! questo hepled me fuori alla grande. Poi ho cercato e trovato una buona spiegazione di inverse_of qui: viget.com/extend/…

  3. 9

    Solo convalidare il rapporto, non l’ID:

    class Task < ActiveRecord::Base
      belongs_to :project
    
      validates_presence_of :project
    end

    Non appena l’associazione è popolato, ActiveRecord di considerare la convalida di essere riuscito, anche se non è stato salvato il modello. Si potrebbe desiderare di indagare il salvataggio automatico, per garantire l’attività del progetto è sempre salvato:

    class Task < ActiveRecord::Base
      belongs_to :project, :autosave => true
    
      validates_presence_of :project
    end
  4. 2

    Purtroppo nessuno di questi suggerimenti funziona per me con Rails 2.3.5.

    Nel mio caso, il progetto di un’attività è sempre nullo se entrambi sono creati utilizzando attributi annidati. Solo se mi tolgo la validates_presence_of, crea attraversa con successo. Il test di unità e il registro di dimostrare che tutto è stato creato correttamente.

    Quindi mi piacerebbe ora tendono ad aggiungere vincoli per il DB invece di Guide che sembra essere più affidabile, in primo luogo.

  5. 1

    Si potrebbe creare il progetto e aggiungere solo i progetti, se si supera la convalida:

    tasks = params.delete(:task_attributes)
    if Project.create(params)
      Project.update_attributes(:task_attributes => tasks)
    end

    Ciao

  6. 0

    Contrariamente a quanto bigo suggerisce, non è sempre accettabile per salvare l’oggetto padre prima e poi i bambini. Di solito si desidera assicurarsi che tutti gli oggetti di convalida prima di iniziare il loro salvataggio. Che dà all’utente la possibilità di ri-modificare il modulo di ingresso e di correggere eventuali errori.

    Il problema che tu descrivi verrà risolto in Rails 3.0. Avrei postato un link al Faro di biglietto, ma stackoverflow.com non permettere che questo, perché io sono un nuovo utente (#fail). Ma per il momento, è possibile utilizzare il plugin “parental_control“, che consentirà di correggere il “bug”.

Lascia un commento