2011-01-31 36 views
78

有沒有一種方法(或拉開類似的功能)做fields_for_with_indexRails:fields_for with index?

例子:

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

這部分被渲染需要知道當前的指數是在fields_for循環什麼。

+3

我會+一個在覈心軌道上......繼續爲這一個案例穿過。 – 2011-08-05 14:43:01

回答

81

這實際上將是一個更好的辦法,下面Rails文檔更加緊密:

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

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

它也可以指定 情況下使用:

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

我希望有一些內置到fields_for爲此,但因爲沒有你的答案救了我的一天。謝謝。 – 2012-02-01 09:27:21

+0

您也可以使用未公開的選項:fields_for上的child_index,如果您需要更多地控制渲染哪個索引,像這樣:fields_for(:projects,project,child_index:index) – 2012-02-01 09:34:54

7

結帳Rendering a collection of partials。如果您的要求是模板需要遍歷數組併爲每個元素呈現子模板。

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

這將呈現「_children.erb」並將局部變量「children」傳遞給模板以供顯示。迭代計數器將自動提供給名稱爲partial_name_counter的模板。在上面的例子中,模板將被輸入children_counter

希望這會有所幫助。

+0

這樣做時,我得到「未定義的局部變量或方法'question_comment_form_counter'」。 `question_comment_form`是我的部分名字... – Shpigford 2011-01-31 17:23:46

+0

做問題has_many:評論和你如何在你的新問題或編輯問題中建立評論,例如嘗試1.times {question.comments。建立} – 2011-01-31 18:10:13

125

答案很簡單,因爲解決方案是在Rails中提供的。您可以使用f.options params。所以,你裏面呈現_some_form.html.erb

指數可以通過訪問:

<%= f.options[:child_index] %> 

您不需要做任何事情。


更新:看來,我的回答不夠清楚......

原始的HTML文件:

<!-- Main ERB File --> 
<% f.fields_for :questions do |builder| %> 
    <%= render 'some_form', :f => builder %> 
<% end %> 

渲染子表單:

<!-- _some_form.html.erb --> 
<%= f.options[:child_index] %> 
6

我看不到一個體面的方式來通過Rails提供的方式來做到這一點,至少不是在-v3.2.14

@Sheharyar Naseer引用了可用於解決問題的選項散列,但並不像我所看到的那樣似乎暗示。

我這樣做=>

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

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

在我的情況g.object_name返回這樣"gallery_set[blog_posts_attributes][2]"的渲染,所以我只是匹配該字符串的指數第三字段中輸入字符串和用它。


其實冷卻器(也許更清潔?)的方式是通過一個lambda並將其稱爲增量。

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

而在視圖

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

導軌4+和Rails 3(下文補丁)

<%= form_for @person do |person_form| %> 
    <%= person_form.fields_for :projects do |project_fields| %> 
    <%= project_fields.index %> 
    <% end %> 
<% end %> 

對於Rails的支持3

要獲得f.index在Rails 3中工作,你需要一個猴補丁添加到您的項目初始化如果你想擁有控制這個功能添加到fields_for

# config/initializers/fields_for_index_patch.rb 

module ActionView 
    module Helpers 
    class FormBuilder 

     def index 
     @options[:index] || @options[:child_index] 
     end 

     def fields_for(record_name, record_object = nil, fields_options = {}, &block) 
     fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options? 
     fields_options[:builder] ||= options[:builder] 
     fields_options[:parent_builder] = self 
     fields_options[:namespace] = options[:namespace] 

     case record_name 
      when String, Symbol 
      if nested_attributes_association?(record_name) 
       return fields_for_with_nested_attributes(record_name, record_object, fields_options, block) 
      end 
      else 
      record_object = record_name.is_a?(Array) ? record_name.last : record_name 
      record_name = ActiveModel::Naming.param_key(record_object) 
     end 

     index = if options.has_key?(:index) 
        options[:index] 
       elsif defined?(@auto_index) 
        self.object_name = @object_name.to_s.sub(/\[\]$/,"") 
        @auto_index 
       end 

     record_name = index ? "#{object_name}[#{index}][#{record_name}]" : "#{object_name}[#{record_name}]" 
     fields_options[:child_index] = index 

     @template.fields_for(record_name, record_object, fields_options, &block) 
     end 

     def fields_for_with_nested_attributes(association_name, association, options, block) 
     name = "#{object_name}[#{association_name}_attributes]" 
     association = convert_to_model(association) 

     if association.respond_to?(:persisted?) 
      association = [association] if @object.send(association_name).is_a?(Array) 
     elsif !association.respond_to?(:to_ary) 
      association = @object.send(association_name) 
     end 

     if association.respond_to?(:to_ary) 
      explicit_child_index = options[:child_index] 
      output = ActiveSupport::SafeBuffer.new 
      association.each do |child| 
      options[:child_index] = nested_child_index(name) unless explicit_child_index 
      output << fields_for_nested_model("#{name}[#{options[:child_index]}]", child, options, block) 
      end 
      output 
     elsif association 
      fields_for_nested_model(name, association, options, block) 
     end 
     end 

    end 
    end 
end 
0

在指標檢查出index選擇

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

如果表單提交這將產生

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

,則params將包括像

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

我不得不使用指數期權,讓我多下拉菜單上班。祝你好運。

1

我知道這是有點晚了,但我最近不得不這樣做,你可以得到fields_for的指數這樣

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

我希望這有助於:)