0

Ich habe ein Problem mit verschachtelten Form und has_many Beziehung. Geschäftsfall: Es gibt Laboratorien und ihre Lieferanten. Lieferanten können zwischen Labors geteilt werden.Rails 4 verschachtelte Formular mit has_many, through und multiple wählen

Modelle

class Lab < ActiveRecord::Base 
    has_many :lab_suppliers 
    has_many :suppliers, through: :lab_suppliers 
    accepts_nested_attributes_for :lab_suppliers 
end 

class Supplier < ActiveRecord::Base 
    has_many :lab_suppliers 
    has_many :labs, through: :lab_suppliers 
    accepts_nested_attributes_for :lab_suppliers 
end 

class LabSupplier < ActiveRecord::Base 
    belongs_to :lab 
    belongs_to :supplier 

    accepts_nested_attributes_for :lab 
    accepts_nested_attributes_for :supplier 
end 

Formular

<%= form_for(@lab) do |f| %> 
    <div class="field"> 
    <%= f.label :code %><br> 
    <%= f.text_field :code %> 
    </div> 
    <div class="field"> 
    <%= f.label :name %><br> 
    <%= f.text_field :name %> 
    </div> 
    <div class"field"> 
    <%= fields_for :lab_suppliers do |ff| %> 
     <%= ff.label :supplier_id %><br> 
     <%= ff.collection_select :supplier_id, Supplier.all, :id, :name, {include_blank: true}, {:multiple => true, :class=>""} %> 
    <% end %> 
    </div> 
    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 

-Controller

class LabsController < ApplicationController 
    before_action :set_lab, only: [:show, :edit, :update, :destroy] 

    # GET /labs/new 
    def new 
    @lab = Lab.new 
    @lab.lab_suppliers.build 
    end 

    # POST /labs 
    # POST /labs.json 
    def create 
    #raise params.inspect 

    @lab = Lab.new(lab_params) 

    @lab_supplier = @lab.lab_suppliers.new(params[:lab_suppliers]) 
    @lab_supplier.save 
    @lab.save 


    private 

    def lab_params 
     params.require(:lab).permit(:code, :name, lab_suppliers_attributes: []) 
    end 
end 

Ergebnis der auf params inspizieren nac r Einreichung Form:

Parameter:

{"utf8"=>"✓", 
"authenticity_token"=>"...", 
"lab"=>{"code"=>"L01", 
"name"=>"xxx"}, 
"lab_suppliers"=>{"supplier_id"=>["", 
"1", 
"3"]}, 
"commit"=>"Create Lab"} 

Während Formular I erhalten ActiveModel :: ForbiddenAttributesError auf der Linie:

@lab_supplier = @lab.lab_suppliers.new(params[:lab_suppliers]) 

Was soll ich es als erwartet machen fehlt zu arbeiten?

Antwort

1

Es scheint, wie Sie explizit lab_params sagen müssen, die von lab_suppliers Sie wie passieren müssen Attribute:

es
params.require(:lab).permit(:code, :name, lab_suppliers_attributes: [:supplier_id]) 

Versuchen und mich wissen lassen.

+0

Nein, ich habe das versucht und immer noch bekomme ich den gleichen Fehler. Ich denke, Problem ist, dass lab_suppliers params sind nicht in der lab_params – Michal

+0

in hier geschachtelt: <% = fields_for: lab_suppliers tun | ff | %> versuchen Sie <% = f.fields_for: lab_suppliers do | ff | %> so, setzen Sie die f – loloso

+0

Sie hatten Recht. Durch den Wechsel zu f.fields_for wurden die lab_suppliers so konfiguriert, dass Werte innerhalb von lab_params verschachtelt werden – Michal

0

Verbindung zu anderen Posten, die mir geholfen, die Arbeitslösung zu finden: [Rails nested form with multiple entries

Im Folgenden werde ich die Arbeitslösung bieten die zeigt, wie Werte aus dem mehrere passieren, wie verschachtelte Attribute auswählen und sie in den db einfügen.

Modelle

class Lab < ActiveRecord::Base 
    has_many :lab_suppliers#, :foreign_key => 'lab_id', dependent: :destroy 
    has_many :suppliers, through: :lab_suppliers 
    accepts_nested_attributes_for :lab_suppliers, :allow_destroy => true 
end 

class Supplier < ActiveRecord::Base 
    has_many :lab_suppliers 
    has_many :labs, through: :lab_suppliers 
end 

class LabSupplier < ActiveRecord::Base 
    belongs_to :lab 
    belongs_to :supplier 
end 

Kommentar: accepts_nested_attributes_for nur auf has_many/has_one Seite gestellt wird. Keine Notwendigkeit, legt es auf belongs_to Seite

Formular (Lab)

<%= form_for(@lab) do |f| %> 
    <div class="field"> 
    <%= f.label :code %><br> 
    <%= f.text_field :code %> 
    </div> 
    <div class="field"> 
    <%= f.label :name %><br> 
    <%= f.text_field :name %> 
    </div> 
    <div class"field"> 
<%= f.fields_for :lab_suppliers do |ff| %> 
    <%= ff.label :supplier_id %><br> 
    <%= ff.collection_select :supplier_id, Supplier.all, :id, :name, {include_blank: true}, {:multiple => true, :class=>""} %> 
<% end %> 

<% = f.Eintragen%> <% end%>

-Controller

Kommentar: Es müssen keine zusätzlichen params beim Lieferant oder lab_suppliers Controller

class LabsController < ApplicationController 
    before_action :set_lab, only: [:show, :edit, :update, :destroy] 

def new 
    @lab = Lab.new 
    @lab.lab_suppliers.build 
end 


def create 
    @lab = Lab.new(lab_params) 

@startcount=1 #start counting from 1 because the first element in the array of nested params is always null 
@lab.lab_suppliers.each do |m| 
    #raise lab_params[:lab_suppliers_attributes]["0"][:supplier_id][@startcount].inspect 
    m.supplier_id = lab_params[:lab_suppliers_attributes]["0"][:supplier_id][@startcount] 
    @startcount +=1 
end 

respond_to do |format| 
    if @lab.save 
    lab_params[:lab_suppliers_attributes]["0"][:supplier_id].drop(@startcount).each do |m| 
     @lab.lab_suppliers.build(:supplier_id => lab_params[:lab_suppliers_attributes]["0"][:supplier_id][@startcount]).save 
     @startcount += 1 
    end 
    format.html { redirect_to labs_path, notice: 'Lab was successfully created.' } 
    format.json { render :show, status: :created, location: @lab } 
    else 
    format.html { render :new } 
    format.json { render json: @lab.errors, status: :unprocessable_entity } 
    end 
end 
end 


    private 

def lab_params 
    params.require(:lab).permit(:name, :code, lab_suppliers_attributes: [supplier_id: [] ]) 
end 
end 

Kommentar ermöglichen: SUPPLIER_ID: [] in Die lab_suppliers_attributes erlaubt Array von Werten aus dem Multi-Drop-down zu übergeben

Verwandte Themen