2017-11-06 5 views
1

Ich habe Probleme mit dem Speichern von Datensätzen aus einer has_many :through Zuordnung. Ich muss etwas Wichtiges verpasst haben.Rails 5.1.4 - Wie erstelle ich Datensätze aus Multi-select mit einer has_many: through-Beziehung?

Das Wichtigste zuerst:

  • Rails-Version: 5.1.4
  • Ruby-Version: 2.4.2

ich diese drei Modelle bekam:

class Event < ApplicationRecord 
    has_many :events_timeslots 
    has_many :timeslots, through: :events_timeslots 
end 

class Timeslot < ApplicationRecord 
    has_many :events_timeslots 
    has_many :events, through: :events_timeslots 
end 

class EventsTimeslot < ApplicationRecord 
    belongs_to :event 
    belongs_to :timeslot 
end 

Nach Jedes Ereignis hat viele Zeitfenster und jedes Zeitfenster hat viele Ereignisse.

Ich möchte ein Mehr wählen aus meiner Sicht:

<%= form_with(model: event, local: true) do |form| %> 
    ... 
    <% fields_for :events_timeslots do |events_timeslots| %> 
    <%= events_timeslots.label :timeslots %> 
    <%= events_timeslots.select(:timeslots, @timeslots.collect {|t| [t.name, t.id]}, {}, {multiple: true}) %> 
    <% end %> 
    ... 
<% end %> 

Ist das der richtige Ansatz mehrere Zeitfenster auszuwählen, während ein neues Ereignis erstellen? Die Zeitfenster sind zu diesem Zeitpunkt bereits vorhanden. Wenn das Ereignis jedoch gespeichert wird, sollten auch die zugehörigen Datensätze in der Tabelle events_timeslots erstellt werden.

ich erlaube auch das timeslots Attribut in starken Parametern:

params.require(:event).permit(:date, timeslots: []) 

Gibt es ein magischen Rails-Way die „eingerüstete“ Controller-Aktionen nutzen, um die neue Veranstaltung sowie die dazugehörigen Datensätze in EventsTimeslot Modell erstellen ? Zu dieser Frage habe ich an answer on another question gefunden, aber ich konnte es nicht zur Arbeit bringen!

Vielleicht habe ich ein sehr dummes kleines Ding verpasst, aber trotzdem danke für die Hilfe.


bearbeiten

Die (verkorkste) events_timeslots Tabelle in schema.rb:

create_table "events_timeslots", force: :cascade do |t| 
    t.bigint "events_id" 
    t.bigint "timeslots_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.index ["events_id"], name: "index_events_timeslots_on_events_id" 
    t.index ["timeslots_id"], name: "index_events_timeslots_on_timeslots_id" 
end 

Antwort

3

Unter der Annahme, Ihre Fremdschlüssel sind der Standard: event_id undvielleicht 10 ...

Dann versuchen timeslots mit timeslot_ids im permit Methode Swapping:

params.require(:event).permit(:date, timeslot_ids: [])

Dann, anstatt die Einstellung der Attribute der Join-Tabelle in einer verschachtelten Form, aktualisieren Sie einfach die timeslot_ids auf die @event:

<%= form_with(model: event, local: true) do |form| %> 

    <%= form.select(:timeslot_ids, Timeslot.all.collect {|t| [t.name, t.id]}, {}, {multiple: true}) %> 

<% end %> 
+1

"Angenommen, Ihre Fremdschlüssel sind der Standard" - stellte sich heraus, dass sie nicht waren! Ich habe sie versehentlich 'events_id' und' timeslots_id' genannt. Jetzt funktioniert es perfekt mit 'timeslot_ids' und der angepassten Form. Danke für den wichtigen Hinweis, die fremden Schlüsselnamen zu überprüfen! :) – mabu

0

fields_for ist für, wenn Sie verschachtelte Datensätze miterstellen.

Es ist nicht erforderlich, wenn Sie einfach nur Elemente zuordnet:

<%= form_with(model: event, local: true) do |form| %> 
    <%= f.collection_select(:timeslot_ids, Timeslot.all, :id, :name, multiple: true) %> 
<% end %> 

Active schafft eine _ids Setter-Methode für has_many Assoziationen, die eine Reihe von ids nimmt. Dies funktioniert Hand in Hand mit der form helpers.

ein Array param Sie es als Schlüsselwort übergeben müssen, um die weiße Liste zu ermöglichen:

params.require(:event).permit(:foo, :bar, timeslot_ids: []) 

Mit [] erlaubt jeder skalaren Wert.

Verwandte Themen