Forme per creare e aggiornare Mongoid campi di matrice
-
27-10-2019 - |
Domanda
Ho lottato per creare un modulo per un Mongoid modello che dispone di un campo di matrice.Voglio che la mia forma sulla casella di testo per voce dell'array.Se sto creando un nuovo record, il valore predefinito sarà un campo vuoto (e un po ' di javascript per aggiungere nuovi campi in modo dinamico sulla pagina).
Ho cercato in giro per una soluzione che utilizza fields_for ma sembra più destinato a gestire il caso in cui si dispone di un array di oggetti di modelli/e non è il caso che ho, che è un array di stringhe.
Ho intenzione di utilizzare l'esempio di una persona e un numero di telefono.
class Person
include Mongoid::Document
field :name, :type => String
field :phone_numbers, :type => Array
end
Per il controller, solo assume il tipico controller, ma in new
metodo che ho inizializzato il numero telefonico array con una stringa vuota.
Ecco il codice del modulo:
<%= form_for(@person) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :phone_numbers %><br />
<% @person.phone_numbers.each do |phone_number| %>
<%= text_field_tag "person[phone_numbers][]", phone_number %>
<% end %>
</div>
<% end %>
Tutto questo funziona bene.Ci sono alcune cose che non mi piacciono.
- Il hardcoded nome del campo nella text_field_tag chiamata.
- Utilizzando text_field_tag invece di f.text_field al
- Avere la sensazione di come io debba essere in qualche modo utilizzando fields_for invece di questo
Qualcuno ha suggerimenti migliori su come implementare questo?Oppure vorresti prendere in considerazione di questo è corretto?
Soluzione
Sono d'accordo con le vostre preoccupazioni -
L'hard-coded nome del campo nella
text_field_tag
chiamata.Utilizzando text_field_tag invece di
f.text_field
utilizzando
fields_for
Dopo aver fatto qualche ricerca ha scoperto che i primi due problemi possono essere risolti e, probabilmente, anche di terzo grado, ma non ho ancora provato.
<%= form_for(@person) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :phone_numbers %><br />
<% @person.phone_numbers.each do |phone_number| %>
<%= f.text_field :phone_numbers, :name => "#{f.object_name}[phone_numbers][]"%>
<% end %>
</div>
<%end%>
Un altro approccio lineare potrebbe essere avere form builder definito text_field al e quindi di aver -
def text_field(attribute, *args)
args.last.merge!(:name => "#{object_name}[#{attribute}][]") if args.last && args.last.is_a?(Hash) && args.last.delete(:array)
super(attribute, args)
end
<% @person.phone_numbers.each do |phone_number| %>
<%= f.text_field :phone_numbers, :array => true%>
<% end %>
Altri suggerimenti
Si potrebbe lavorare con embeds_many:
class Person
include Mongoid::Document
field :name
embeds_many :phone_numbers
end
class PhoneNumber
include Mongoid::Document
field :number
embedded_in :person
end
E poi, all'interno della vostra vista, è possibile utilizzare:
<%= form_for(@person) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<%= @person.phone_numbers.each do |phone_number| %>
<%= f.fields_for phone_number do |p| %>
<div class="field">
<%= p.label :number %><br />
<%= p.text_field :number %>
</div>
<% end %>
<% end %>
<% end %>
Secondo un commento postato hanno potuto visitare la moschea in un commento a la sua soluzione:
ogni volta che si utilizza fields_for, si aspetta un oggetto con funzioni di accesso per gli attributi e alcuni altri metodi come la new_record?Fondamentalmente parlando, l'oggetto hat per implementare il ActiveModel interfaccia.
La risposta alla mia domanda è che non c'è un modo migliore meno di non creare un altro modello di telefono nubmers, come hanno potuto visitare la moschea suggerito.
Il secondo div dovrebbe essere simile al seguente
<div class="field"><%= f.fields_for :phone_numbers do | phone | %>
<%= phone.text_field "phone_numer[]" %><% end %></div>