[ruby-on-rails] Rails : fields_for 색인 포함?
할 방법 (또는 유사한 기능을 끌어내는 방법)이 fields_for_with_index
있습니까?
예:
<% f.fields_for_with_index :questions do |builder, index| %>
<%= render 'some_form', :f => builder, :i => index %>
<% end %>
렌더링되는 부분은 현재 인덱스가 fields_for
루프 에 있는지 알아야 합니다.
답변
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 %>
답변
솔루션이 Rails 내에서 제공되므로 대답은 매우 간단합니다. f.options
매개 변수 를 사용할 수 있습니다 . 따라서 렌더링 된 _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] %>
답변
Rails 4.0.2부터 색인이 FormBuilder 객체에 포함되었습니다.
https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-fields_for
예를 들면 :
<%= form_for @person do |person_form| %>
...
<%= person_form.fields_for :projects do |project_fields| %>
Project #<%= project_fields.index %>
...
<% end %>
...
<% end %>
답변
Rails 4+ 용
<%= form_for @person do |person_form| %>
<%= person_form.fields_for :projects do |project_fields| %>
<%= project_fields.index %>
<% end %>
<% end %>
Rails 3 지원을위한 Monkey Patch
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
답변
Checkout 부분 컬렉션 렌더링 . 템플릿이 배열을 반복하고 각 요소에 대한 하위 템플릿을 렌더링해야하는 것이 요구 사항 인 경우.
<%= 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
됩니다.
도움이 되었기를 바랍니다.
답변
적어도 -v3.2.14가 아닌 Rails에서 제공하는 방법을 통해 이것을 수행하는 적절한 방법을 볼 수 없습니다.
@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]"
하므로 해당 문자열의 인덱스를 일치시키고 사용합니다.
실제로 그것을 수행하는 더 멋진 (그리고 아마도 더 깨끗한?) 방법은 람다를 전달하고 그것을 증가하도록 호출하는 것입니다.
# /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 %>
답변
나는 이것이 조금 늦었다는 것을 알고 있지만 최근에 이것을해야했습니다. 이러한 fields_for의 색인을 얻을 수 있습니다.
<% f.fields_for :questions do |builder| %>
<%= render 'some_form', :f => builder, :i => builder.options[:child_index] %>
<% end %>
도움이 되었기를 바랍니다. 🙂