Hé les gars, je me suis cogné la tête contre un mur avec un cas d'utilisation particulier pour les formes imbriquées (j'utilise Rails 2.3.5).Rails imbriqué avec ressource imbriquée: mise à jour appartient à l'association lors de la création has_many
Essentiellement, j'ont des modèles de projet et de paiement qui ressemble à ceci
class Project < ActiveRecord::Base
has_many :payments
end
class Payment < ActiveRecord::Base
belongs_to :project
accepts_nested_attributes_for :project
end
J'utilise aussi le routage imbriqué pour ces deux ressources:
map.resources :projects do |project|
project.resources :payments
end
J'essaie d'utiliser une forme imbriquée pour permettre à l'utilisateur de modifier certains attributs du projet lors de la création d'un nouveau paiement. Donc, si le projet a un titre, par exemple, la vue de la création d'un nouveau paiement ressemblerait à ceci:
<% form_for([@project, @payment]) do |f| %>
<% f.fields_for :project do |project_form| %>
<%= project_form.label :title %>
<%= project_form.text_field :title %>
<% end %>
<%= f.text_field :credit_card_number %>
...
<% end %>
Le contrôleur paiements est à peu près standard:
class PaymentsController < ApplicationController
before_filter :load_project
# GET /payments/new
# GET /payments/new.xml
def new
@payment = @project.payments.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @payment }
end
end
# POST /payments
# POST /payments.xml
def create
@payment = @project.payments.build(params[:payment])
respond_to do |format|
if @payment.save
flash[:notice] = 'Payment was successfully created.'
format.html { redirect_to([@project, @payment]) }
format.xml { render :xml => @payment, :status => :created, :location => @payment }
else
format.html { render :action => "new" }
format.xml { render :xml => @payment.errors, :status => :unprocessable_entity }
end
end
end
private
def load_project
@project = Project.find(params[:project_id])
end
end
Ce que je trouve est que sur le nouveau formulaire de paiement, je suis de se retrouver avec quelque chose comme ceci:
<input id="payment_project_attributes_title" name="payment[project_attributes][title]" size="30" type="text" />
<input id="payment_project_attributes_id" name="payment[project_attributes][id]" type="hidden" value="56" />
(Notez le #payment_project_attributes_id automatiquement créé)
Lorsque le formulaire est soumis, rails reçoit cela comme si (gardez à l'esprit que le projet n ° 56 existe déjà):
"payment"=>{"project_attributes"=>{"title"=>"test title", "id"=>"56"}, "credit_card_number"=>"41111111111111111"}
Et voici le problème: quand cela est géré par le contrôleur, il n'a pas appliquer l'attribut title au projet de paiement.
Ce qui est étrange, c'est que si je supprime ce "id" => "56", le titre du projet est mis à jour. Voici un exemple en utilisant la console:
ruby-1.8.7-p249 > Project.find(56)
=> #<Project id: 56, title: nil, created_at: "2010-06-18 15:58:25", updated_at: "2010-06-18 16:01:37">
ruby-1.8.7-p249 > p=Project.find(56).payments.new({"project_attributes"=>{"title"=>"my new title", "id"=>"56"}})
=> #<Payment id: nil, project_id: 56, created_at: nil, updated_at: nil>
ruby-1.8.7-p249 > p.project
=> #<Project id: 56, title: nil, created_at: "2010-06-18 15:58:25", updated_at: "2010-06-18 16:01:37">
ruby-1.8.7-p249 > p=Project.find(56).payments.new({"project_attributes"=>{"title"=>"test title"}})
=> #<Payment id: nil, project_id: 56, created_at: nil, updated_at: nil>
ruby-1.8.7-p249 > p.project
=> #<Project id: nil, user_id: nil, title: "test title", created_at: nil, updated_at: nil>
(Notez que le second payments.new, sans l'identification, les causes p.project.title à être mis à jour)
Cela semble en contradiction directe avec ce billet: https://rails.lighthouseapp.com/projects/8994/tickets/3687-nested-attributes-with-belongs_to-only-supports-one-use-case
Quelqu'un a-t-il des idées?
Je dois noter que ce que j'essaie vraiment de faire est une couche plus complexe - j'essaie de mettre à jour user_attributes pour Project (en utilisant un belongs_to: utilisateur/accept_nested_attributes_for: utilisateur sur le projet) mais je suis sorte d'espérer que ce sera travailler si je peux comprendre cela.
Aussi, je pense que votre formulaire pour devrait être juste pour le paiement <% form_for @payment do | f | %> et alors vos champs pour ça devrait aller. – Mike