【问题标题】:Ruby: undefined local variable or method for ClassRuby:类的未定义局部变量或方法
【发布时间】:2016-02-03 22:50:21
【问题描述】:

我认为我的控制器中有一个非常简单的方法:

class ReportsController < ApplicationController

  client = MWS.reports

  def request_all_listings
    begin
      parser = client.request_report('_GET_FLAT_FILE_OPEN_LISTINGS_DATA_', opts = {})
      @result = parser.parse["ReportRequestInfo"]["ReportProcessingStatus"]

      puts @result

    rescue Excon::Errors::ServiceUnavailable => e
      logger.warn e.response.message
      retry
    end
  end

  request_all_listings

end

这给了我错误:

 undefined local variable or method `request_all_listings' for ReportsController:Class

我在这里做错了什么?当我删除 def request_all_listings def 和 end 行并且只有开始/救援/结束时,我的代码工作正常......

【问题讨论】:

    标签: ruby


    【解决方案1】:

    request_all_listings 不明确。它可以是一个变量,也可以是一个类方法调用request_all_listings 是一个对象方法。

    要修复它,您需要将request_all_listings 定义为类方法。

    def self.request_all_listings
        ...
    end
    

    或者创建一个对象来调用request_all_listings

    ReportsController.new.request_all_listings
    

    一般来说,加载类时执行工作是一种不好的形式。这使得在没有工作的情况下加载类是不可能的,并且会减慢速度并使其难以使用和测试。

    相反,我建议在加载实例并将其缓存在 class instance variable 中时执行此工作。

    class Foo
      # class instance variable
      @all_listings = []
    
      # class method
      def self.request_all_listings
        puts "Calling request_all_listings"
        @all_listings = [1,2,3]
    
        return
      end
    
      # class method
      def self.all_listings
        request_all_listings if @all_listings.size == 0
    
        return @all_listings
      end
    
      # object method
      def all_listings
        return self.class.all_listings
      end
    end
    
    # request_all_listings is only called once for two objects
    puts Foo.new.all_listings.inspect
    puts Foo.new.all_listings.inspect
    

    【讨论】:

    • 很好,详细的回复!我对 Ruby 很陌生(我是 Node 开发人员,不要打我),这实际上是用于访问 API,因此每次加载关联视图时都需要运行它,这似乎与您的不同'在建议。是这样吗?
    • @Jascination 不,同样的事情。我猜这是Rails。 Rails(以及其他任何东西)只会在服务器启动时加载一次类,因此使用您的方法 request_all_listings 只会运行一次。 Rails(我认为)将为每个请求创建一个控制器类的实例。在 Ruby 中,一切都与对象有关。
    【解决方案2】:

    request_all_listings 行移到构造函数中:

    def initialize
        request_all_listings
    end
    

    当您创建 ReportsController 实例时,initialize 将自动运行:

    reports = ReportsController.new
    

    【讨论】:

    • 不完全确定您的意思。为什么我需要将request_all_listings 放在一个单独的方法中?如果我需要打电话给initialize,那肯定会重复问题吗?
    • @Jascination initialize,如果存在,在对象创建时自动运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    相关资源
    最近更新 更多