2012-03-30 11 views
23

Ho un utente e la classe profilo annidata nel modo seguente:attributo nidificati update_attributes usi inseriscono piuttosto che aggiornare

class User < ActiveRecord::Base 
    has_one :profile 
    attr_accessible :profile_attributes 
    accepts_nested_attributes_for :profile 
end 

class Profile < ActiveRecord::Base 
    belongs_to :user 
    attr_accessible :name 
end 

user = User.find(1) 
user.profile.id # => 1 
user.update_attributes(profile_attributes: {name: 'some name'}) 
user.profile.id # => 2 

Non capisco il motivo per cui le rotaie è buttare via il vecchio profilo e crearne uno nuovo.

Utilizzando

user.profile.update_attributes({name: 'some name'}) 

solo aggiorna il profilo corrente come previsto. Ma in tal caso non sto approfittando di accept_nested_attributes_for

Qualcuno sa perché l'aggiornamento avviene in questo modo? Preferirei non finire con un database di righe del profilo non connesso a nessun utente.

+0

si può provare, 'user.update_attributes (profile_attributes: {: id => user.profile.id,: nome: 'some name'})' –

risposta

17

ho risolto questo problema aggiungendo l'opzione update_only:

accepts_nested_attributes_for :profile, update_only: true 

Ora un nuovo profilo viene creato solo se non esiste già.

+3

Sono abbastanza sicuro che la risposta di @Winfield sia quella giusta – jones

+0

Perché non funziona? solo curioso .. – light24bulbs

+0

Perché il default (update_only: false) funziona se si include l'id dell'oggetto nidificato, e ha senso perché è il modo preciso per recuperare l'oggetto nidificato dal database. Maggiori informazioni leggere il http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for – lulalala

21

Se si controlla il modulo, è necessario impostare l'attributo id all'interno dell'hash dell'attributo nidificato per l'oggetto Profile. Se l'ID non è impostato, ActiveRecord presuppone che sia un nuovo oggetto.

Ad esempio, se si dispone di un modulo ERB che crea un set di parametri "utente" con un hash di parametro "profile_attributes" nidificato per il profilo nidificato all'interno dell'utente, è possibile includere un valore nascosto per l'id profilo, come questo :

<%= hidden_field "user[profile_attributes][id]", @profile.id %> 
+0

Come si imposta l'attributo id negli attributi nidificati per l'oggetto Profile? – Glide

+0

Aggiunto un codice di esempio che mostra come iniettare un valore nascosto del modulo. – Winfield

+0

non è un'idea non molto buona? in quanto gli utenti potrebbero solo incasinare con il valore id. fare riferimento all'utilizzo dell'opzione 'update_only: true' come @jason ha detto – davoclavo

31

Per tutti coloro che hanno lo stesso problema in Rails 4: fields_for aggiunge già l'id per i moduli nidificati, ma è necessario consentire il parametro: id. Ho solo permesso un parametro: object_name_id e dato che questo non ha generato alcun errore mi ci è voluto un po 'di tempo prima di vederlo nei log del server. Spero che questo aiuti qualcuno a perdere meno tempo di me su questo :)

+0

sì! grazie, è stato così difficile fare il debug, stupidi params! ;-) – andy

+0

questo è tutto! :) Grazie – XeNoN

+5

Trovo utile cambiare 'config.action_controller.action_on_unpermitted_parameters' a': raise' invece del valore predefinito, ': log'. Rende molto più facile il debug quando ti scoppia in faccia! https://github.com/rails/strong_parameters#handling-of-unpermitted-keys – styger

0

Sono stato colpito con questo in un'altra versione di Rails e ho pensato che perderò la testa. Aggiungendo update_only => true risolto, penso che sia un bug da qualche parte in Rails.

Sintomi nel mio caso: vorrei ottenere l'associazione per appartiene_to cancellato e nuovo oggetto nidificato creato - fino a quando ho prima aggiornato la pagina. Dopo che ha funzionato correttamente.

Nel mio caso ho aggiunto un metodo before_save alla mia classe nidificata e stampato ciò che è stato salvato. Ho anche stampato gli attributi prima di chiamare update_attributes. Avevano il set "parent_id" correttamente. Ho anche incluso il campo ID nascosto nel modulo, nessuna modifica, il che era normale poiché era già incluso utilizzando fields_for ...

Sorpresa: ho visto una chiamata di aggiornamento che generava due chiamate di salvataggio. Il primo salvataggio avrebbe l'id nidificato dell'oggetto ma null per l'id_destinazione. - Quindi questo aggiornerebbe il record per impostare "parent_id" su null. Il secondo salvataggio avrebbe il set "parent_id" ma l'ID oggetto nidificato sarà impostato su null.

Come ho detto, l'ho risolto aggiungendo update_only => true, ma penso che sia ancora un bug.

Vorrei sapere se i sintomi sopra riportati si applicano anche al tuo caso per confermare che si tratta di un bug.

Problemi correlati