簡體   English   中英

Rails 3:a​​lias_method_chain仍在使用嗎?

[英]Rails 3: alias_method_chain still used?

我只是在閱讀有關Rails 3的Gems / Plugin開發的知識,並且發現這篇帖子說alias_method_chain已不再使用。 我可以在activesupport-3.0.0 / lib / active_support / core_ext / module / aliasing.rb中看到該方法。

我應該在Rails 3中仍然使用alias_method_chain嗎?

難道還反映在Rails 3的是要修改的ActiveRecord寶石/插件的最佳實踐?

不,它已被模塊中方法重寫和super關鍵字的巧妙使用所取代。

基本上,您可以在包含的模塊中定義原始功能,然后在另一個包含的模塊中覆蓋它。 當您在覆蓋函數中調用super時,它將調用原始函數。 但是有一個陷阱。 您必須包含基礎模塊之后並按照您希望鏈接發生的順序來包含擴展模塊。

class Something
  module Base  
    def my_method
      # (A) original functionality
    end
  end

  module PreExtension
    def my_method
      # (B) before the original
      super # calls whatever was my_method before this definition was made
    end
  end

  module PostExtension
    def my_method
      super # calls whatever was my_method before this definition was made
      # (C) after the original
    end
  end

  include Base # this is needed to place the base methods in the inheritance stack
  include PreExtension # this will override the original my_method
  include PostExtension # this will override my_method defined in PreExtension
end

s = Something.new
s.my_method 
#=> this is a twice extended method call that will execute code in this order:
#=> (B) before the original
#=> (A) the original
#=> (C) after the original

Railscasts的 Ryan Bates討論了如何在Rails路由代碼中使用它 我建議您觀看它以及他的其他截屏視頻。 他們有權將編織的祖母轉變為Rails大師。

PS: 感謝Peeja糾正我的原始答案中的一個基本錯誤。 謝謝。

通常,模塊永遠不能覆蓋其包含的類中的方法。這是因為模塊包含的工作就像子類化。 一個超類也不能覆蓋其子類的方法,也不會期望它。

當模塊包含在類中時,該模塊將在該類的祖先鏈中緊隨該類之后插入。 類中調用super將調用模塊的實現。

class Something
  module PreExtension; end
  module PostExtension; end

  include PreExtension
  include PostExtension
end

Something.ancestors # => [Something, Something::PostExtension, Something::PreExtension, Object, Kernel]

每當在Something上調用方法時,Ruby都會按順序瀏覽此列表並調用找到的第一個實現。 如果實現調用super ,它將繼續查找並找到下一個。

這意味着后面包含的模塊優先於前面包含的模塊,並且可以調用super獲得早期模塊的實現。 這是因為將包含的模塊直接在之后插入到祖先鏈中。 這是Edgerunner提到的路由代碼的工作方式。 該代碼將所有內容放入模塊,如下所示:

class SomethingNew
  module Base
    def my_method
      puts "(A)"
    end
  end

  module Extension
    def my_method
      puts "(B)"
      super
    end
  end

  include Base
  include Extension
end

SomethingNew.new.my_method
# Output:
# >> (B)
# >> (A)

SomethingNew.ancestors # => [SomethingNew, SomethingNew::Extension, SomethingNew::Base, Object, Kernel]

這就是為什么alias_method_chain首先存在的原因。 如果不能將基本代碼放入模塊中,則不確定如何完成等效的alias_method_chain

我看到在Rails 3.0.0中不再存在alias_method_chain http://api.rubyonrails.org/不報告它,而rails console報告它是undefined local variable or method

另請參見-https: //rails.lighthouseapp.com/projects/8994/tickets/285-alias_method_chain-limits-extensibility#ticket-285-20

更新:正如@ecoologic在評論中指出的那樣,Rails 3.1.1中仍然存在alias_method_chain

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM