Veamos un ejemplo de uso de included .
En Ruby no existe una palabra abstract que indique que un método es abstracto. Creemos una:
[~/Chapter7ClassesAndModules/inheritance]$ cat abstract.rb module Abstract def self.included(base) base.extend(ClassMethods) end module ClassMethods def abstract_methods(*args) args.each do |name| class_eval(<<-CHUCHU) def #{name}(*args) raise NotImplementedError.new("You must implement #{name}.") end CHUCHU end # args.each end # def abstract_methods end # module ClassMethods end class Tutu include Abstract abstract_methods :foo, :bar end
[~/Chapter7ClassesAndModules/inheritance]$ pry [1] pry(main)> require './abstract' => true [2] pry(main)> z = Tutu.new => #<Tutu:0x007f9bde11ac70> [3] pry(main)> z.bar NotImplementedError: You must implement bar. from (eval):2:in `bar' [4] pry(main)>
[~/src/ruby/ruby_best_practices/chapter3_mastering_the_dynamic_toolkit/tracking_mixins(master)]$ cat including_class_and_instance_methods.rb module MyFeatures module ClassMethods def say_hello "Hello" end def say_goodbye "Goodbye" end end def say_hello "Hello from #{self}!" end def say_goodbye "Goodbye from #{self}" end end class A include MyFeatures extend MyFeatures::ClassMethods end # List instance methods puts A.public_instance_methods.select { |m| m =~/say/ }.inspect # [:say_hello, :say_goodbye] # List class methods puts A.methods.select { |m| m =~/say/ }.inspect # [:say_hello, :say_goodbye] puts A.say_hello # Hello puts A.new.say_hello # Hello from #<A:0x007fb8c38880f0>!
included is a callback invoked whenever the receiver is included in another module or class. Por ejemplo:
[~/chapter8ReflectionandMetaprogramming]$ pry [1] pry(main)> module A [1] pry(main)* def A.included(mod) [1] pry(main)* puts "#{self} included in #{mod}" [1] pry(main)* end [1] pry(main)* end => :included [2] pry(main)> module Enumerable [2] pry(main)* include A [2] pry(main)* end A included in Enumerable
Sigue la solución:
[~/src/ruby/ruby_best_practices/chapter3_mastering_the_dynamic_toolkit/tracking_mixins(master)]$ cat including_class_and_instance_methods2.rb module MyFeatures module ClassMethods def say_hello "Hello" end def say_goodbye "Goodbye" end end def self.included(base) # set the hook base.extend(ClassMethods) end def say_hello "Hello from #{self}!" end def say_goodbye "Goodbye from #{self}" end end class A include MyFeatures # Now only one include is needed end # List instance methods puts A.public_instance_methods.select { |m| m =~/say/ }.inspect # [:say_hello, :say_goodbye] # List class methods puts A.methods.select { |m| m =~/say/ }.inspect # [:say_hello, :say_goodbye] puts A.say_hello # Hello puts A.new.say_hello # Hello from #<A:0x007fb8c38880f0>!
Casiano Rodriguez León 2015-01-07