web-dev-qa-db-de.com

Ruby on Rails: Senden eines Arrays in einem Formular

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"

60
William Jones

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.

83
Larry K
= simple_form_for @article do |f|
  = f.input_field :name, multiple: true
  = f.input_field :name, multiple: true
  = f.submit
45
stAndrei

TL; DR Version der HTML []-Konvention:

Array:

<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'] } }

Hash

<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' } }
38
ecoologic

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    
8
Ana Franco

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
7
Peter Ehrlich

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

0
sovanlandy