2016-07-20 24 views
0

我在新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 %> 

此代碼工作正常,如果我刪除建設者PARAM。下面是來自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(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 

它看起來好像在尋找collection屬性*args列表中的第二個屬性。但它是第一個。如果我通過field作爲第一個參數,但是我得到Stack Level Too Deep

+0

嘗試'超(* args)'而不是 –

+0

它試過了。用結果更新問題。 – AKWF

回答

2

super沒有參數列表重新發送當前消息,在超類啓動消息分派,傳遞與傳遞給當前方法的參數完全相同的參數。

在你的情況下,參數傳遞給當前的方法是(field, *args),所以super不帶參數列表將沿着(field, *args)傳球,可惜沒有super參數列表裏面define_method不起作用,所以你必須傳遞下去參數明確使用super(field, *args)

這將調用在超類中傳遞name的名稱的方法,傳遞的順序爲(field, *args),就好像您在沒有參數列表的情況下調用了super一樣。

Looking at the code, I'm not sure how to change it.

簡單:因爲super沒有一個參數列表隱含沿參數傳遞,正是因爲他們獲得通過,相當於明確是把剛纔複製&從方法定義的參數列表粘貼到參數列表super。在這種情況下,方法定義爲define_method(name) do |field, *args| … end,因此參數列表爲(field, *args),您只需將其複製到參數列表supersuper(field, *args)

它可能或不可能(和期望)通過不同參數,根據該方法如何設計,以及如何處理這些論點,但這種總是作品。 (換句話說,如果這不起作用,那麼使用super的原始代碼也不起作用。唯一的例外是當你想傳遞一個塊並且你沒有將該塊捕獲到Proc,您將不得不修改方法簽名以添加&blk參數。)

+0

我試着通過'''field',* args''',但不幸的是這段代碼顯然不能在ruby> ='''2.1''上運行。顯式傳遞參數只會給出一個'''Stack Level Too Deep'''錯誤。所以沒有辦法讓這個舊的2.3應用程序運行在新版本的ruby上。 – AKWF

+0

我特別欣賞最後一句話。那時候我想過那個。 –