1

尋找有關如何解決此錯誤的建議,並重構此代碼以改進它。模塊中的機械化,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' 

回答

2

Ruby有一個命名約定。 agent是類範圍內的局部變量。爲了讓其他方法可見,您應該將其命名爲10類變量,並將其命名爲@@agent,並且它將在WebBot的所有對象中共享。但是,首選的方法是通過將其命名爲@agent來使其成爲實例變量WebBot的每個對象都將擁有自己的@agent。但是,你應該把它放在initialize,當你創建一個新的對象與new

class WebBot 
    def initialize 
    @agent = Mechanize.new do |a| 
     a.user_agent_alias = 'Windows Chrome' 
    end 
    end 
..... 

而且會發生page相同的錯誤initialize將被調用。您在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| 
    ..... 

這些更改將解決名稱錯誤。重構是另一個故事順便說一句。

+0

儘管名稱錯誤,而不是語法錯誤。 – pguardiario

+0

是的。完全正確。我要解決它。 –

+0

工程,很好,謝謝。有關清理代碼的任何建議? – user2012677