2010-09-23 12 views
6

Sto lavorando su un modulo disordinato che, tra le altre cose, deve gestire una sezione con nidificazione a due livelli. Funziona quasi, ma c'è un intoppo e l'unica cosa che posso vedere è diversa dalle altre forme profondamente nidificate che funzionano è che c'è una relazione belong_to piuttosto che has_many. Qui ci sono i modelli:Forme di Rails profondamente annidate che utilizzano belong_to non funzionanti?

Event 
    has_many :company_events, :dependent => :destroy 
    accepts_nested_attributes_for :company_events 

CompanyEvent 
    belongs_to :company 
    accepts_nested_attributes_for :company, :update_only => true 
    belongs_to :event 
    belongs_to :event_type 

Company 
    has_many :company_events 
    has_many :events, :through => :company_events 

quindi è un rapporto abbastanza standard molti-a-molti tramite una tabella di collegamento, company_events. Il modulo in questione è la creazione/modifica di un evento, con un pulsante Javascript dinamico "Aggiungi azienda", tutto basato sullo screencast di Ryan Bates e sul repository GitHub.

La principale forma:

<table id="companies"> 
    <tr><th>Company Name</th></tr> 
    <% f.fields_for :company_events do |builder| %> 
    <%= render 'company_event_fields', :f => builder, :f_o => nil %> 
    <% end -%> 
</table> 
<p><br/><%= link_to_add_fields "Add Company", f, :company_events, "events" %></p> 

E la forma incluse sono le seguenti. Una cosa importante da notare è che l'ID dell'azienda è impostato tramite un aggiornamento Javascript, che non includerò qui perché è lungo. Fondamentalmente l'utente inizia a digitare un nome, viene visualizzato un elenco di completamento automatico e facendo clic sul nome si imposta sia il nome dell'azienda che l'id nel modulo.

<tr class="company_event_fields"> 
    <td> 
    <% f.fields_for(:company) do |company_form| -%> 
     <%= company_form.text_field :name, :size => 80 %> 
     <%= company_form.hidden_field :id %> 
    <% end -%> 
    </td> 
    <td> 
    <%= f.hidden_field :_destroy %> 
    <%= link_to_function "remove", "remove_co_fields(this)" %> 
    </td> 
</tr> 

Quando aggiorno un record esistente, tutto funziona perfettamente. Quando cerco di salvare il modulo con un record appena creato, però, ottengo:

ActiveRecord::RecordNotFound in EventsController#update 

Couldn't find Company with ID=12345 for CompanyEvent with ID= 

Con lo stacktrace:

/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:401:in `raise_nested_attributes_record_not_found' 
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:289:in `assign_nested_attributes_for_one_to_one_association' 
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:244:in `company_attributes=' 
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2906:in `send' 

Ho guardato attraverso il codice a nested_attributes, e passare per con un debugger. Ciò che sta accadendo sembra essere che, poiché c'è un Company.id, ActiveRecord presuppone che ci sia già una voce, ma ovviamente non ne trova una. Questo sembra molto strano, dal momento che ovviamente dovrei passare un ID per creare una nuova voce di CompanyEvent. Quindi, immagino che mi manchi qualcosa.

Gli esempi che ho trovato che funzionano sembrano tutti nidificati usando has_many relazioni fino in fondo, mentre in questo caso è un belongs_to, e mi chiedo se questa sia la radice del problema. Qualsiasi idea sarebbe molto apprezzata ...

risposta

4

Mi sono imbattuto nello stesso problema, sembra proprio che le rotaie non supportino l'uso di modelli nidificati come questo: non è possibile salvare un nuovo oggetto con un modello annidato che esiste, ad esempio, immaginare questa situazione:

class Monkey < ActiveRecord::Base 
end 
class Banana < ActiveRecord::Base 
    belongs_to :monkey 
    accepts_nested_attributes_for :monkey 
end 

questo non funzionerà se si cerca sulla console:

banana = Banana.create! 
monkey = Monkey.new 
monkey.attributes = {:banana_attributes => { :id => banana.id}} 

Ma la sua semplice per ovviare a questo, nel modulo non è necessario impostare alcun attributi nidificati se la tua banana è già persistente, devi solo avere un campo nascosto sul modulo scimmia con banana_id, che si tradurrà in qualcosa di simile:

monkey.attributes = {:banana_id => banana.id} 

E quello salverà proprio bene.

+0

Non ho provato il codice, ma se avete accepts_nested_attributes_for: scimmia, non dovrei essere il tuo esempio banana.attributes = {: monkey_attributes ...}? monkey.attributes = {: banana_attributes ...} non sembra funzionare. –

13

Ecco un'altra soluzione possibile che ho postato in una domanda simile: https://stackoverflow.com/a/12064875/47185

qualcosa di simile ...

accepts_nested_attributes_for :company 
    def company_attributes=(attributes) 
    if attributes['id'].present? 
     self.company = Company.find(attributes['id']) 
    end 
    super 
    end 
Problemi correlati