2011-10-08 17 views
8

che sto cercando di utilizzare accepts_nested_attributes_for su un modello di associazione has_one, e ottenere assolutamente nulla :-(Rails 3.1: accept_nested_attributes_for e has_one association - non funzionerà?

Ho due modelli, un utente e una posizione Un utente ha una posizione:.

class User < ActiveRecord::Base 
    # current location 
    has_one :location, :dependent => :destroy 
    accepts_nested_attributes_for :location 
end 

class Location < ActiveRecord::Base 
    belongs_to :user 
end 

posso salvare le modifiche al modello utilizzando User.find(1).location.current_location_text = "blah" dalla console, quindi so le associazioni sono impostati correttamente.

ho due forme sulla pagina di modifica dell'utente. Uno che aggiorna gli attributi utente principale (e funziona bene e non mostrato sotto) e poi questo che consente all'utente di aggiornare un att ribute del modello di posizione, chiamato "current_location_text":

<%= form_for(@user) do |f| %> 
    <%= fields_for(@user.location) do |location_fields| %> 
     <%= location_fields.label :current_location_text, 'Current Location' %> 
     <%= location_fields.text_field :current_location_text, :placeholder => 'Road, City or Postcode' %> 
    <% end %> 

    <%= f.submit "Update Current Location" %> 
<% end %> 

Questo non funziona. Sono un po 'confuso perché i parametri inviati dal modulo sembrano errati. Quando il modulo viene inviato, questo è nel registro:

Started PUT "https://stackoverflow.com/users/1" for 127.0.0.1 at 2011-10-08 00:28:05 +0100 
    Processing by UsersController#update as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"YdTAsXwEvRgXIqri+jfx3dLlYG2XWQTuYkgLDsO/OJw=", "location"=>{"current_location_text"=>"E14 8JS"}, "commit"=>"Update Current Location", "id"=>"1"} 
    User Load (10.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 
    User Load (5.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = ? LIMIT 1 [["id", "1"]] 
    SQL (4.4ms) BEGIN 
    (2.5ms) COMMIT 
Redirected to http://localhost:3000/users/1 

Due cose che trovo strano su questo:

  1. C'è il messaggio "commit", ma senza stringa di aggiornamento precedente, e nessun errore. Ad esempio, se si è tentato di eseguire il commit di un attributo protetto, si otterrà il messaggio di errore "impossibile assegnare la massa ..." a quel punto.

  2. I parametri mi sembrano sbagliati. Il bit "location" è annidato come mi aspetto, ma mi piacerebbe anche aspettatevi di essere un nidificato all'interno l'hash "utente", qualcosa di simile:

    {"utf8"=>"✓", "authenticity_token"=>"YdTAsXwEvRgXIqri+jfx3dLlYG2XWQTuYkgLDsO/OJw=", "user"=>{"location"=>{"current_location_text"=>"E14 8JS"}, "commit"=>"Update Current Location", "id"=>"1"}} 
    

Non credo Sono completamente stupido qui. Mi manca qualcosa di veramente ovvio? Ho provato ad aggiungere ulteriori campi nascosti al mio modulo, cioè un id utente, e poi ottengo l'hash dell'utente, ma allo stesso livello dell'hash "location", e non come genitore di esso come mi aspetterei!

anche se aiuta, ecco il mio aggiornamento nel mio UsersController:

aggiornare def @user = User.find (params [: id])

if @user.update_attributes(params[:user]) 
    redirect_to current_user, :notice => 'User was successfully updated.' 
else 
    render :action => "edit" 
end 

finali

ed ecco ciò che è nella mia routes.rb (anche se non credo che sia rilevante):

resources :users do 
    resource :location 
end 

Qualsiasi aiuto apprezzato. Se non risolvo questo, il portatile esce dalla finestra ... Grazie.

risposta

11
<%= fields_for(@user.location) do |location_fields| %> 

Questo è il tuo problema.È necessario in realtà "nido" della fields_for all'interno del modulo, in questo modo:

<% f.fields_for(@user.location) do |location_fields| -%> 
+0

Riferimento documentazione? Tutto quello che posso vedere è che il documento "<% -%>" tratta degli spazi bianchi finali. (http://api.rubyonrails.org/classes/ActionView/Base.html) – 0112

+0

Giusto per chiarire, il problema era 'fields_for' vs' f.fields_for'. Il '-%>' era solo un'abitudine. –

5

Prova a modificare la

<%= f.fields_for :location do |location_fields| %> 

Piuttosto che dare è l'oggetto stesso, dire rotaie quale associazione che si desidera avere lo carico per

+0

Grazie - in realtà ho bisogno di fare anche questo, trovo strano che l'utilizzo di un oggetto nella dichiarazione fields_for non funziona. – DaveStephens

+0

Per chiunque utilizzi la gemma Judge per la convalida in linea: si otterranno errori con questo metodo. Utilizzare @ user.location anziché il simbolo perché Judge deve fare riferimento all'oggetto. – bradleygriffith