Ich habe ein Modell mit einem Attribut, das ein Array ist. Wie kann ich dieses Attribut aus einer Formularübergabe ausfüllen?
Ich weiß, dass eine Formulareingabe mit einem Feld, dessen Name Klammern enthält, einen Hash aus der Eingabe erstellt. Soll ich das einfach nehmen und im Controller durchgehen, um es in ein Array zu massieren?
Beispiel, um es weniger abstrakt zu machen:
class Article
serialize :links, Array
end
Die Links-Variable nimmt die Form eines Arrays von URLs an, d. H. [["http://www.google.com"], ["http://stackoverflow.com"]]
Wenn ich in meinem Formular so etwas wie das Folgende verwende, wird ein Hash erstellt:
<%= hidden_field_tag "article[links][#{url}]", :track, :value => nil %>
Der resultierende Hash sieht folgendermaßen aus:
"links" => {"http://www.google.com" => "", "http://stackoverflow.com" => ""}
Wenn ich die URL nicht in den Namen des Links einfüge, blockieren sich zusätzliche Werte:
<%= hidden_field_tag "article[links]", :track, :value => url %>
Das Ergebnis sieht so aus: "links" => "http://stackoverflow.com"
Wenn Ihr HTML-Formular Eingabefelder mit leeren eckigen Klammern enthält, werden diese zu einem Array innerhalb von Parametern im Controller.
# Eg multiple input fields all with the same name:
<input type="textbox" name="course[track_codes][]" ...>
# will become the Array
params["course"]["track_codes"]
# with an element for each of the input fields with the same name
Hinzugefügt:
Beachten Sie, dass die Rails-Helfer not setup sind, um den Array-Trick automatisch und automatisch auszuführen. Sie müssen möglicherweise die Attribute name manuell erstellen. Für Kontrollkästchen gelten außerdem eigene Probleme, wenn Sie die Rails-Helfer verwenden, da die Kontrollkästchen-Helfer zusätzliche ausgeblendete Felder erstellen, um den ungeprüften Fall zu behandeln.
= simple_form_for @article do |f|
= f.input_field :name, multiple: true
= f.input_field :name, multiple: true
= f.submit
TL; DR Version der HTML []
-Konvention:
<input type="textbox" name="course[track_codes][]", value="a">
<input type="textbox" name="course[track_codes][]", value="b">
<input type="textbox" name="course[track_codes][]", value="c">
Params erhalten:
{ course: { track_codes: ['a', 'b', 'c'] } }
<input type="textbox" name="course[track_codes][x]", value="a">
<input type="textbox" name="course[track_codes][y]", value="b">
<input type="textbox" name="course[track_codes][z]", value="c">
Params erhalten:
{ course: { track_codes: { x: 'a', y: 'b', z: 'c' } }
Ich habe auch herausgefunden, dass, wenn Sie Ihre Eingabehilfe so übergeben, Sie eine Reihe von Kursen mit jeweils eigenen Attributen erhalten.
# Eg multiple input fields all with the same name:
<input type="textbox" name="course[][track_codes]" ...>
# will become the Array
params["course"]
# where you can get the values of all your attributes like this:
params["course"].each do |course|
course["track_codes"]
end
Ich habe gerade eine Lösung mit Jquery Taginput eingerichtet:
http://xoxco.com/projects/code/tagsinput/
Ich habe eine benutzerdefinierte simple_form-Erweiterung geschrieben
# for use with: http://xoxco.com/projects/code/tagsinput/
class TagInput < SimpleForm::Inputs::Base
def input
@builder.text_field(attribute_name, input_html_options.merge(value: object.value.join(',')))
end
end
Ein Kaffeeausschnitt:
$('input.tag').tagsInput()
Und ein Tweak an meinem Controller, der leider etwas spezifisch sein muss:
@user = User.find(params[:id])
attrs = params[:user]
if @user.some_field.is_a? Array
attrs[:some_field] = attrs[:some_field].split(',')
end
Für diejenigen, die ein einfaches Formular verwenden, können Sie diese Lösung in Betracht ziehen. Grundsätzlich müssen Sie Ihre eigene Eingabe einrichten und als Array verwenden. Dann müssten Sie Eingaben in Ihrer Controller-Ebene erledigen.
#inside lib/utitilies
class ArrayInput < SimpleForm::Inputs::Base
def input
@builder.text_field(attribute_name, input_html_options.merge!({value: object.premium_keyword.join(',')}))
end
end
#inside view/_form
...
= f.input :premium_keyword, as: :array, label: 'Premium Keyword (case insensitive, comma seperated)'
#inside controller
def update
pkw = params[:restaurant][:premium_keyword]
if pkw.present?
pkw = pkw.split(", ")
params[:restaurant][:premium_keyword] = pkw
end
if @restaurant.update_attributes(params[:restaurant])
redirect_to admin_city_restaurants_path, flash: { success: "You have successfully edited a restaurant"}
else
render :edit
end
end
In Ihrem Fall ändern Sie einfach: premium_keyword in Ihr Array-Feld