模块中的机械化,名称错误“代理”

Mechanize in Module, Nameerror ' agent'

寻求有关如何修复此错误并重构此代码以改进它的建议。

require 'mechanize'
require 'pry'
require 'pp'




module Mymodule
  class WebBot 

    agent = Mechanize.new { |agent| 
        agent.user_agent_alias = 'Windows Chrome'
    }

    def form(response)
      require "addressable/uri"
      require "addressable/template"
      template = Addressable::Template.new("http://www.domain.com/{?query*}")
      url = template.expand({"query" => response}).to_s
      page = agent.get(url)  
    end 

    def get_products
      products = []
      page.search("datatable").search('tr').each do |row|
        begin
          product =  row.search('td')[1].text
        rescue => e
            p e.message
        end
        products << product
      end  
      products
    end  
  end 
end

调用模块:

response = {size: "SM", color: "BLUE"}

t = Mymodule::WebBot.new
t.form(response)
t.get_products

错误:

NameError: undefined local variable or method `agent'

Ruby 有一个命名约定。 agent 是 class 范围内的 局部变量 。要使其对其他方法可见,您应该通过将其命名为 @@agent 使其成为 class 变量 ,并且它将在 [= 的所有对象之间共享15=]。不过,首选方法是将其命名为 @agent,使其成为 实例变量 WebBot 的每个对象都会有自己的 @agent。但是你应该把它放在 initialize 中,当你使用 new

创建一个新对象时, initialize 将被调用
class WebBot
  def initialize
    @agent = Mechanize.new do |a|
      a.user_agent_alias = 'Windows Chrome'
    end
  end
.....

page也会出现同样的错误。您在 form 中将其定义为 局部变量 。当 form 完成执行时,它将被删除。你应该使它成为一个实例变量。幸运的是,您不必将它放在 initialize 中。您可以在 form 中定义它。对象在调用 form 后将拥有自己的 @page。在 form:

中执行此操作
def form(response)
  require "addressable/uri"
  require "addressable/template"
  template = Addressable::Template.new("http://www.domain.com/{?query*}")
  url = template.expand({"query" => response}).to_s
  @page = agent.get(url)  
end 

并且记得将每次出现的 pageagent 更改为 @page@agent。例如,在您的 get_products 中:

def get_products
  products = []
  @page.search("datatable").search('tr').each do |row|
  .....

这些更改将解决名称错误。顺便说一句,重构是另一个故事。