@@ -40,7 +40,9 @@ class HasManyBuilder < SimpleDelegator
4040 attr_reader :assoc
4141 attr_reader :options
4242 attr_reader :heading , :sortable_column , :sortable_start
43- attr_reader :new_record , :destroy_option
43+ attr_reader :new_records , :destroy_option
44+
45+ NewRecord = Struct . new ( :object , :text )
4446
4547 def initialize ( has_many_form , assoc , options )
4648 super has_many_form
@@ -70,11 +72,32 @@ def extract_custom_settings!(options)
7072 @heading = options . key? ( :heading ) ? options . delete ( :heading ) : default_heading
7173 @sortable_column = options . delete ( :sortable )
7274 @sortable_start = options . delete ( :sortable_start ) || 0
73- @new_record = options . key? ( :new_record ) ? options . delete ( :new_record ) : true
75+ @new_records = extract_new_records ( options )
7476 @destroy_option = options . delete ( :allow_destroy )
7577 options
7678 end
7779
80+ def extract_new_records ( options )
81+ Array . wrap ( options . fetch ( :new_record , { } ) ) . flat_map do |new_record |
82+ option =
83+ case new_record
84+ when false
85+ next [ ]
86+ when Hash
87+ new_record
88+ when String
89+ { text : new_record }
90+ else
91+ { object : new_record }
92+ end
93+ object = option . fetch ( :object , assoc_klass . new )
94+ [ NewRecord . new (
95+ object ,
96+ option . fetch ( :text , I18n . t ( 'active_admin.has_many_new' , model : object . class . model_name . human ) )
97+ ) ]
98+ end
99+ end
100+
78101 def default_heading
79102 assoc_klass . model_name .
80103 human ( count : ::ActiveAdmin ::Helpers ::I18n ::PLURAL_MANY_COUNT )
@@ -93,7 +116,7 @@ def content_has_many(&block)
93116 contents = without_wrapper { inputs ( options , &form_block ) }
94117 contents ||= "" . html_safe
95118
96- js = new_record ? js_for_has_many ( options [ :class ] , &form_block ) : ''
119+ js = js_for_has_many ( options [ :class ] , &form_block )
97120 contents << js
98121 end
99122
@@ -156,19 +179,20 @@ def without_wrapper
156179
157180 # Capture the ADD JS
158181 def js_for_has_many ( class_string , &form_block )
159- assoc_name = assoc_klass . model_name
160- placeholder = "NEW_#{ assoc_name . to_s . underscore . upcase . gsub ( /\/ / , '_' ) } _RECORD"
161- opts = {
162- for : [ assoc , assoc_klass . new ] ,
163- class : class_string ,
164- for_options : { child_index : placeholder }
165- }
166- html = template . capture { __getobj__ . send ( :inputs_for_nested_attributes , opts , &form_block ) }
167- text = new_record . is_a? ( String ) ? new_record : I18n . t ( 'active_admin.has_many_new' , model : assoc_name . human )
168-
169- template . link_to text , '#' , class : "button has_many_add" , data : {
170- html : CGI . escapeHTML ( html ) . html_safe , placeholder : placeholder
171- }
182+ template . safe_join ( new_records . map do |new_record |
183+ assoc_name = assoc_klass . model_name
184+ placeholder = "NEW_#{ assoc_name . to_s . underscore . upcase . gsub ( /\/ / , '_' ) } _RECORD"
185+ opts = {
186+ for : [ assoc , new_record . object ] ,
187+ class : class_string ,
188+ for_options : { child_index : placeholder }
189+ }
190+ html = template . capture { __getobj__ . send ( :inputs_for_nested_attributes , opts , &form_block ) }
191+
192+ template . link_to new_record . text , '#' , class : "button has_many_add" , data : {
193+ html : CGI . escapeHTML ( html ) . html_safe , placeholder : placeholder
194+ }
195+ end )
172196 end
173197
174198 def wrap_div_or_li ( html )
0 commit comments