2016-10-15 3 views
1

Ich habe eine Nachricht, die Empfänger, verdrahtet diese Weise hat:Pass Array von IDs als einzelnes verborgenes Feld

class Message < ApplicationRecord 
    has_many :message_recipients 
    has_many :recipients, through: :message_recipients, source: :user 
end 

I passieren die benutzerkennungen als GET param an die neue Nachricht Form vorzunehmen PROPULATE Empfänger:

def new 
    @message = Message.new 
    @message.recipients = User.where(id: params[:user_ids]) 
end 

haben strong_params wie so ein:

def message_params 
    params.require(:message).permit(
    :subject, 
    :body, 
    recipient_ids: [] 
) 
end 

und haben die Form, wie so ein:

= simple_form_for @message do |f| 
    = f.hidden_field :recipient_ids 

ich erwartet habe all dies nur funktionieren, aber dann merkte ich, dass das versteckte Feld nicht allein als Skalar behandelt wird, so dass es von strong_params ignoriert wird (sonst hätte ich :recipient_ids statt recipient_ids: [] zu tun hat, aber dann wäre es nicht als Array sowieso enden).

So dann dachte ich über das tun dies:

= hidden_field_tag 'message[recipient_ids][]', @message.recipients.pluck(:id) 

Aber dann die Steuerung würde die params wie folgt analysieren:

message_params[:recipient_ids] => ["1, 2, 3"] 

statt:

message_params[:recipient_ids] => ["1", "2", "3"] 

So hatte ich zurück zum hässlichen:

Und dann hat alles funktioniert.

Aber ich denke, das ist alles andere als ideal, weil ich jetzt Dutzende von DOM-Elementen herumliegen habe, anstatt nur eines.

Kennen Sie einen besseren Weg, um das gleiche Ergebnis zu erzielen?

Vielleicht sollte Rails ein wenig clever sein, wenn man ein einzelnes skalares Zahlenfeld erhält, das durch Kommas getrennt ist?

Nun, was denkst du?

Rails-Version: 5.0.0

+0

Ich glaube, Sie beide Weisen entdeckt haben dieses Problem in Ihrer Frage zu nähern: 1) mit mehreren Eingängen mit [] im Namen, so dass sie als Array verarbeitet werden oder 2) Serialisierung der Daten in einer Form Eingabe, und dann unsere Serialisierung auf dem Server. Das Einreichen weniger Elemente kann den ersten Ansatz bevorzugen, während mehr Elemente den letzteren Ansatz bevorzugen können. – Puhlze

Antwort

0

Halten recipient_ids als einfaches Attribut in message_params

def message_params 
    params.require(:message).permit(
    :subject, 
    :body, 
    :recipient_ids 
) 
end 

Und dann tun message_params[:recipient_ids].split(",")

So wird es sein

"1, 2, 3".split(",") 
=> ["1", " 2", " 3"] 
+0

Wo würdest du diesen Code platzieren? Dann müsste ich daran denken, dies sowohl in 'create' als auch' update' Aktionen zu nennen. Sie sehen meinen Punkt, es beginnt den Controller der unnötigen Logik zu verwirren, meinst du nicht? –

+0

Ich würde dies in Ihrem model.rb tun. Erstellen Sie einen neuen Setter, der einen kommagetrennten Wert akzeptiert und in ein Array konvertiert. Konvertieren Sie den Wert in Ihrem Formular einfach in Komma getrennt – Kosmonaut

0

Ihr Modell.rb

message_params=(val) 
    if val.class==String #if we pass a string 
    super(val.split(',')) #split back into array and assign value 
    else 
    super(val) 
    end 
end 

und dann in Ihrem Formular-Builder (vorausgesetzt Simple)

f.input :message_params, 
    as: :hidden, 
    input_html { 
    value: @yourmodel.message_params.join(',') #split array back into comma separated string 
    } 

und