2013-10-07 11 views
6

Ich habe eine frühere Frage zu diesem Thema und wurde empfohlen, viele relevante Informationen zu lesen. Ich habe es gelesen und versucht, etwa 30 verschiedene Lösungen zu implementieren. Keine von denen hat für mich gearbeitet.Absolut fest stecken zu versuchen, verschachtelte Assoziation in Schienen Form mit has_many durch

Hier ist, was ich habe.

Ich habe ein Miniatures-Modell. Ich habe ein Hersteller-Modell. Miniaturen haben viele Hersteller durch ein Productions-Modell.

Die Assoziationen scheinen korrekt eingerichtet zu sein, da ich sie in meinen Ansichten anzeigen und über die Konsole erstellen kann. Wo ich ein Problem habe, besteht darin, die Miniaturen NEW und EDIT Ansichten erstellen zu lassen und auf die Productions-Tabelle zu aktualisieren.

In der Konsole funktioniert der Befehl @miniature.productions.create(manufacturer_id: 1), was mich zu der Annahme führt, dass ich in der Lage sein sollte, das Gleiche in einer Form zu tun.

Ich denke, mein Problem ist immer in der Miniaturen-Controller und speziell die CREATE-Funktion. Ich habe dort eine Menge anderer Lösungen ausprobiert und keiner hat es geschafft. Es ist auch möglich, dass mein field_for Zeug in meiner Form falsch ist, aber das scheint weniger fummelig.

Ich bin seit Tagen auf diesem fest und während es andere Dinge gibt, an denen ich arbeiten könnte, wenn diese Verbindung nicht möglich ist, dann müsste ich meine gesamte Anwendung überdenken.

Das Formular erstellt nun eine Zeile in der Productions-Tabelle, enthält jedoch nicht alle wichtigen Hersteller-IDs.

Jede Hilfe sehr geschätzt.

My New Miniatur-Form

<% provide(:title, 'Add miniature') %> 
<h1>Add a miniature</h1> 

<div class="row"> 
    <div class="span6 offset3"> 
    <%= form_for(@miniature) do |f| %> 
     <%= render 'shared/error_messages', object: f.object %> 
     <%= f.label :name %> 
     <%= f.text_field :name %> 
     <%= f.fields_for :production do |production_fields| %> 
     <%= production_fields.label :manufacturer_id, "Manufacturer" %> 
     <%= production_fields.select :manufacturer_id, options_from_collection_for_select(Manufacturer.all, :id, :name) %> 
     <% end %> 
     <%= f.label :release_date %> 
     <%= f.date_select :release_date, :start_year => Date.current.year, :end_year => 1970, :include_blank => true %> 

     <%= f.submit "Add miniature", class: "btn btn-large btn-primary" %> 
    <% end %> 
    </div> 
</div> 

Miniatures Controller

class MiniaturesController < ApplicationController 
    before_action :signed_in_user, only: [:new, :create, :edit, :update] 
    before_action :admin_user,  only: :destroy 

    def productions 
    @production = @miniature.productions 
    end 

    def show 
    @miniature = Miniature.find(params[:id]) 
    end 

    def new 
    @miniature = Miniature.new 
    end 

    def edit 
    @miniature = Miniature.find(params[:id]) 
    end 

    def update 
    @miniature = Miniature.find(params[:id]) 
    if @miniature.update_attributes(miniature_params) 
     flash[:success] = "Miniature updated" 
     redirect_to @miniature 
    else 
     render 'edit' 
    end 
    end 
    def index 
    @miniatures = Miniature.paginate(page: params[:page]) 
    end 

    def create 
    @miniature = Miniature.new(miniature_params) 
    if @miniature.save 
     @production = @miniature.productions.create 
     redirect_to @miniature 
    else 
     render 'new' 
    end 
    end 

    def destroy 
    Miniature.find(params[:id]).destroy 
    flash[:success] = "Miniature destroyed." 
    redirect_to miniatures_url 
    end 

