を引き起こしている私は、フォームビルダのサブクラスを持ってdefine_methodは無限再帰
helpers.each do |name|
# We don't want to have a label for a hidden field
# ERROR: The call to super below is actually calling itself and causing infinite recursion.
# How can I get it to call
next if name=="hidden_field"
define_method name do |field, *args|
options = args.detect {|argument| argument.is_a?(Hash)} || {}
build_shell(field, options) do
super(field,*args)
end
end
end
super
呼び出しが、それはブロックが定義されているコードをカプセル化のメソッドを呼び出しています!これは無限再帰を引き起こし、Stack Level Too Deep
です。
フォームビルダーインスタンス自体の変数name
で定義されているメソッドを呼び出す必要があります。
私はちょうどそのインスタンスを参照する方法がわかりません。 super
の代わりにself.send
を使用しても、依然として再帰が発生します。
class ErrorHandlingFormBuilder < ActionView::Helpers::FormBuilder
helpers = field_helpers +
%w(date_select datetime_select calendar_date_select time_select collection_select) +
%w(collection_select select country_select time_zone_select) -
%w(label fields_for)
helpers.each do |name|
# We don't want to have a label for a hidden field
next if name=="hidden_field"
define_method name do |field, *args|
ErrorPrinter.print "name: #{name}"
ErrorPrinter.print "field: #{field}"
options = args.detect {|argument| argument.is_a?(Hash)} || {}
build_shell(field, options) do
super(field,*args)
end
end
end
def build_shell(field, options)
# Capitalize the string, unless it's already been hardcoded.
options[:label] = field.to_s.humanize.gsub(/^[a-z]|\s+[a-z]/) { |a| a.upcase } unless options[:label]
options[:label].gsub!(/\w+/) { |word| CAPITALS.include?(word.upcase) ? word.upcase : word }
options[:label] += ":" unless options[:label].last==":"
@template.capture do
ErrorPrinter.print "Before"
locals = {:element => yield, :label => label(field, options[:label])}
ErrorPrinter.print "After"
if has_errors_on?(field)
locals.merge!(:error => error_message(field, options))
@template.render :partial => 'forms/field_with_errors', :locals => locals
else
@template.render :partial => 'forms/field', :locals => locals
end
end
end
def error_message(field, options)
if has_errors_on?(field)
errors = object.errors.on(field)
errors.is_a?(Array) ? errors.to_sentence : errors
else
''
end
end
def has_errors_on?(field)
!(object.nil? || object.errors.on(field).blank?)
end
end
再帰の問題はbuild_shell
のこの行を次のとおりです:
locals = {:element => yield, :label => label(field, options[:label])}
証明されたようにここで
は、私は、スタックを追跡するために入れ、いくつかのログと一緒に、その全体のコードですログによって:
XXXXXXXXX
name: collection_select
XXXXXXXXX
XXXXXXXXX
field: system_id
XXXXXXXXX
XXXXXXXXX
Before
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb collection_select start
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb object: :review
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb method: :system_id
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb collection: #<Set: {#<System id: 1, name: "Catalog"}>
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb value_method: :id
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb text_method: :name
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb options: {:include_blank=>"Select a Standard", :label=>"System:", :object=>nil}
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb html_options: {:onchange=>"new Ajax.Request('/review/makes', {asynchronous:true, evalScripts:true, method:'post', parameters:Form.serialize('text')})"}
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb collection_select end
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb to_collection_select_tag start
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb collection: #<Set: {#<System id: 1, name: "Catalog"}>
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb value_method: id
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb text_method: name
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb options: {:include_blank=>"Select a Standard", :label=>"System:"}
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb html_options: {:onchange=>"new Ajax.Request('/review/makes', {asynchronous:true, evalScripts:true, method:'post', parameters:Form.serialize('text')})"}
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb to_collection_select_tag end
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb options_from_collection_for_select start
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb collection: #<Set: {#<System id: 1, name: "Catalog"}>
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb value_method: :id
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb text_method: :name
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb selected: {:selected=>nil, :disabled=>nil}
XXXXXXXXX
XXXXXXXXX
actionpack form_options_helper.rb options_from_collection_for_select end
XXXXXXXXX
XXXXXXXXX
End options_from_collection_for_select
XXXXXXXXX
XXXXXXXXX
name: label
XXXXXXXXX
XXXXXXXXX
field: system_id
XXXXXXXXX
XXXXXXXXX
Before
XXXXXXXXX
XXXXXXXXX
name: label
XXXXXXXXX
XXXXXXXXX
field: system_id
XXXXXXXXX
XXXXXXXXX
Before
XXXXXXXXX
XXXXXXXXX
name: label
XXXXXXXXX
XXXXXXXXX
field: system_id
XXXXXXXXX
XXXXXXXXX
Before
XXXXXXXXX
XXXXXXXXX
name: label
XXXXXXXXX
XXXXXXXXX
field: system_id
XXXXXXXXX
XXXXXXXXX
Before
XXXXXXXXX
XXXXXXXXX
name: label
XXXXXXXXX
XXXXXXXXX
field: system_id
XXXXXXXXX
XXXXXXXXX
Before
XXXXXXXXX
XXXXXXXXX
name: label
XXXXXXXXX
XXXXXXXXX
field: system_id
XXXXXXXXX
XXXXXXXXX
Before
XXXXXXXXX
XXXXXXXXX
name: label
XXXXXXXXX
XXXXXXXXX
field: system_id
XXXXXXXXX
XXXXXXXXX
Before
XXXXXXXXX
'スーパーコールはコードブロックをカプセル化しているメソッドを呼び出しています! '私はそれが真実であるとは思わない。再帰的ループを表示するのに十分なスタックトレースを共有できますか? –
'build_shell'コードを共有してください。 – mudasobwa
私はあなたがウィザードを意味することを知っています。私はスーパーコールの上にプリントステートメントを置いて、Stack Level Too Deepが表示されるまで無限にプリントします。上記のコードが追加されました。 – AKWF