34 votes

Rails 3: alias_method_chain toujours utilisé?

Je viens de lire sur les pierres précieuses/développement d'un Plugin pour Rails 3 et couru à travers ce post qui dit que alias_method_chain n'est plus utilisé. Je peux voir la méthode est toujours là dans activesupport-3.0.0/lib/active_support/core_ext//module de l'aliasing.rb.

Dois-je toujours utiliser alias_method_chain dans Rails 3?

Est ce toujours le reflet de l'meilleures pratiques pour les gemmes/plugins dans Rails 3, que voulez modifier ActiveRecord?

57voto

edgerunner Points 9581

Non, il a été remplacé par une utilisation habile de la redéfinition de méthode dans les modules et l' super mot-clé.

Fondamentalement, vous définissez la fonction d'origine dans un module, et l'écraser dans un autre module. Lorsque vous appelez super dans la fonction dominante, il appelle la fonction d'origine. Mais il ya un hic. Vous devez inclure l'extension de modules après , y compris le module de base, et dans l'ordre que vous voulez que le chaînage de se produire.

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

Ryan Bates de Railscasts parle de comment il est utilisé dans les Rails code de Routage. Je vous recommande de le regarder, et de ses autres vidéos explicatives. Ils ont le pouvoir de transformer un tricot de grand-mère dans un Rails de gourou.

PS: le Crédit va à Peeja pour la correction d'une erreur fondamentale dans ma réponse originale à cette question. Merci.

19voto

Peeja Points 2406

En général, un module ne peut jamais remplacer une méthode dans la classe il est inclus dans l'. C'est parce que le module de l'inclusion fonctionne comme le sous-classement. Une super-classe ne pouvez pas remplacer ses sous-classes" méthodes soit, ni voulez-vous attendre d'elle.

Lorsqu'un module est inclus dans une classe, le module est inséré juste après la classe dans la classe de l'ancêtre de la chaîne. L'appel super de la classe va appeler le module demise en œuvre.

class Something
  module PreExtension; end
  module PostExtension; end

  include PreExtension
  include PostExtension
end

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

Chaque fois qu'une méthode est appelée sur un Something, Ruby on regarde à travers cette liste dans l'ordre et appelle la mise en œuvre d'abord qu'il trouve. Si la mise en œuvre des appels d' super, il ne cesse de regarder et trouve à la prochaine.

Cela signifie que les modules inclus par la suite, prendre la priorité sur modules inclus plus tôt, et peut appeler super pour obtenir le plus tôt des modules de mise en œuvre. C'est parce que les modules sont inclus inséré dans l'ancêtre de la chaîne d' directement après la classe. Cette est de savoir comment le code de routage edgerunner mentionné œuvres. Ce code met tout dans des modules, comme suit:

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]

C'est pourquoi, alias_method_chain existe, en premier lieu. Si mettre la base de code dans un module n'est pas une option, je ne suis pas sûr de la façon de réaliser l'équivalent d' alias_method_chain.

0voto

Vikrant Chaudhary Points 4306

Je vois qu' alias_method_chain n'est plus présent dans les Rails 3.0.0. http://api.rubyonrails.org/ ne pas le signaler et rails console rapports pour être undefined local variable or method.

Voir Également - https://rails.lighthouseapp.com/projects/8994/tickets/285-alias_method_chain-limits-extensibility#ticket-285-20

Mise à JOUR: Comme le fait remarquer @ecoologic dans les commentaires, alias_method_chain est toujours présent dans les Rails 3.1.1.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X