private 
    def miniature_params 
     params.require(:miniature).permit(:name, :release_date, :material, :scale, :production, :production_attributes) 
    end 

    def admin_user 
     redirect_to(root_url) unless current_user.admin? 
    end 

    def signed_in_user 
     unless signed_in? 
     store_location 
     redirect_to signin_url, notice: "Please sign in." 
     end 
    end 
end 

Miniatur-Modell

class Miniature < ActiveRecord::Base 
    has_many :productions, dependent: :destroy 
    has_many :manufacturers, :through => :productions 
    accepts_nested_attributes_for :productions 

    validates :name, presence: true, length: { maximum: 50 } 
    validates :material, presence: true 
    validates :scale, presence: true 
    validates_date :release_date, :allow_blank => true 

    def name=(s) 
    super s.titleize 
    end 

end 

Produktion Modell

class Production < ActiveRecord::Base 
    belongs_to :miniature 
    belongs_to :manufacturer 



end 

Hersteller Modell

class Manufacturer < ActiveRecord::Base 
    has_many :productions 
    has_many :miniatures, :through => :productions 
    validates :name, presence: true, length: { maximum: 50 } 
    accepts_nested_attributes_for :productions 
end 
+1

Haben Sie nicht durch diese ausgiebig gesucht, aber Sie haben ein Problem auf Ihrer erstellen Aktion in dem die Beziehung sein wird aufbauen '@ Miniature' (mit einem großen 'm') anstelle von '@ miniature' (Kleinbuchstaben 'm' mit Ihren Instanzvariablen @miniature) ... –

+0

Ah danke, dass Sie das bemerkt haben. Ich korrigierte es und es wurde ein Fehler nach dem Motto "Kann erst nach dem Speichern des Elternteils erstellt werden" ausgegeben, also habe ich die Zeile unterhalb der Zeile "if @ miniature.save" verschoben. Jetzt wird die Zeile in der Productions-Tabelle erstellt, aber das Feld manufacturer_id wird nicht ausgefüllt. Ich war vorher schon mal hier. – Ossie

Antwort

8

Statt Aufruf:

@production = @miniature.productions.create 

Versuchen Rails' "bauen" Methode:

def new 
    @miniature = Miniature.new(miniature_params) 
    @miniature.productions.build 
end 

def create 
    @miniature = Miniature.new(miniature_params) 
    if @miniature.save 
    redirect_to @miniature 
    else 
    render 'new' 
    end 
end 

Mithilfe der Build-Methode wird die ActiveSecure-Assoziationsfunktion von ActiveRecord verwendet.

Siehe http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html

Sie müssen auch Ihre params Weise aktualisieren, zum Beispiel

def miniature_params 
    params.require(:miniature).permit(:name, :release_date, :material, :scale, productions_attributes: [:manufacturer_id]) 
end 

Auch sollte Ihre fields_for Plural sein (glaube ich) ...

<%= f.fields_for :productions do |production_fields| %> 
+0

Ja, das erlaubt mir, die Zeile über die "if @miniature save" Zeile zu verschieben, aber es funktioniert genauso. Ich bekomme eine neue Zeile in der Tabelle, aber es enthält nicht die Hersteller-ID. Es muss entweder sein, dass ich meine Form anders zusammensetzen muss oder ich muss den Controller zwingen, diesen bestimmten Parameter zu verwenden. Ooof. – Ossie

+0

Ich hatte verschiedene Kombinationen im Params-Bit ausprobiert. Dies sieht gut aus, übergibt die manufacturer_id jedoch nicht an Produktionen. Es ist sehr möglich, oder? – Ossie

+1

Können Sie anhand Ihres Protokolls feststellen, ob der Parameter übergeben wurde, aber herausgefiltert wird? Oder geht es überhaupt nicht vorbei? Tut mir leid, ich war nicht zu viel Hilfe, ich versuche verschachtelte Formulare zugunsten der Verwendung von Formularobjekten zu verwenden ... Schau dir das Muster # 3 in Form Objects an, hier: http://blog.codeclimate.com/blog/2012/10/17/7-Wege zu zersetzen-Fett-Active-Record-Modelle/ –

Verwandte Themen