2009-07-01 2 views
1

Я пытаюсь определить класс под названием «HTML» до extend Nokogiri - который использует модули.Ruby: класс, расширяющий модуль

Я попытался следующие:

require 'nokogiri' 

class HTML 
    include Nokogiri 
end 

и

require 'nokogiri' 

class HTML 
    extend Nokogiri 
end 

но до сих пор это было невозможно, что класс HTML наследует все функции в nokogiri. Так как материал не работает:

doc = HTML.new 
doc.HTML(open('http://www.google.com/search?q=tenderlove')) 

неопределенный метод `HTML» для # (NoMethodError)

Кто-нибудь знает, как мне удалось запрограммировать класс, который наследует все методы модуля?

ответ

10

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" 

% 

То, что вы хотите сделать, это использовать все методы класса в Nokogiri модуль как метод экземпляра вашего класса. Это немного нестандартно, поэтому синтаксис не поддерживает его. Большинство программистов используют модули ruby ​​для шаблона Singleton - там должен быть только один Nokogiri, поэтому другие вещи не должны использовать его методы.

Вы можете сделать некоторые хаки с помощью UndefinedMethods, чтобы обойти это, но учитывая, что у Nokogiri есть скомпилированный код в бэкэнд, это может вызвать неопределенные ошибки.

Что не сказать, что вы не можете переадресовать звонки 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) 
 
% ruby nokogiri_wrapper.rb 
calling Nokogiri directly 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
<html></html> 

calling Nokogiri through wrapper 
call for :HTML, <html></html>, and no block 
forwarding to Nokogiri 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
<html></html> 

calling non-Nokogiri method with wrapper 
call for :scooby_dooby_doo!, , and no block 
falling back to default behaviour 
["undefined method `scooby_dooby_doo!' for #<NokogiriWrapper:0x581f74>", ["nokogiri_wrapper.rb:12:in `method_missing'", "nokogiri_wrapper.rb:29"]] 

Это один из способов реализации шаблона доверителя в рубине (другой способ заключается в использовании одного доверителя классы).

+0

Спасибо за это. – Benjamin

 Смежные вопросы

  • Нет связанных вопросов^_^