Ruby on Rails: przesyłanie tablicy w formie

Mam model, który ma atrybut, który jest tablicą. Jaki jest właściwy sposób na wypełnienie tego atrybutu z formularza?

Wiem, że wprowadzenie formularza z polem, którego nazwa zawiera nawiasy, tworzy hash z wejścia. Czy powinienem to wziąć i przechodzić przez kontroler, żeby wmasować go w tablicę?

Przykład, aby uczynić go mniej abstrakcyjnym:

class Article
  serialize :links, Array
end

Zmienna links ma postać tablicy adresów URL, czyli [["http://www.google.com"], ["http://stackoverflow.com"]]

Kiedy używam czegoś podobnego do poniższego w moim formularzu, tworzy to hash:

<%= hidden_field_tag "article[links][#{url}]", :track, :value => nil %>

Wynikowy hash wygląda tak:

"links" => {"http://www.google.com" => "", "http://stackoverflow.com" => ""}

Jeśli nie podam adresu url w nazwie linku, dodatkowe wartości będą się wzajemnie blokować:

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

Wynik wygląda następująco: "links" => "http://stackoverflow.com"

Author: engineersmnky, 2010-06-22

6 answers

Jeśli twój formularz html zawiera pola wejściowe z pustymi nawiasami kwadratowymi, to zostaną one zamienione w tablicę wewnątrz params w kontrolerze.

# 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

Dodany:

Zauważ, że helpery rails są, a nie ustawione, aby wykonać sztuczkę z tablicami automatycznie-magicznie. Być może będziesz musiał ręcznie utworzyć atrybuty name. Ponadto, pola wyboru mają swoje własne problemy, jeśli używasz helperów rails, ponieważ helpery te tworzą dodatkowe ukryte pola do obsługi niezaznaczonej sprawy.

 79
Author: Larry K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 03:28:51
= simple_form_for @article do |f|
  = f.input_field :name, multiple: true
  = f.input_field :name, multiple: true
  = f.submit
 43
Author: stAndrei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-30 22:11:30

TL; DR wersja HTML [] konwencja:

Tablica:

<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 otrzymane:

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

{ course: { track_codes: { x: 'a', y: 'b', z: 'c' } }
 32
Author: ecoologic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-27 00:41:16

Dowiedziałem się również, że jeśli przekażesz swój helper wejściowy w ten sposób, otrzymasz tablicę kursów, każdy z własnymi atrybutami.

# 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
Author: Ana Franco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-26 21:35:18

Właśnie skonfigurowałem rozwiązanie używając jquery taginput:

Http://xoxco.com/projects/code/tagsinput/

Napisałem niestandardowe rozszerzenie simple_form

# 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

Fragment coffeescrpt:

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

I poprawkę do mojego kontrolera, która niestety musi być nieco specyficzna:

@user = User.find(params[:id])
attrs = params[:user]

if @user.some_field.is_a? Array
  attrs[:some_field] = attrs[:some_field].split(',')
end
 7
Author: Peter Ehrlich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-07 22:49:08

Dla tych, którzy używają prostej formy, można rozważyć To rozwiązanie. Zasadniczo trzeba skonfigurować własne wejście i użyć go jako: array. Następnie musisz obsługiwać dane wejściowe na poziomie kontrolera.

#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

W Twoim przypadku wystarczy zmienić: premium_keyword na pole tablicy

 0
Author: sovanlandy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-05 04:12:43