Ruby on Rails: Senden eines Arrays in einem Formular




ruby array reduce (5)

TL; DR- Version von 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 erhielt:

{ 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 erhielt:

{ course: { track_codes: { x: 'a', y: 'b', z: 'c' } }

Ich habe ein Modell mit einem Attribut, das ein Array ist. Was ist der richtige Weg für mich, dieses Attribut aus einer Formularübergabe herauszufüllen?

Ich weiß, dass eine Formulareingabe mit einem Feld, dessen Name Klammern enthält, einen Hash von der Eingabe erzeugt. Soll ich das einfach nehmen und im Controller durchgehen, um es in ein Array zu mahlen?

Beispiel, um es weniger abstrakt zu machen:

class Article
  serialize :links, Array
end

Die Linkvariable hat die Form eines Arrays von URLs, dh [["http://www.google.com"], ["http://stackoverflow.com"]]

Wenn ich etwas wie das Folgende in meiner Form verwende, erzeugt es einen Hash:

<%= 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 im Namen des Links angeben, verstopfen sich die zusätzlichen Werte gegenseitig:

<%= hidden_field_tag "article[links]", :track, :value => url %>

Das Ergebnis sieht folgendermaßen aus: "links" => "http://stackoverflow.com"


Answer #1

Wenn Ihr HTML-Formular Eingabefelder mit leeren eckigen Klammern hat, werden diese zu einem Array innerhalb von Parametern im Controller umgewandelt.

# 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 nicht dazu eingerichtet sind, den Array-Trick automatisch auszuführen. Daher müssen Sie die Namensattribute möglicherweise manuell erstellen. Außerdem haben Checkboxen ihre eigenen Probleme, wenn sie die Rails-Helfer verwenden, da die Checkbox-Helfer zusätzliche versteckte Felder erstellen, um den unmarkierten Fall zu behandeln.


Answer #2

Für diejenigen, die einfache Form verwenden, können Sie diese Lösung in Betracht ziehen. Im Grunde müssen Sie Ihre eigene Eingabe einrichten und sie als Array verwenden. Dann müssten Sie Eingaben in Ihrer Controller-Ebene behandeln.

#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


Answer #3

Ich habe auch herausgefunden, dass wenn Sie Ihren Eingabe-Helfer wie folgt übergeben, Sie eine Reihe von Kursen bekommen werden, jedes mit seinen eigenen Attributen.

# 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    

Answer #4

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 Kaffee-Schnipsel:

$('input.tag').tagsInput()

Und eine Änderung an meinem Controller, die 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






hash