Rails 3.2.1 verschachtelte form und accepts_nested_attributes_for gibt: :Client(xxxxx) erwartet, bekam array(xxxxx)"
Bitte helfen Sie mir zu verstehen, wohin ich gehe falsch, so viel, so dass ich diese Meldung wenn ich versuche meine Daten speichern-Anmeldeformular(komplexe form), sobald ich alle Daten eingegeben haben?
Habe ich fünf Modelle wie folgt:
class Contract < AR::Base
has_many :clientlines
has_many :codelines
has_many :clients, :through => :clientlines
has_many :codes, :through => :codelines
accepts_nested_attributes_for :clientlines
end
class Clientline < AR::Base
belongs_to :contract
belongs_to :client
accepts_nested_attributes_for :contract
end
class Client < AR::Base
has_many :clientlines
has_many :contracts, :through => :clientlines
end
class Codeline < AR::Base
belongs_to :contract
belongs_to :code
units_alloc
accepts_nested_attributes_for :code
end
class Code < AR::Base
has_many :codelines
has_many :contracts, :through => :codelines
end
Benutzte ich den folgenden Artikel als mein design Quelle:
http://rubysource.com/complex-rails-forms-with-nested-attributes/
In meiner app/Controllers/contracts_controller.rb habe ich Folgendes:
def new
@contract = Contract.new
4.times { @contract.codes.build }
4.times { @contract.codelines.build }
end
def create
@contract = Contract.new(params[:contract])
if @contract.save
flash[:success] = "New Contract has been saved"
redirect_to @contract # this redirects to the contract show page
else
@title = "You have some errors"
render 'new'
end
end
.
.
.
end
Ich zusammen die komplexe form wie folgt:
- provide(:title, 'Add Contract')
%h2 New Contract
=form_for(@contract) do |f|
=render 'shared/contract_error_messages', object: f.object
=render 'fields', f: f
.actions
= f.submit "Save", class: 'save strong round'
die teilweise _fields:
<fieldset><legend>Enter Contract Details</legend>
.field
= f.label :name, "AuthNum"
%br/
= f.text_field :authnum, :size => 10, :class => "ui-state-default"
.field
= f.label :name, "Start Date"
%br/
= f.text_field :st_date, :size => 12, :class => "ui-state-default"
.field
= f.label :name, "End Date"
%br/
= f.text_field :end_date, :size => 12, :class => "ui-state-default"
</fieldset>
<fieldset><legend>Enter Client Details</legend>
= f.fields_for :clients do |ff|
.field
= ff.label :name, "First Name"
%br/
= ff.text_field :f_name, :size => 15, :class => "ui-state-default"
.field
= ff.label :name, "MI"
%br/
= ff.text_field :mi, :size => 3, :class => "ui-state-default"
.field
= ff.label :name, "Last Name"
%br/
= ff.text_field :l_name, :size => 15, :class => "ui-state-default"
.field
= ff.label :name, "Birth Date"
%br/
= ff.text_field :birth_date, :size => 12, :class => "ui-state-default"
.field
= ff.label :name, "Address1"
%br/
= ff.text_field :address1, :size => 25, :class => "ui-state-default"
.field
= ff.label :name, "Address2"
%br/
= ff.text_field :address2, :size => 25, :class => "ui-state-default"
.field
= ff.label :name, "City"
%br/
= ff.text_field :city, :size => 15, :class => "ui-state-default"
.field
= ff.label :name, "ZipCode"
%br/
= ff.text_field :zip_code, :size => 10, :class => "ui-state-default"
.field
= ff.label :name, "State"
%br/
= ff.text_field :state, :size => 15, :class => "ui-state-default"
.field
= ff.label :name, "MedicareNum"
%br/
= ff.text_field :medicarenum, :size => 20, :class => "ui-state-default"
.field
= ff.label :name, "MedicaidNum"
%br/
= ff.text_field :medicaidnum, :size => 20, :class => "ui-state-default"
.field
= ff.label :name, "MemberNum"
%br/
= ff.text_field :membernum, :size => 20, :class => "ui-state-default"
.field
= ff.label :name, "SocSerCareMgr"
%br/
= ff.text_field :socsercaremgr, :size => 20, :class => "ui-state-default"
.field
= ff.label :name, "SSCM_Ph"
%br/
= ff.text_field :sscm_ph, :size => 15, :class => "ui-state-default"
.field
= ff.label :name, "NurseCareMgr"
%br/
= ff.text_field :nursecaremgr, :size => 20, :class => "ui-state-default"
.field
= ff.label :name, "NCM_Ph"
%br/
= ff.text_field :ncm_ph, :size => 15, :class => "ui-state-default"
.field
= ff.label :name, "EmergencyContact"
%br/
= ff.text_field :emergencycontact, :size => 20, :class => "ui-state-default"
.field
= ff.label :name, "EC_Ph"
%br/
= ff.text_field :ec_ph, :size => 15, :class => "ui-state-default"
.field
= ff.label :name, "PrimaryCarePhy"
%br/
= ff.text_field :primarycarephy, :size => 20, :class => "ui-state-default"
.field
= ff.label :name, "PCPhy_Ph"
%br/
= ff.text_field :pcphy_ph, :size => 15, :class => "ui-state-default"
</fieldset>
<fieldset><legend>Enter Billing Code Details</legend>
= f.fields_for :codes do |ff|
.field
= ff.label :name, "Code Name"
%br/
= ff.text_field :code_name, :size => 15, :class => "ui-state-default"
.field
= ff.label :name, "Status"
%br/
= ff.text_field :status, :size => 10, :class => "ui-state-default"
.field
= ff.label :name, "Description"
%br/
= ff.text_field :description, :size => 25, :class => "ui-state-default"
= f.fields_for :codelines do |ff|
.field
= ff.label :name, "Units Alloc"
%br/
= ff.text_field :units_alloc, :precision => 6, :scale => 2, :size => 10, :class =>
"ui-state-default"
</fieldset>
Meine erste und unmittelbare problem ist, dass sobald ich alle Daten eingegeben haben, auf die form und drückte dann auf den button 'Speichern' erhalte ich die folgende:
ActiveRecord::Verein TypeMisMatch in ContractsController#Erstellen.
Client(#xxxxxx) erwartet, bekam Array(#xxxxxx).
Das andere problem ist, dass, wenn ich auch 'accepts_nested_attributes_for :codelines' in meinem Vertrag-Modell, die 'units_alloc" - Attribut verschwindet aus meinem Formular.
Jede Hilfe oder Anleitung wäre sehr geschätzt, die auf diese beiden Fragen. Ich habe einige Zeit damit verbracht zu Lesen, komplexe Formen, gesehen "komplexe Formen" railcasts und ich habe gelesen und wieder Lesen-Schienen-Führungen über die Verbände sowie die API-Dokumentation auf accepts_nested_attributes_for Methode. Offensichtlich ist mein Verständnis von diesen Konzepten sind noch nicht aufgegangen bis zu dem vollen Verständnis erforderlich, um diese Probleme zu lösen, daher mein Hilferuf.
Update
app/controllers/contracts_controller.rb
class ContractsController < ApplicationController
def index
@contracts = Contract.paginate(page: params[:page])
end
def show
@contract = Contract.find(params[:id])
end
def new
@contract = Contract.new
@contract.codes.build
@contract.codelines.build
@contract.clients.build
end
def create
raise params[:contract].to_s ------ **this is line #19**
@contract = Contract.new(params[:contract])
if @contract.save
flash[:success] = "New Contract has been saved"
redirect_to @contract # this redirects to the contract show page
else
@title = "You have some errors"
render 'new'
end
end
def edit
@contract = Contract.find(param[:id])
end
def update
if @contract.update_attributes(params[:contract])
flash[:success] = "Contract Profile updated"
redirect_to @contract
else
render 'edit'
end
end
end
Habe ich noch die "raise params[:Vertrag].to_s" als erste Zeile in meinem create-Aktion in der contracts_controller.rb und der Ausgang folgt:
RuntimeError in ContractsController#create
{"authnum"=>"700900", "st_date"=>"04/03/2012", "end_date"=>"06/29/2012", "clients"=>
{"f_name"=>"Lefty", "mi"=>"L", "l_name"=>"Right", "birth_date"=>"07/18/1979",
"address1"=>"54 Frosty Lane", "address2"=>"", "city"=>"Frave", "zip_code"=>"54806",
"state"=>"WI", "medicarenum"=>"789987456", "medicaidnum"=>"931579135",
"membernum"=>"890333-3", "socsercaremgr"=>"Caring Serving",
"sscm_ph"=>"1-444-444-4444", "nursecaremgr"=>"Caring Nurse",
"ncm_ph"=>"1-555-555-5555", "emergencycontact"=>"Quick Response",
"ec_ph"=>"1-666-666-6666", "primarycarephy"=>"This One", "pcphy_ph"=>"1-777-777-7777"},
"codes"=>{"code_name"=>"S-5463", "status"=>"Active", "description"=>"Transition from
sch to mkt"}, "codelines"=>{"units_alloc"=>"80.00"}}
Rails.root: /home/tom/rails_projects/tracking
Application Trace | Framework Trace | Full Trace
app/controllers/contracts_controller.rb:19:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"/i21h2vwzuDPjIrCXzYEIAg41FnMxfGdCQQggjqcZjY=",
"contract"=>{"authnum"=>"700900",
"st_date"=>"04/03/2012",
"end_date"=>"06/29/2012",
"clients"=>{"f_name"=>"Lefty",
"mi"=>"L",
"l_name"=>"Right",
"birth_date"=>"07/18/1979",
"address1"=>"54 Frosty Lane",
"address2"=>"",
"city"=>"Frave",
"zip_code"=>"54806",
"state"=>"WI",
"medicarenum"=>"789987456",
"medicaidnum"=>"931579135",
"membernum"=>"890333-3",
"socsercaremgr"=>"Caring Serving",
"sscm_ph"=>"1-444-444-4444",
"nursecaremgr"=>"Caring Nurse",
"ncm_ph"=>"1-555-555-5555",
"emergencycontact"=>"Quick Response",
"ec_ph"=>"1-666-666-6666",
"primarycarephy"=>"This One",
"pcphy_ph"=>"1-777-777-7777"},
"codes"=>{"code_name"=>"S-5463",
"status"=>"Active",
"description"=>"Transition from sch to mkt"},
"codelines"=>{"units_alloc"=>"80.00"}},
"commit"=>"Save"}
Update 1
Änderte ich meine contracts_controller neue Aktion:
def new
@contract = Contract.new
Bauen die codelines Objekt durch den Vertrag, dann bauen Sie die codes durch die codelines Objekt
codelines = @contract.codelines.build
codelines.codes.build
Bauen die clientlines Objekt durch den Vertrag, dann bauen die Kunden durch die clientlines Objekt
clientlines = @contract.clientlines.build
clientlines.clients.build
end
Ich habe auch meinen Vertrag Modells durch hinzufügen accepts_nested_attributes_for :clientlines, :codelines, sowie das hinzufügen der attr_accessor Linie.
class Contract < ActiveRecord::Base
has_many :clientlines
has_many :codelines
has_many :clients, :through => :clientlines
has_many :codes, :through => :codelines
accepts_nested_attributes_for :clients
accepts_nested_attributes_for :codes
accepts_nested_attributes_for :clientlines
accepts_nested_attributes_for :codelines
attr_accessor :codes, :clients, :clientlines, :codelines
end
Ich habe jetzt nested_attribute_writers mit Vereins-Namen, die in meinem params aber jetzt mein Fehler hat sich verändert:
NoMethodError in ContractsController#new
undefined method `build' for nil:NilClass
Nun ist die Frage, "Ist es richtig, haben attr_accessor Referenzierung für alle Vereine?"
Die andere Frage die ich habe ist, "muss ich ein form_helper erstellen Datensätze für client-code, und codeline?" Der Grund warum ich Frage ist, dass es scheint, dass trotz der build-Aktion habe ich in meiner contracts_controller es scheint, dass es immer noch null.
Wenn die Antwort ja ist auf die zweite Frage können Sie mir einige Ressourcen, die mich führen würde, die in Gebäude ein form_helper? Ich bin der überprüfung RailsGuides.
Dank.
Update 2
Habe ich schon im Kreis, wechselte ich meine contracts_controller neue Aktion:
def new
@contract = Contract.new
@contract.codes.build
@contract.clients.build
end
Ich habe auch meinen Vertrag Modell zurück zu:
class Contract < ActiveRecord::Base
has_many :clientlines
has_many :codelines
has_many :clients, :through => :clientlines
has_many :codes, :through => :codelines
accepts_nested_attributes_for :clients
accepts_nested_attributes_for :codes
attr_accessible :clients_attributes, :codes_attributes etc
end
Schließlich entfernte ich den Abschnitt in meinen Augen teilweise, _fields.html-Code.haml, betraf, zu codelines, nämlich:
= f.fields_for :codelines do |ff| and the next four lines
und jetzt ist mein params hat die nötige "clients_attributes" und "codes_attributes", und als ein Ergebnis der form speichert, um die entsprechenden Tabellen. Ich habe noch einige Fragen, nämlich die extra-Attribut in codeline, 'units_alloc' und ein paar andere, aber die Dinge werden besser Aussehen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ok, also dein problem ist mit der Art und Weise, dass Ihre Formulare setup up.
Ihre
contract
Modell annehmen kann, verschachtelte Attribute fürclientlines
jedoch versuchen Sie zu akzeptieren, verschachtelte Attribute fürclients
,code
.Um dies zu tun, müssen Sie setup Ihre
Contract
Modell wie folgt:Ich glaube, ich verstehe Ihre Verwirrung hier, da
ClientLines
ist der Besitzer descodes
undclients
das ist die Beziehung, die Sie sollten akzeptieren, verschachtelte Attribute, aber das ist falsch.Sobald Sie mit der
has_many :codes, :through => :clientlines
Sie haben die Einrichtung zu einem erste-Klasse-Verein zwischenContract
undCode
, also, wenn Sie erstellen möchten neuecodes
imcontract
form, dann müssen Sie sagenaccepts_nested_attributes_for :codes
in IhremContract
Modell.Hoffe, das hilft.
So, in Bezug auf dein letztes posting in der params-das problem ist die
:codes
und:clients
. Wenn Sie hatte dieaccepts_nested_attributes_for :codes
undaccepts_nested_attributes_for :clients
code in IhreContract
Modell, das sollte gut funktionieren.Hier ist das problem, um richtig zu bauen, die Kunden oder die codes, die Sie brauchen, um zu bauen auch Ihre parent-Objekt. Also dein controller sollte Aussehen wie dieses:
Nun, wenn Sie dies getan haben, richtig, anstatt zu sehen
:clients
oder:codes
in Ihremparams
haben, sollten Sie sehen:clients_attributes
oder:codes_attributes
.Ich glaube wirklich, das sollte es tun.
@contract.clients.build
ContractsController#create
Aktion tun Sie dies, bevor@contract = Contract.new(params[:contract])
,raise params[:contract].to_s
und speichern Sie die Ausgabe in Ihrem OP.codeline has_many :codes
, aber wenn nicht, sollte es das sein, was mein update sagt.Die erste Antwort war eine große Hilfe, aber es nicht bekommen habe mich den ganzen Weg zu der Lösung.
Ich habe eine Lösung gefunden, dass hat mich bis zum Ende auf dieser Seite, debugging nested_forms.
Es ist die neunte Kugel nach unten, wo Sie Lesen, dass, wenn Sie arbeiten mit eine has_many :through association, dann müssen Sie auf Basis Ihrer nested_form auf die join-Modell oder etwas in der Nähe, dass.
Ich schnell ein test lief durch die Umgestaltung etwas code hier und da, und ich habe jetzt eine praktikable verschachtelten form, dass bietet den richtigen Parameter an die Steuerung, die abwechselnd Prozesse richtig und mein codelines Tabelle hat nur einen Datensatz.