0

Ich baue eine Rails-App für eine Wettkampf-Bestenliste. Das Datenmodell istRails senden mehrere verschachtelte Formulare mit einer Senden-Schaltfläche

class Tournament 
    has_many :events 
end 

class User 
    has_many :entries 
    has_many :events, through: :entries 
end 

class Events 
    has_many :entries 
    belongs_to :tournament 
end 

class Entry 
    belongs_to :user 
    belongs_to :event 
end 

Jedes Turnier hat 2 Ereignisse und ein Benutzer kann bis zu 4 Einträgen pro Ereignis ein, so insgesamt 8 Einträge pro Turnier. Ich möchte dem Benutzer erlauben, alle 8 Einträge in einem Formular mit einer Übermittlungsschaltfläche einzugeben.

Meine Strecken

resources :entries, except: [:index, :show] do 
    collection do 
    match 'create_collection', via: [:create] 
    end 
end 

Ich habe auch eine create_collection Methode in der Einträge-Controller um die Einträge zu verarbeiten, obwohl ich noch nicht so weit bekommen haben. Ich bin mir nicht sicher, wie man das Formular richtig funktioniert.

_form.html.haml (die durch eine teilweise Ansichten/Turnieren/index.html.haml und übergibt die next_events Ereignisinstanzen für das Turnier.

.entry-form 
    = form_tag create_collection_entries_path do |form| 
    - next_events.each do |event| 
     = event.name 
     = fields_for "events[]", event do |f| 
     - 4.times do 
      = f.fields_for :entries do |f| 
      = f.label_tag 'player' 
      = f.text_field 'player' 

    = submit_tag "Submit", class: "btn btn-success" 

Die Form zeigt, wie I die 2 wiedergegeben ist, erwarten, aber wenn ich die einreichen klicken nur die letzten vier Einträge in dem params vorgelegt und die Ereignis-ID nicht wird übergeben

"events"=>[{"entries_attributes"=> 
    {"0"=>{"player"=>"player5","id"=>"33"}, 
    "1"=>{"player"=>"player6", "id"=>"34"}, 
    "2"=>{"player"=>"player7", "id"=>"35"}, 
    "3"=>{"player"=>"player8", "id"=>"36"}}}], 
"commit"=>"Submit"} 

Wie werde ich alle Eingabeparameter für beiden Veranstaltungen mit dem richtigen vorgelegt werden Ereignis-ID?

Antwort

1

Meine Forschung zeigt, dass Rails keine Möglichkeit bietet, mehrere Instanzen eines Modells in einem Formular mit einem Submit einzureichen. Ich schaute auf this und this, die für mich nicht ganz funktionierte. Also habe ich mein eigenes gerollt.

Das Formular, um alle Werte im params-Hash auf eine ziemlich überschaubare Weise zu übergeben. Es ist nicht die eleganteste Lösung und erfordert ein gutes Stück Verarbeitung im Backend. Aber ich kann keinen Weg finden, dies auf eine rassistischere Weise zu tun.

form.html.haml

.entry-form.on 
    = form_tag create_collection_entries_path(@user.id) do 
    - Tournament.next.events.each do |event| 
     %div= event.name 
     %div 
     - @num_of_entry_forms.times do |n| 
      %div 
      = label_tag 'player' 
      = text_field_tag "event[#{event.id}][entries][player_#{n}]" 

    = submit_tag "Submit", class: "btn btn-success" 

routes.rb

resources :entries, except: [:index, :show] do 
    collection do 
    get '/new_collection/:user_id', to: 'entries#new_collection', as: 'new_collection' 
    post '/create_collection/:user_id', to: 'entries#create_collection', as: 'create_collection' 
    end 
end 

entries_controller.rb

def new_collection 
    @num_of_entry_forms = EventEntryCollectionCreator::MAX_ENTRIES_PER_EVENT 
    @user = User.find(params[:user_id]) 
end 

def create_collection 
    @eec = EventEntryCollection.new(params) 
    if @eec.save 
    redirect_to root_path 
    else 
    render :new_collection 
    end 
end 

Ich arbeite immer noch auf dem EventEntryCollectionCreator, die ein Service-Modell ist, aber hier ist der Kern davon.

Wie gesagt, das ist nicht die eleganteste Lösung, aber es löst das Problem. Die guten Punkte sind, dass die unordentliche Backend-Verarbeitung aus dem Controller in sein eigenes Servicemodell abstrahiert wird. Die negativen Aspekte sind, dass es einige Code-Gerüche gibt, viele Werte in Hashes und Objekte, die zu viel über die Hash-Struktur wissen müssen.

Ich bin offen für andere Lösungen oder Verbesserungen an dieser Arbeit im Gange.

Verwandte Themen