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?

È stato utile?

Soluzione

Sono d'accordo con le vostre preoccupazioni -

  1. L'hard-coded nome del campo nella text_field_tag chiamata.

  2. Utilizzando text_field_tag invece di f.text_field

  3. 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 %>

Potete trovare ulteriori informazioni qui

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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top