2010-02-09 11 views
9

Sto provando ad accedere al mio modello genitore nel mio modello figlio durante la convalida. Ho trovato qualcosa su una proprietà inversa su has_one, ma il mio Rails 2.3.5 non lo riconosce, quindi non deve averlo mai inserito nella versione. Non sono sicuro se sia esattamente ciò di cui ho bisogno.Rails accept_nested_attributes_for child non ha padre set durante la convalida

Voglio convalidare il bambino in base alle condizioni genitoriali. Il mio modello principale è già stato creato. Se il bambino non è stato creato quando update_attributes sul genitore, non ha accesso al genitore. Mi sto chiedendo come posso accedere a questo genitore. È dovrebbe essere essere facile, qualcosa come parent.build_child imposta l'id padre del modello figlio, perché non lo fa quando costruisce il figlio per accept_nested_attributes_for?

Per esempio:

class Parent < AR 
    has_one :child 
    accepts_nested_attributes_for :child 
end 
class Child < AR 
    belongs_to :parent 
    validates_presence_of :name, :if => :some_method 

    def some_method 
    return self.parent.some_condition # => undefined method `some_condition' for nil:NilClass 
    end 
end 

La mia forma è di serie:

<% form_for @parent do |f| %> 
    <% f.fields_for :child do |c| %> 
    <%= c.name %> 
    <% end %> 
<% end %> 

Con un metodo di aggiornamento

def update 
    @parent = Parent.find(params[:id]) 
    @parent.update_attributes(params[:parent]) # => this is where my child validations take place 
end 

risposta

0

controllo questi siti, forse vi aiuteranno ...

Rails Nested Attributes Association Validation Failing

accepts_nested_attributes_for child association validation failing

http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

a quanto pare, le rotaie assegnerà parent_id dopo la convalida del bambino riesce. (come genitore ha un id dopo averla salvata)

forse vale la pena provare questo:

child.parent.some_condition 

invece di self.parent.some_condition ... chissà ...

7

Non si può fare questo perché il bambino in memoria non conosce il genitore a cui è stato assegnato. Lo sa solo dopo il salvataggio. Per esempio.

child = parent.build_child 
parent.child # => child 
child.parent # => nil 

# BUT 
child.parent = parent 
child.parent # => parent 
parent.child # => child 

Quindi è possibile forzare questo comportamento eseguendo l'associazione inversa manualmente. Per esempio

def child_with_inverse_assignment=(child) 
    child.parent = self 
    self.child_without_inverse_assignment = child 
end 

def build_child_with_inverse_assignment(*args) 
    build_child_without_inverse_assignment(*args) 
    child.parent = self 
    child 
end 

def create_child_with_inverse_assignment(*args) 
    create_child_without_inverse_assignment(*args) 
    child.parent = self 
    child 
end 

alias_method_chain :"child=", :inverse_assignment 
alias_method_chain :build_child, :inverse_assignment 
alias_method_chain :create_child, :inverse_assignment 

Se davvero lo trovi necessario.

P.S. Il motivo per cui non lo fa ora è perché non è troppo facile. Deve essere esplicitamente detto come accedere a genitore/figlio in ogni caso particolare. Un approccio completo con la mappa delle identità lo avrebbe risolto, ma per la versione più recente è disponibile la soluzione :inverse_of. Alcune discussioni come this one si sono svolte sui newsgroup.

8

Ho avuto un problema simile: Ruby on Rails - nested attributes: How do I access the parent model from child model

Ecco come ho risolto alla fine; impostando il genitore sulla richiamata

class Parent < AR 
    has_one :child, :before_add => :set_nest 
    accepts_nested_attributes_for :child 

private 
    def set_nest(child) 
    child.parent ||= self 
    end 
end 
+0

Ho avuto lo stesso errore dell'op, ma quando ho provato questo metodo ho ottenuto "Chiave (e) sconosciuta: before_add"? – Kvass

8

Avevo sostanzialmente lo stesso problema con Rails 3.2.Come suggerito nella domanda, l'aggiunta dell'opzione inverse_of all'associazione del genitore ha risolto il problema per me.

Problemi correlati