13

配列フィールドを持つMongoidモデルのフォームを作成するのに苦労してきました。配列のエントリごとにフォームにテキストボックスを配置したいと思います。新しいレコードを作成する場合、デフォルトは1つの空のフィールド(およびページに新しいフィールドを動的に追加するためのJavaScript)になります。

fields_forを使用して解決策を探しましたが、文字列の配列である私が持っている場合ではなく、オブジェクト/モデルの配列がある場合を処理することを目的としているようです。

人と電話番号の例を使用します。

class Person
  include Mongoid::Document
  field :name, :type => String
  field :phone_numbers, :type => Array
end

コントローラーについては、一般的なコントローラーを想定していますが、このnew方法では、phone_number配列を1つの空白の文字列で初期化しました。

フォームコードは次のとおりです。

  <%= 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 %>

これはすべて正常に機能します。気に入らないことがいくつかあります。

  • text_field_tag呼び出しのフィールドのハードコードされた名前。
  • f.text_fieldの代わりにtext_field_tagを使用する
  • どういうわけかこれの代わりにfields_forを使うべきだと感じている

誰かがこれを実装する方法についてもっと良い提案がありますか?それともこれは正しいと思いますか?

4

4 に答える 4

8

私はあなたの懸念に同意します -

  1. text_field_tag呼び出しのフィールドのハードコーディングされた名前。

  2. 代わりに text_field_tag を使用するf.text_field

  3. 使用してfields_for

いくつかの調査を行った後、最初の 2 つの懸念は解決でき、おそらく 3 番目の懸念も解決できることがわかりましたが、まだ試していません。

 <%= 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%>

別のクリーンなアプローチは、フォームビルダーで text_field を定義してから、-

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

詳細はこちら

于 2012-01-19T19:02:00.447 に答える
3

あなたは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

そして、ビュー内で次を使用できます。

<%= 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 %>
于 2011-06-14T06:06:41.557 に答える
1

モッシュが自分のソリューションへのコメントに投稿したコメントによると:

fields_for を使用するときはいつでも、属性のアクセサと new_record? のような他のメソッドを持つオブジェクトが必要です。基本的に、オブジェクトは ActiveModel インターフェイスを実装する必要があります。

私の質問への答えは、モッシュが提案したように、電話番号用の別のモデルを作成しない限り、より良い方法はないということです。

于 2011-06-17T08:48:59.063 に答える
0

2番目のdivは次のようになります

<div class="field"><%= f.fields_for :phone_numbers do | phone | %>
 <%= phone.text_field "phone_numer[]" %><% end %></div>
于 2012-11-28T09:23:41.627 に答える