Rails 3.2.1 Forma nidificata e ACCECTS_NESTED_ATTRIBUTE_FOR RESTITUZIONE :: client (XXXXX) previsto, ottenuto array (xxxxx) "

StackOverflow https://stackoverflow.com/questions/9523944

Domanda

Aiutami a capire dove sto andando male così tanto che ricevo questo messaggio quando provo a salvare il mio modulo di inserimento dati (modulo complesso) una volta inseriti tutti i dati?

Ho cinque modelli come segue:

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
.

Ho usato il seguente articolo della mia fonte di progettazione:

http://rubysource.com/complex-rails-forms-with-nested-attributes/
.

Nella mia app / controller / contract_controller.rb Ho quanto segue:

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
.

Ho messo insieme la forma complessa come segue:

- 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'
.

i campi parziali:

<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>
.

Il mio primo e il mio problema immediato è che una volta che ho inserito tutti i dati sul modulo e poi ho premuto il pulsante "Salva" ottengo quanto segue:

ACTIVERCORD :: Associazione Typemismatch in ContractScontroller # Crea. Client (#xxxxxx) previsto, ottenuto array (#xxxxxx).

L'altro problema è che se includo 'ACCECTISTS_NESTED_ATTRIBUTE_FOR: CODELINES' nel mio modello di contratto, l'attributo 'unità_alloc' scompare dalla mia forma.

Qualsiasi aiuto o orientamento sarebbe più apprezzato in queste due domande. Ho trascorso un po 'di tempo a leggere su forme complesse, ho guardato le "forme complesse" e ho letto e ho letto e ri-leggere le guide dei binari sulle associazioni e la documentazione API su ACCECTS_Nestato Metodo. Ovviamente la mia comprensione di questi concetti non è aumentata fino alla completa comprensione necessaria per risolvere questi problemi, quindi la mia chiamata per aiuto.

Aggiornamento app / controller / 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
.

Ho aggiunto il "Sollevare params [: contratto] .to_s" come prima la prima riga nella mia azione di creazione nel contratto_Controller.rb e la produzione segue:

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"}
.

Aggiornamento 1

Ho cambiato il mio contratto_controller Nuova azione per:

def new
  @contract = Contract.new
.

Costruisci l'oggetto Codelines tramite il contratto, quindi crea i codici attraverso l'oggetto Codelines

  codelines = @contract.codelines.build
  codelines.codes.build
.

Costruisci l'oggetto Clientlines attraverso il contratto, quindi crea i client attraverso l'oggetto Clientlines

  clientlines = @contract.clientlines.build
  clientlines.clients.build
end
.

Ho anche modificato il mio modello di contratto aggiungendo ACCECTS_NESTED_ATTRIBUTE_FOR: clientlines ,: Codelines e aggiungendo la linea ATTR_Accessore.

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
.

Ora ho nidificato_attribute_writer con nomi di associazione nei miei parametri, ma ora il mio errore è cambiato in:

NoMethodError in ContractsController#new

undefined method `build' for nil:NilClass
.

La domanda ora è: "È corretto avere attr_accessore a fare riferimento a tutte le associazioni?" L'altra domanda che ho è: "Devo usare un form_helper per creare record per clienti, codice e co-line?" La ragione per cui chiedo questo è che sembrerebbe che, nonostante l'azione di costruzione che abbia nel mio contratto_controller sembra che sia ancora nulla. Se la risposta è sì alla seconda domanda puoi indirizzarmi a qualche risorsa che mi guiderebbe nella costruzione di un form_helper? Sto controllando guide.

Grazie.

Aggiorna 2

Sono andato nei circoli, ho cambiato la mia nuova azione di contratti per:

def new
  @contract = Contract.new

  @contract.codes.build
  @contract.clients.build
end
.

Ho anche cambiato il mio modello di contratto per:

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
.

Infine ho rimosso la sezione a mio avviso parziale, _fields.html.haml, che pertativa per le codeline, vale a dire:

= f.fields_for :codelines do |ff| and the next four lines
.

E ora i miei parametri hanno il neccessario "clients_attributes" e "codici_attributes" e come risultato il modulo salva alle tabelle appropriate. Ho ancora alcuni problemi, vale a dire l'attributo extra in CoDeline, 'Unità_Alloc' e alcuni altri, ma le cose sembrano migliori.

È stato utile?

Soluzione 2

The first answer was a great help, but it did not get me all the way to the solution. I found a solution, that did take me through to the end at this site, debugging nested_forms.

It is the ninth bullet down where you read that if you are working with a has_many :through association then you need to base your nested_form on the join model or something close to that.

I quickly ran a test by refactoring some code here and there and I now have a workable nested form that serves up the correct params to the controller which in turns processes it correctly and my codelines table now has just one record.

Altri suggerimenti

Ok, so your problem is with the way that your forms are setup up.

Your contract model can accept nested attributes for clientlines, however, you are trying to accept nested attributes for clients, code.

In order to do this you need to setup your Contract model as follows:

class Contract < AR::Base
  has_many :clientlines
  has_many :codelines
  has_many :clients, :through => :clientlines
  has_many :codes, :through => :codelines

  accepts_nested_attributes_for :codes
  accepts_nested_attributes_for :clients
end

I think I understand your confusion here, since ClientLines is the owner of codes and clients that is the relationship that you should accept nested attributes for, but that is incorrect.

Once you use the has_many :codes, :through => :clientlines you have setup a first class association between Contract and Code, so if you want to create new codes in a contract form, then you need to say accepts_nested_attributes_for :codes in your Contract model.

Hope this helps.

So in regards to your last posting of the params, the problem is the :codes and :clients. If you had the accepts_nested_attributes_for :codes and accepts_nested_attributes_for :clients code in your Contract model, this should work just fine.

Here is the problem, in order to properly build the clients or the codes, you need to also build their parent object. So your controller should look more like this:

class ContractsController < ApplicationController
  def new
    @contract = Contract.new

    #Build the codelines object throught the contract, then build the codes through the codelines object
    codelines =  @contract.codelines.build
    codelines.build_code

    # Do the same for the clients
    clientlines = @contract.clientlines.build
    clientlines.build_client
  end

Now, if you have done this properly, instead of seeing :clients or :codes in your params, you should see :clients_attributes or :codes_attributes.

I really think that should do it.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top