2012-01-16 71 views
2

我想我明白爲什麼會發生這種情況,但我不確定如何解決問題。NoMethodError:未定義的方法`methodname'爲#<內存位置>

我會在下面發佈相關代碼。

class CoveragesController < ApplicationController 
    def grab 
    url = { 
     "cnn" => "http://www.cnn.com/", 
     "cnn_politics" => "http://www.cnn.com/POLITICS/", 
    } 

    url.each do |key, value| 
     data = urlToString(value) 
     appearances = countAppearances(data) 
     @coverage = Coverage.create(
     :media  => key, 
     :url   => value, 
     :content  => data, 
     :obama  => appearances["obama"], 
    ) 
    end 
    end 
end 

抓取方法的作用並不重要。這只是一種使用多種其他方法來計算CNN網站提及的「奧巴馬」時間數量的方法。

在rails控制檯中,我試圖運行Coverage.grab。這是我得到的錯誤消息。

1.9.3-p0 :003 > Coverage.grab 
NoMethodError: undefined method `grab' for #<Class:0x007f9a5d813bf8> 
    from /Users/jasonkim/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/base.rb:1088:in `method_missing' 
    from (irb):3 
    from /Users/jasonkim/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands/console.rb:45:in `start' 
    from /Users/jasonkim/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands/console.rb:8:in `start' 
    from /Users/jasonkim/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.1.3/lib/rails/commands.rb:40:in `<top (required)>' 
    from script/rails:6:in `require' 
    from script/rails:6:in `<main>' 

Coverage.new工作得很好。

此外,當我配置route.rb,並創建一個運行grab方法的地址,它也運行良好。

我猜測,當我運行Coverage.grab時,其中沒有Coverage的任何實例,對於我來說運行「grab」方法。

任何想法如何解決這個問題?

回答

3

起初,你在CoverageController定義你的方法,而不是Coverage 其次,你定義一個實例方法,因此僅在類的一個實例有效。你可以這樣調用:

coverages_controller = CoveragesController.new 
coverages_controller.grab 
+0

Thanks Holger Just and everyone else。儘管Jordan和clyfe在他們的回答中是正確的,但在Rails的背景下,Holger建議似乎最適合。 – 2012-01-16 21:42:51

+1

Rails控制器並不意味着除框架以外的其他實例,並且這樣做是不好的事情。如果你想讓控制器中的抓取方法可能最多將其移動到ApplicationController(並通過繼承調用它),但最好將它放入它自己的RemoteRequest類或類似的類中,最有可能是類方法。 – clyfe 2012-01-16 22:10:22

+1

@clyfe一般而言,你是對的。 Rails控制器最好只用於Rails路由器。但總是有例外。例如。當你使用服務層時(並且不要認爲名稱層非常嚴重),那麼直接實例化和調用控制器方法可能是有意義的。儘管你必須確保你不使用'params'哈希或會話等環境信息。所以是的,大多數情況下,在通常的ActiveRecord/ActionPack之外構建服務層或模型抽象更爲明智。 – 2012-01-16 22:24:57

3

CoverageCoverageController是不一樣的東西。您已將grab定義爲類CoverageController上的實例方法,但您試圖呼叫Coverage.grab,該類是類Coverage上的類方法。

如果你想能夠調用Coverage.grab你將它定義成這樣:

class Coverage < ActiveRecord::Base 
    def self.grab 
    puts "foo" 
    end 
end 

# Usage 
>> Coverage.grab 
=> foo 

如果你想grab是在CoverageController的動作,但是,你已經正確地定義它。但它是一種實例方法,而不是類方法 - 您不能調用CoverageController.grab,因爲CoverageController是類本身,不是類的實例,並且沒有類方法grab

通常情況下,您不會直接在控制器上調用方法,而是將其留給路由器。你可以嘗試實例CoverageController的實例,例如:

>> @cc = CoverageController.new ... 
>> @cc.grab 

但除非你提供同樣的環境和參數的路由器會,這將失敗。

2

您將grab方法定義爲CoveragesController上的實例方法,然後嘗試將其稱爲Coverages類中的類方法。

您需要做的是將其定義爲Coverages類中的類方法。

class Coverages 
    def self.grab 
    # ... 
    end 
end