Rails: fields_for with index?

2019-01-04 21:34发布

Is there a method (or way to pull off similar functionality) to do a fields_for_with_index?

Example:

<% f.fields_for_with_index :questions do |builder, index| %>  
  <%= render 'some_form', :f => builder, :i => index %>
<% end %>

That partial being rendered needs to know what the current index is in the fields_for loop.

8条回答
该账号已被封号
2楼-- · 2019-01-04 22:17

Checkout Rendering a collection of partials. If your requirement is that a template needs to iterate over an array and render a sub template for each of the elements.

<%= f.fields_for @parent.children do |children_form| %>
  <%= render :partial => 'children', :collection => @parent.children, 
      :locals => { :f => children_form } %>
<% end %>

This will render “_children.erb“ and pass the local variable 'children' to the template for display. An iteration counter will automatically be made available to the template with a name of the form partial_name_counter. In the case of the example above, the template would be fed children_counter.

Hope this helps.

查看更多
贪生不怕死
3楼-- · 2019-01-04 22:19

If you want to have control over the indexes check out the index option

<%= f.fields_for :other_things_attributes, @thing.other_things.build do |ff| %>
  <%= ff.select :days, ['Mon', 'Tues', 'Wed'], index: 2 %>
  <%= ff.hidden_field :special_attribute, 24, index: "boi" %>
<%= end =>

This will produce

<select name="thing[other_things_attributes][2][days]" id="thing_other_things_attributes_7_days">
  <option value="Mon">Mon</option>
  <option value="Tues">Tues</option>
  <option value="Wed">Wed</option>
</select>
<input type="hidden" value="24" name="thing[other_things_attributes][boi][special_attribute]" id="thing_other_things_attributes_boi_special_attribute">

If the form is submitted, params will include something like

{
  "thing" => {
  "other_things_attributes" => {
    "2" => {
      "days" => "Mon"
    },
    "boi" => {
      "special_attribute" => "24"
    }
  }
}

I had to use the index option to get my multi-dropdowns to work. Good luck.

查看更多
看我几分像从前
4楼-- · 2019-01-04 22:21

I can't see a decent way to do this through the ways provided by Rails, at least not in -v3.2.14

@Sheharyar Naseer makes reference to the options hash which can be used to solve the problem but not as far as I can see in the way he seems to suggest.

I did this =>

<%= f.fields_for :blog_posts, {:index => 0} do |g| %>
  <%= g.label :gallery_sets_id, "Position #{g.options[:index]}" %>
  <%= g.select :gallery_sets_id, @posts.collect  { |p| [p.title, p.id] } %>
  <%# g.options[:index] += 1  %>
<% end %>

or

<%= f.fields_for :blog_posts do |g| %>
  <%= g.label :gallery_sets_id, "Position #{g.object_name.match(/(\d+)]/)[1]}" %>
  <%= g.select :gallery_sets_id, @posts.collect  { |p| [p.title, p.id] } %>
<% end %>

In my case g.object_name returns a string like this "gallery_set[blog_posts_attributes][2]" for the third field rendered so I just match the index in that string and use it.


Actually a cooler (and maybe cleaner?) way to do it is to pass a lambda and call it to increment.

# /controller.rb
index = 0
@incrementer = -> { index += 1}

And the in the view

<%= f.fields_for :blog_posts do |g| %>
  <%= g.label :gallery_sets_id, "Position #{@incrementer.call}" %>
  <%= g.select :gallery_sets_id, @posts.collect  { |p| [p.title, p.id] } %>
<% end %>
查看更多
冷血范
5楼-- · 2019-01-04 22:25

This would actually be a better approach, following Rails documentation more closely:

<% @questions.each.with_index do |question,index| %>
    <% f.fields_for :questions, question do |fq| %>  
        # here you have both the 'question' object and the current 'index'
    <% end %>
<% end %>

From: http://railsapi.com/doc/rails-v3.0.4/classes/ActionView/Helpers/FormHelper.html#M006456

It’s also possible to specify the instance to be used:

  <%= form_for @person do |person_form| %>
    ...
    <% @person.projects.each do |project| %>
      <% if project.active? %>
        <%= person_form.fields_for :projects, project do |project_fields| %>
          Name: <%= project_fields.text_field :name %>
        <% end %>
      <% end %>
    <% end %>
  <% end %>
查看更多
唯我独甜
6楼-- · 2019-01-04 22:27

As of Rails 4.0.2, an index is now included in the FormBuilder object:

http://apidock.com/rails/v4.0.2/ActionView/Helpers/FormHelper/fields_for

For example:

<%= form_for @person do |person_form| %>
  ...
  <%= person_form.fields_for :projects do |project_fields| %>
    Project #<%= project_fields.index %>
  ...
  <% end %>
  ...
<% end %>
查看更多
The star\"
7楼-- · 2019-01-04 22:28

I know that this is a bit late but I recently had to do this you can get the index of the fields_for like this

<% f.fields_for :questions do |builder| %>
  <%= render 'some_form', :f => builder, :i => builder.options[:child_index] %>
<% end %>

I hope that this helps :)

查看更多
登录 后发表回答