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