如何更改此超级调用以显式传递参数?
How can I change this super call to pass the arguments explicitly?
我是新 VM 上的 运行 遗留 Rails 2.3
(是的,我知道)应用程序。是 运行 Ruby v2.3.1
。我已完成所有建议的更改,以便在此版本上获得此旧应用程序 运行。除了这段代码外,一切都运行得很好,而且速度更快。此代码来自 Advanced Recipes for Rails
旧书并且是 error_handling_form_builder.rb
.
首先,这是表单声明:
<% form_for(:review, :builder => ErrorHandlingFormBuilder) do |f| %>
<%= f.collection_select :system_id, @systems, :id, :name, { :include_blank => "Select a Standard"}, { :onchange => remote_function(:url => { :action => :makes }, :submit => :text, :method => 'post') } %>
<div id="categoriesdiv">
</div>
<% end %>
如果我删除构建器参数,此代码可以正常工作。这是来自 ErrorHandlingFormBuilder
:
的代码
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|
options = args.detect {|argument| argument.is_a?(Hash)} || {}
build_shell(field, options) do
super # This call fails
end
end
end
上面对 super
的调用失败并出现以下错误:
implicit argument passing of super from method defined by define_method()
is not supported. Specify all arguments explicitly.
看了代码,不知道怎么改。
我知道我必须用显式参数调用 super,但我试过这个:
super(field, options)
我得到:
wrong number of arguments (given 2, expected 4..6)
我也试过:
build_shell(field, options) do
super(*args)
end
但我得到:
undefined method `map' for :id:Symbol
Did you mean? tap
它似乎在寻找 *args
列表中的第 2 个 collection
属性。但它是第一个。如果我将 field
作为第一个参数传递,我会得到 Stack Level Too Deep
.
super
没有参数列表重新发送当前消息,在超类中开始消息调度,传递与传递给当前方法的完全相同的参数。
在您的情况下,传递给当前方法的参数是 (field, *args)
,因此没有参数列表的 super
会传递 (field, *args)
,但不幸的是 super
没有参数列表在 define_method
中不起作用,因此您必须使用 super(field, *args)
.
显式传递参数
这将在传递 (field, *args)
的超类中调用由 name
给出的名称的方法,就像您在没有参数列表的情况下调用 super
一样。
Looking at the code, I'm not sure how to change it.
简单:因为没有参数列表的 super
会隐式传递参数,与传递的参数完全一样,explicit 等同于复制并粘贴参数列表从方法定义到 super
的参数列表。在这种情况下,方法定义是 define_method(name) do |field, *args| … end
,因此参数列表是 (field, *args)
,您只需将其复制到 super
的参数列表中:super(field, *args)
.
传递 不同的 参数可能可行也可能不可行(并且可取),这取决于方法的设计方式以及您处理参数的方式,但这 总是 有效。 (或者,换句话说:如果这不起作用,那么仅使用 super
的原始代码也不起作用。唯一的例外是当您想要传递一个块并且您不捕获该块变成 Proc
,您将必须修改方法签名以添加 &blk
参数。)
我是新 VM 上的 运行 遗留 Rails 2.3
(是的,我知道)应用程序。是 运行 Ruby v2.3.1
。我已完成所有建议的更改,以便在此版本上获得此旧应用程序 运行。除了这段代码外,一切都运行得很好,而且速度更快。此代码来自 Advanced Recipes for Rails
旧书并且是 error_handling_form_builder.rb
.
首先,这是表单声明:
<% form_for(:review, :builder => ErrorHandlingFormBuilder) do |f| %>
<%= f.collection_select :system_id, @systems, :id, :name, { :include_blank => "Select a Standard"}, { :onchange => remote_function(:url => { :action => :makes }, :submit => :text, :method => 'post') } %>
<div id="categoriesdiv">
</div>
<% end %>
如果我删除构建器参数,此代码可以正常工作。这是来自 ErrorHandlingFormBuilder
:
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|
options = args.detect {|argument| argument.is_a?(Hash)} || {}
build_shell(field, options) do
super # This call fails
end
end
end
上面对 super
的调用失败并出现以下错误:
implicit argument passing of super from method defined by define_method()
is not supported. Specify all arguments explicitly.
看了代码,不知道怎么改。
我知道我必须用显式参数调用 super,但我试过这个:
super(field, options)
我得到:
wrong number of arguments (given 2, expected 4..6)
我也试过:
build_shell(field, options) do
super(*args)
end
但我得到:
undefined method `map' for :id:Symbol
Did you mean? tap
它似乎在寻找 *args
列表中的第 2 个 collection
属性。但它是第一个。如果我将 field
作为第一个参数传递,我会得到 Stack Level Too Deep
.
super
没有参数列表重新发送当前消息,在超类中开始消息调度,传递与传递给当前方法的完全相同的参数。
在您的情况下,传递给当前方法的参数是 (field, *args)
,因此没有参数列表的 super
会传递 (field, *args)
,但不幸的是 super
没有参数列表在 define_method
中不起作用,因此您必须使用 super(field, *args)
.
这将在传递 (field, *args)
的超类中调用由 name
给出的名称的方法,就像您在没有参数列表的情况下调用 super
一样。
Looking at the code, I'm not sure how to change it.
简单:因为没有参数列表的 super
会隐式传递参数,与传递的参数完全一样,explicit 等同于复制并粘贴参数列表从方法定义到 super
的参数列表。在这种情况下,方法定义是 define_method(name) do |field, *args| … end
,因此参数列表是 (field, *args)
,您只需将其复制到 super
的参数列表中:super(field, *args)
.
传递 不同的 参数可能可行也可能不可行(并且可取),这取决于方法的设计方式以及您处理参数的方式,但这 总是 有效。 (或者,换句话说:如果这不起作用,那么仅使用 super
的原始代码也不起作用。唯一的例外是当您想要传递一个块并且您不捕获该块变成 Proc
,您将必须修改方法签名以添加 &blk
参数。)