简体   繁体   English

Ruby 执行class中的代码继承到

[英]Ruby execute code in class getting inherited to

I'm trying to be able to have a global exception capture where I can add extra information when an error happens.我正在尝试能够进行全局异常捕获,以便在发生错误时添加额外信息。 I have two classes, "crawler" and "amazon".我有两个班级,“爬虫”和“亚马逊”。 What I want to do is be able to call "crawl", execute a function in amazon, and use the exception handling in the crawl function.我想要做的是能够调用“抓取”,在亚马逊中执行 function,并在抓取 function 中使用异常处理。

Here are the two classes I have:这是我的两个课程:

require 'mechanize'

class Crawler
  Mechanize.html_parser = Nokogiri::HTML

  def initialize
    @agent = Mechanize.new
  end

  def crawl
    puts "crawling"

    begin
      #execute code in Amazon class here?
    rescue Exception => e
      puts "Exception: #{e.message}"
      puts "On url: #{@current_url}"
      puts e.backtrace
    end
  end

  def get(url)
    @current_url = url
    @agent.get(url)
  end
end

class Amazon < Crawler
  #some code with errors
  def stuff
    page = get("http://www.amazon.com")
    puts page.parser.xpath("//asldkfjasdlkj").first['href']
  end
end

a = Amazon.new
a.crawl

Is there a way I can call "stuff" inside of "crawl" so I can use that exception handling over the entire stuff function?有没有一种方法可以在“爬网”中调用“东西”,这样我就可以对整个东西 function 使用该异常处理? Is there a better way to accomplish this?有没有更好的方法来完成这个?

EDIT: This is when I ended up doing编辑:这是我结束的时候

require 'mechanize'

class Crawler
  Mechanize.html_parser = Nokogiri::HTML

  def initialize
    @agent = Mechanize.new
  end

  def crawl
    yield
  rescue Exception => e
    puts "Exception: #{e.message}"
    puts "On url: #{@current_url}"
    puts e.backtrace
  end

  def get(url)
    @current_url = url
    @agent.get(url)
  end
end

c = Crawler.new

c.crawl do
  page = c.get("http://www.amazon.com")
  puts page.parser.xpath("//asldkfjasdlkj").first['href']
end

I managed to get the desired functionality with "super" and a placeholder function. Is there still a better way to do this?我设法通过“super”和占位符 function 获得了所需的功能。还有更好的方法吗?

require 'mechanize'

class Crawler
  Mechanize.html_parser = Nokogiri::HTML

  def initialize
    @agent = Mechanize.new
  end

  def stuff
  end

  def crawl
    stuff
  rescue Exception => e
    puts "Exception: #{e.message}"
    puts "On url: #{@current_url}"
    puts e.backtrace
  end

  def get(url)
    @current_url = url
    @agent.get(url)
  end
end

class Amazon < Crawler
  #some code with errors
  def stuff
    super
    page = get("http://www.amazon.com")
    puts page.parser.xpath("//asldkfjasdlkj").first['href']
  end
end

a = Amazon.new
a.crawl

You could have crawl accept a code block:你可以让 crawl 接受一个代码块:

def crawl
  begin
    yield
  rescue Exception => e
    # handle exceptoin
  end
end

def stuff
  crawl do
    # implementation of stuff
  end
end

I'm not crazy about having a method with no body.我对没有身体的方法并不疯狂。 A code block might make more sense here.代码块在这里可能更有意义。 May also eliminate the need for subclassing depending on what you want to do.还可以根据您想要执行的操作消除子类化的需要。

If you want it another way, take a look at "strategy" design patten:如果您想要另一种方式,请查看“策略”设计模式:

# test_mach.rb
require 'rubygems'
require 'mechanize'

# this is the context class,which calls the different strategy implementation
class Crawler
  def initialize(some_website_strategy)
    @strategy = some_website_strategy
  end

  def crawl
    begin
      @strategy.crawl
      #execute code in Amazon class here?
    rescue Exception => e
      puts "==== starts this exception comes from Parent Class"
      puts e.backtrace
      puts "==== ends  this exception comes from Parent Class"
    end
  end
end

# strategy class for Amazon
class Amazon
  def crawl
    puts "now crawling amazon"
    raise "oh ... some errors when crawling amazon"
  end
end

# strategy class for taobao.com 
class Taobao
  def crawl
    puts "now crawling taobao"
    raise "oh ... some errors when crawling taobao"
  end
end

then run this code:然后运行这段代码:

amazon = Crawler.new(Amazon.new)
amazon.crawl
taobao = Crawler.new(Taobao.new)
taobao.crawl

result:结果:

now crawling amazon
==== starts this exception comes from Parent Class
test_mach.rb:27:in `crawl'
test_mach.rb:13:in `crawl'
test_mach.rb:38
==== ends  this exception comes from Parent Class
now crawling taobao
==== starts this exception comes from Parent Class
test_mach.rb:34:in `crawl'
test_mach.rb:13:in `crawl'
test_mach.rb:40
==== ends  this exception comes from Parent Class

BTW.顺便提一句。 for your implementation, basically I did the same way with you.对于你的实施,基本上我对你做了同样的事情。 except除了

# my implementation
class Crawler
  def stuff
    raise "abstract method called"
  end
end 

If you want it another way, take a look at "around alias" (<< metaprogramming ruby>>, page 155 ).如果您想要另一种方式,请查看“around alias”(<< metaprogramming ruby>>,第 155 页)。 However I think "around alias" is the revert case from strategy.但是我认为“围绕别名”是策略的还原案例。

( I mean, ( 我是说,

  • in strategy pattern, you at first implement the "context" class, then you need to implement the "strategy" class.在策略模式中,你首先实现“上下文”class,然后你需要实现“策略”class。
  • but in "around alias" spell, you need to first of all get an "strategy" implemented, then you write a new class that "around alias" the "strategy"...但是在“around alias”拼写中,你需要首先实施一个“strategy”,然后你写一个新的 class 来“around alias”这个“strategy”......

err... hope I didn't make you confused ^_^ )呃...希望我没有让你感到困惑^_^)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM