Forms to create and update Mongoid array fields
我一直在努力为具有数组字段的Mongoid模型创建表单。我希望我的表单在数组中每个条目的文本框上都有。如果我要创建新记录,则默认值为一个空字段(以及一些可在页面上动态添加新字段的JavaScript)。
我一直在寻找使用fields_for的解决方案,但似乎更适合处理您拥有对象/模型数组的情况,而不是我拥有字符串数组的情况。
我将以一个人和一个电话号码为例。
1 2 3 4 5 | class Person include Mongoid::Document field :name, :type => String field :phone_numbers, :type => Array end |
对于控制器,仅假设是典型的控制器,但是在
这是表格代码:
1 2 3 4 5 6 7 8 9 10 11 12 | <%= form_for(@person) do |f| %> <%= f.label :name %><br /> <%= f.text_field :name %> <%= f.label :phone_numbers %><br /> <% @person.phone_numbers.each do |phone_number| %> <%= text_field_tag"person[phone_numbers][]", phone_number %> <% end %> <% end %> |
一切正常。有些事情我不喜欢。
- text_field_tag调用中字段的硬编码名称。
- 使用text_field_tag代替f.text_field
- 感觉像我应该以某种方式使用fields_for代替这个
有人对如何实施此方法有更好的建议吗?还是您认为这是正确的?
我同意您的担忧-
使用text_field_tag代替
使用
经过一些研究,发现前两个问题可以解决,第三个问题可以解决,但尚未尝试。
1 2 3 4 5 6 7 8 9 10 11 12 | <%= form_for(@person) do |f| %> <%= f.label :name %><br /> <%= f.text_field :name %> <%= f.label :phone_numbers %><br /> <% @person.phone_numbers.each do |phone_number| %> <%= f.text_field :phone_numbers, :name =>"#{f.object_name}[phone_numbers][]"%> <% end %> <%end%> |
另一种干净的方法是让表单构建器定义text_field,然后使-
1 2 3 4 5 6 7 8 | 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 %> |
您可以在此处找到更多信息
您可以使用embeds_many:
1 2 3 4 5 6 7 8 9 10 11 | class Person include Mongoid::Document field :name embeds_many :phone_numbers end class PhoneNumber include Mongoid::Document field :number embedded_in :person end |
然后,在您的视图中,您可以使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <%= form_for(@person) do |f| %> <%= f.label :name %><br /> <%= f.text_field :name %> <%= @person.phone_numbers.each do |phone_number| %> <%= f.fields_for phone_number do |p| %> <%= p.label :number %><br /> <%= p.text_field :number %> <% end %> <% end %> <% end %> |
根据评论,mosch在对自己的解决方案的评论中发表了文章:
whenever you use fields_for, it expects an object with accessors for the attributes and some other methods like new_record? Basically speaking, the object hat to implement the ActiveModel interface.
我的问题的答案是,除非像mosch建议的那样为电话数字用户创建另一个模型,否则没有更好的方法。
第二个div应该类似于以下
1 2 | <%= f.fields_for :phone_numbers do | phone | %> <%= phone.text_field"phone_numer[]" %><% end %> |