2017-04-06 90 views
1

我有一個方法在我的CLI應用程序中給我一個錯誤。未定義的方法`attr'爲零:NilClass(NoMethodError)

的方法是:

def self.deal_page(input, product_url) 
    self.open_deal_page(input) 
    deal = {} 
    html = open(@product_url) 
    doc = Nokogiri::HTML(html) 
    data = doc.text.strip 
    deal[:name] = doc.css("h1").text.strip 
    deal[:discription] = doc.css(".textDescription").text.strip 
    @purchase_link = nil 
    @purchase_link= doc.at_css("div.detailLeftColumn a.success").attr("href") 
     if @purchase_link.nil? 
     deal[:purchase] = @product_url 
     else 
     deal[:purchase] = @purchase_link 
     end 
    deal 
    end 

和錯誤是:

/home/himachhag-45739/code/popular-deals-from-slickdeals.net-cli/lib/popular_deals/newdeals.rb:54:in `deal_page': undefined method `attr' for nil:NilClass (NoMethodError) 
     from /home/himachhag-45739/code/popular-deals-from-slickdeals.net-cli/lib/popular_deals/cli.rb:70:in `disply_deal'             
     from /home/himachhag-45739/code/popular-deals-from-slickdeals.net-cli/lib/popular_deals/cli.rb:49:in `menu'               
     from /home/himachhag-45739/code/popular-deals-from-slickdeals.net-cli/lib/popular_deals/cli.rb:9:in `call'               
     from /home/himachhag-45739/code/popular-deals-from-slickdeals.net-cli/bin/popular-deals:10:in `<top (required)>'             
     from /usr/local/rvm/gems/ruby-2.3.1/bin/popular-deals:22:in `load'                         
     from /usr/local/rvm/gems/ruby-2.3.1/bin/popular-deals:22:in `<main>'                        
     from /usr/local/rvm/gems/ruby-2.3.1/bin/ruby_executable_hooks:15:in `eval'                       
     from /usr/local/rvm/gems/ruby-2.3.1/bin/ruby_executable_hooks:15:in `<main>' 

我試過xpathat_cssunlessif .. else,但於事無補。另外,我不會每次都得到這個錯誤,但我想擺脫它。

+1

當遇到像這樣的'nil'問題時,退一步操作並查看未能參與的操作非常重要。它看起來像'doc.at_css(...)'沒有找到任何東西。另外需要注意的是試着保持縮進一致。那條'如果'條款被推到那裏,就像它被滑出了一樣。 – tadman

+0

@tadman非常感謝您的建議。我同意你的看法,就像doc.at_css(...)沒有找到任何東西。但如果我再次嘗試尋找相同的交易,它確實給了我輸出!我不明白。我也會更加註意縮進。 –

+0

歡迎來到SO。請閱讀「[mcve]」和鏈接頁面。您需要提供允許我們確認問題的代碼。目前我們不能這樣做,因爲您沒有告訴我們如何調用您的方法。 –

回答

4

一種方法是有點偏執:

@purchase_link = doc.at_css("div.detailLeftColumn a.success").try(:attr, "href") 

deal[:purchase] = @purchase_link || @product_url 

幾件事情要牢記在這裏。在紅寶石只有nilfalse邏輯上是錯誤的,所以它是非常罕見的,你需要專門測試nil?的東西。唯一必要的情況是,當你想區分nilfalse時,你可以想象它並不經常。

因此,在這種情況下,無論您是使用at_css還是未使用,在這種情況下try調用都不會執行任何操作。如果它發現某個try呼叫繼續進行另一個呼叫。然後,您可以使用簡單的||(或)運算符來執行任務,以優先選擇它們。

另一件事是因爲這段代碼是在一個類的方法裏面,隨便使用實例變量可能會有麻煩。如果僅在此方法中使用purchase_link之類的內容,請刪除使其持久化的@

另一件事要小心的是如何你的方法被定義爲:

def self.deal_page(input, product_url) 

聲明參數product_url,但裏面:

html = open(@product_url) 

此引用類實例變量@product_url這是不一樣。您可能在這裏調用了錯誤的變量open

+2

請注意'.try()'是[Rails](https://apidock.com/rails/v3.2.1/Object/try)方法,而不是核心Ruby方法。 '[安全導航運算符](http://stackoverflow.com/questions/36812647/what-does-ampersand-dot-mean-in-ruby)與'doc.at_css()&。attr() '。 – anothermh

+0

2.3引入了安全導航操作符,它實際上比'try'更加連貫。我忘了這是Rails的具體。 – tadman

+1

@tadman此解決方案的工作原理!我非常感謝你的時間和建議。 –

0

當你的堆棧跟蹤顯示該行導致該錯誤:

@purchase_link= doc.at_css("div.detailLeftColumn a.success").attr("href") 

attr方法不能在零調用。查看元素是否存在於HTML中。

您可以通過打印的

doc.at_css("div.detailLeftColumn a.success") 

值對於您可以參考http://www.nokogiri.org/tutorials/更多信息調試此。爲解決這一問題

0

此處,我認爲這個問題是:

def self.deal_page(input, product_url) 
    ... 
    html = open(@product_url) 

您使用product_url作爲參數,而是試圖打開@product_url

open不會在這個方法產生一個錯誤,如果@product_url爲空或爲零,所以@product_url必須預先地方,但很明顯。我懷疑這不是你認爲的頁面,因此選擇器失敗。

你在你的代碼中的其他問題:

deal[:name] = doc.css("h1").text.strip 
deal[:discription] = doc.css(".textDescription").text.strip 

您使用css,它返回一個節點集

doc.css('h1').class # => Nokogiri::XML::NodeSet 

然後text其串接在節點集,這是幾乎總是所有文字不是你想做什麼。試想一下:

require 'nokogiri' 

doc = Nokogiri::HTML(DATA.read) 
doc.css('h1').text # => "foobar" 
doc.css('h1').map(&:text) # => ["foo", "bar"] 

__END__ 
<html> 
    <body> 
    <h1>foo</h1> 
    <h2>blah</h2> 
    <h1>bar</h1> 
    <h2>blah</h2> 
    </body> 
</html> 

doc.css('h1').text級聯"foo""bar"導致"foobar"。一旦發生這種情況,解開連接引起的混亂是非常困難的。

取而代之,你應該使用doc.css('h1').map(&:text),除了那罕見情況下,你知道文本實際上需要連接。我只會遇到這種情況......哦......永遠不會。

相關問題