Ruby:扩展模块的类
我试图定义一个名为“HTML”的类来扩展Nokogiri,它使用模块 我尝试了以下方法:Ruby:扩展模块的类,ruby,class,include,module,extend,Ruby,Class,Include,Module,Extend,我试图定义一个名为“HTML”的类来扩展Nokogiri,它使用模块 我尝试了以下方法: require 'nokogiri' class HTML include Nokogiri end 及 但到目前为止,HTML类不可能继承nokogiri中的所有函数。所以像这样的东西不起作用: doc = HTML.new doc.HTML(open('http://www.google.com/search?q=tenderlove')) #的未定义方法“HTML”(NoMethodEr
require 'nokogiri'
class HTML
include Nokogiri
end
及
但到目前为止,HTML类不可能继承nokogiri中的所有函数。所以像这样的东西不起作用:
doc = HTML.new
doc.HTML(open('http://www.google.com/search?q=tenderlove'))
#的未定义方法“HTML”(NoMethodError)
有人知道我如何编写一个继承模块所有方法的类吗?Nokogiri没有任何要继承的实例方法:
irb> Nokogiri.instance_methods
#=> []
但通常,您会使用extend
% ri extend
---------------------------------------------------------- Object#extend
obj.extend(module, ...) => obj
------------------------------------------------------------------------
Adds to obj the instance methods from each module given as a
parameter.
module Mod
def hello
"Hello from Mod.\n"
end
end
class Klass
def hello
"Hello from Klass.\n"
end end
k = Klass.new
k.hello #=> "Hello from Klass.\n"
k.extend(Mod) #=> #<Klass:0x401b3bc8>
k.hello #=> "Hello from Mod.\n"
%
%里延
----------------------------------------------------------对象#扩展
对象扩展(模块,…)=>对象
------------------------------------------------------------------------
将每个模块中的实例方法作为
参数
模块模块
你好
“来自Mod的您好。\n”
结束
结束
克拉斯班
你好
“来自Klass的你好。\n”
结束
k=Klass.new
k、 你好#=>“克拉斯你好。\n”
k、 扩展(Mod)#=>#
k、 你好#=>“你好,来自国防部。\n”
%
您要做的是使用Nokogiri模块的所有类方法作为类的实例方法。这有点不标准,这就是语法不支持它的原因。大多数程序员将ruby模块用于Singleton模式——只需要一个Nokogiri,所以其他东西不应该能够使用它的方法
您可以使用UndefinedMethods进行一些黑客攻击来绕过这个问题,但是考虑到Nokogiri在后端有一些编译代码,这可能会产生未定义的bug
这并不是说你不能把电话转给Nokogiri:
# nokogiri_wrapper.rb
require 'rubygems'
require 'nokogiri'
class NokogiriWrapper
def method_missing(meth, *args, &blk)
puts "call for #{meth.inspect}, #{args}, #{blk ? "with block" : "and no block"}"
if Nokogiri.methods.include? meth.to_s
puts "forwarding to Nokogiri"
Nokogiri.send(meth, *args, &blk)
else
puts "falling back to default behaviour"
super
end
end
end
html = "<html></html>"
puts "calling Nokogiri directly"
p Nokogiri.HTML(html)
wrapper = NokogiriWrapper.new
puts "calling Nokogiri through wrapper"
p wrapper.HTML(html)
puts "calling non-Nokogiri method with wrapper"
p(begin
wrapper.scooby_dooby_doo!
rescue NoMethodError => e
[e.message, e.backtrace]
end)
#nokogiri#u wrapper.rb
需要“rubygems”
需要“nokogiri”
Nokogiriwraper类
def方法_缺失(meth、*args和blk)
将“调用#{meth.inspect}、#{args}、#{blk?”与block放在一起“:“并且没有block”}”
如果Nokogiri.methods.include?冰毒
将“转发至Nokogiri”
Nokogiri.send(meth、*args和blk)
其他的
将“退回默认行为”
超级的
结束
结束
结束
html=“”
将“直接呼叫Nokogiri”
p Nokogiri.HTML(HTML)
包装器=NokogiriWrapper.new
将“通过包装器调用Nokogiri”
p wrapper.HTML(HTML)
放置“使用包装器调用非Nokogiri方法”
p(开始
包装纸,史酷比!
救援命名错误=>e
[电子信息,电子回溯]
(完)
%ruby nokogiri_wrapper.rb
直接打电话给Nokogiri
通过包装器调用Nokogiri
调用:HTML,无块
转发至Nokogiri
使用包装器调用非Nokogiri方法
呼叫:史酷比!,没有障碍
回归违约行为
[“用于#”的未定义方法`scooby_dooby_doo!',[“nokogiri_wrapper.rb:12:in`method_missing'”,“nokogiri_wrapper.rb:29”]
这是在ruby中实现delegator模式的一种方法(另一种方法是使用delegator类之一)。Nokogiri没有任何实例方法可继承:
irb> Nokogiri.instance_methods
#=> []
但通常,您会使用extend
% ri extend
---------------------------------------------------------- Object#extend
obj.extend(module, ...) => obj
------------------------------------------------------------------------
Adds to obj the instance methods from each module given as a
parameter.
module Mod
def hello
"Hello from Mod.\n"
end
end
class Klass
def hello
"Hello from Klass.\n"
end end
k = Klass.new
k.hello #=> "Hello from Klass.\n"
k.extend(Mod) #=> #<Klass:0x401b3bc8>
k.hello #=> "Hello from Mod.\n"
%
%里延
----------------------------------------------------------对象#扩展
对象扩展(模块,…)=>对象
------------------------------------------------------------------------
将每个模块中的实例方法作为
参数
模块模块
你好
“来自Mod的您好。\n”
结束
结束
克拉斯班
你好
“来自Klass的你好。\n”
结束
k=Klass.new
k、 你好#=>“克拉斯你好。\n”
k、 扩展(Mod)#=>#
k、 你好#=>“你好,来自国防部。\n”
%
您要做的是使用Nokogiri模块的所有类方法作为类的实例方法。这有点不标准,这就是语法不支持它的原因。大多数程序员将ruby模块用于Singleton模式——只需要一个Nokogiri,所以其他东西不应该能够使用它的方法
您可以使用UndefinedMethods进行一些黑客攻击来绕过这个问题,但是考虑到Nokogiri在后端有一些编译代码,这可能会产生未定义的bug
这并不是说你不能把电话转给Nokogiri:
# nokogiri_wrapper.rb
require 'rubygems'
require 'nokogiri'
class NokogiriWrapper
def method_missing(meth, *args, &blk)
puts "call for #{meth.inspect}, #{args}, #{blk ? "with block" : "and no block"}"
if Nokogiri.methods.include? meth.to_s
puts "forwarding to Nokogiri"
Nokogiri.send(meth, *args, &blk)
else
puts "falling back to default behaviour"
super
end
end
end
html = "<html></html>"
puts "calling Nokogiri directly"
p Nokogiri.HTML(html)
wrapper = NokogiriWrapper.new
puts "calling Nokogiri through wrapper"
p wrapper.HTML(html)
puts "calling non-Nokogiri method with wrapper"
p(begin
wrapper.scooby_dooby_doo!
rescue NoMethodError => e
[e.message, e.backtrace]
end)
#nokogiri#u wrapper.rb
需要“rubygems”
需要“nokogiri”
Nokogiriwraper类
def方法_缺失(meth、*args和blk)
将“调用#{meth.inspect}、#{args}、#{blk?”与block放在一起“:“并且没有block”}”
如果Nokogiri.methods.include?冰毒
将“转发至Nokogiri”
Nokogiri.send(meth、*args和blk)
其他的
将“退回默认行为”
超级的
结束
结束
结束
html=“”
将“直接呼叫Nokogiri”
p Nokogiri.HTML(HTML)
包装器=NokogiriWrapper.new
将“通过包装器调用Nokogiri”
p wrapper.HTML(HTML)
放置“使用包装器调用非Nokogiri方法”
p(开始
包装纸,史酷比!
救援命名错误=>e
[电子信息,电子回溯]
(完)
%ruby nokogiri_wrapper.rb
直接打电话给Nokogiri
通过包装器调用Nokogiri
调用:HTML,无块
转发至Nokogiri
使用包装器调用非Nokogiri方法
呼叫:史酷比!,没有障碍
回归违约行为
[“用于#”的未定义方法`scooby_dooby_doo!',[“nokogiri_wrapper.rb:12:in`method_missing'”,“nokogiri_wrapper.rb:29”]
这是在ruby中实现delegator模式的一种方法(另一种方法是使用一个delegator类)